问题描述:
在一个项目中,下位机使用的是STM8S003F3为主芯片。在使用RS485进行与上位机通信时,会一直进入接收中断,根本未接收到上位机的正确数据。
解决过程:
一开始以为是485芯片R0引脚未上拉的缘故导致这个问题,经过将此引脚通过MCU内部上拉,问题得到缓解。程序工作也稳定了,运行了一周也没问题,所以一直以为问题解决了,结果在实地安装后,没过多久又出现了这个问题,按理说,如果是外部电磁干扰,应该是偶发,也不应该出现了就不会好起来,干扰源不可能一直都在。然后又是一个头疼的事啊。。继续找答案解决。
这时又跑去官网下载了stm8s类芯片的应用手册,重点就是它了。
原来stm8s类型芯片的UART使用时在接收中断时要注意一个过载问题,下面呢就是手册原文:
过载错误
如果RXNE还没有被复位,又接收到一个字符,则发生溢出错误。数据只有当RXNE位被清零后
才能从移位寄存器转移到RDR寄存器。
当溢出错误产生时:
● OR位被置位。
● RDR内容将不会丢失。读UART_DR寄存器仍能得到先前的数据。
● 移位寄存器中以前的内容将被覆盖。随后接收到的数据都将丢失。
● 如果RIEN位被置1,则产生中断。
顺序执行对UART_SR和UART_DR寄存器的读操作,可复位OR位。
首先STM8的UART接收中断的使能位是RIEN,而当RIEN为1的时候就会进入接收中断,而能让RIEN为1的时候是有两种情况的。
1,一个就是在接收寄存器不为空的时候。(对应的中断请求标志RXNE)
2,另一个就是上面说的过载错误了,在RXNE标志位还没有复位,又接收到一个字符,这时也会触发接收 中断。(对应的中断标志位OR)
那么我们的问题就是出现在这里了,我们在每次接收中断都会清除RXNE标志位,但是并没有清除OR标志位,故当出现一次RXNE还没有被复位,又接收到一个字符的情况也就出现了OR一直没被清除,所以就一直进入接收中断了。所以解决问题就是只要每次接收中断都需要清除RXEN和OR这两个标志位就可以解决问题了。
解决方法:
对于RXNE清零有两种方法:直接手动清零或读UART_DR寄存器就可以让RXNE清零。
对于OR清零就不能直接手动写0了,这时为了同时能清除RXNE和OR标志位,我们就使用手册上最后一句给的方案。顺序读取这两个寄存器,这样即清除了OR同时又清除了RXNE标志位。
代码:(用的stm8s lib库)
INTERRUPT_HANDLER(UART1_RX_IRQHandler, 18)
{
/* Read one byte from the receive data register */
if( UART1_GetITStatus(UART1_IT_RXNE) == SET)
{
Rxdata = UART1_ReceiveData8();
}
}
if( UART1_GetITStatus(UART1_IT_RXNE) == SET)
这句就是读取UART_SR寄存器,函数是库函数
Rxdata = UART1_ReceiveData8();
这句就是读取UART_DR寄存器,Rxdata就是自己定义接收数据的一个变量(缓存区)。函数是库函数,读 取八位数据。
至此,无限进入接收中断的问题就解决了。