▪ 现象
STM8 UART1 开启了读中断,初始化代码如下:
// 配置串口参数为:波特率115200,8位数据位,1位停止位,无校验,禁止同步传输,允许接收发送
UART1_Init((u32)115200, UART1_WORDLENGTH_8D, UART1_STOPBITS_1, UART1_PARITY_NO, UART1_SYNCMODE_CLOCK_DISABLE, UART1_MODE_TXRX_ENABLE);
// 启用 UART1 中断
// UART1_IT_RXNE_OR 表示 接收数据寄存器非空或者溢出错误时 触发中断
UART1_ITConfig(UART1_IT_RXNE_OR, ENABLE);
// 启用 UART1
UART1_Cmd(ENABLE);
当通过PC端的串口软件向 STM8 一次性发送多字节数据时(例如:01 02 03),那么STM8就会一直不停的进入读中断,陷入死循环。
▪ 原因
STM8S 类型芯片的 UART 使用时在接收中断时要注意一个过载问题,下面呢就是手册原文:
过载错误:
如果 RXNE 还没有被复位,又接收到一个字符,则发生溢出错误。数据只有当 RXNE 位被清零后才能从移位寄存器转移到RDR寄存器(接收数据寄存器)。
当溢出错误产生时:
- OR位被置位
- RDR内容将不会丢失。读UART_DR寄存器仍能得到先前的数据。
- 移位寄存器中以前的内容将被覆盖。随后接收到的数据都将丢失。
- 如果RIEN位被置1,则产生中断。
如果顺序执行对UART_SR和UART_DR寄存器的读操作,可复位OR位。
首先 STM8 的 UART 接收中断的使能位是 RIEN,而当 RIEN 为1的时候就会进入接收中断,而能让 RIEN 为1的时候是有两种情况的:
- 一个就是在接收寄存器不为空的时候。(对应的中断请求标志 RXNE )
- 另一个就是过载错误了,在 RXNE 标志位还没有复位,又接收到一个字符,这时也会触发接收中断。(对应的中断标志位OR)
那么我们的问题就是出现在这里了,我们在每次接收中断都会清除 RXNE 标志位,但是并没有清除 OR 标志位,故当出现一次 RXNE 还没有被复位,又接收到一个字符的情况也就出现了 OR 一直没被清
除,所以就一直进入接收中断了。所以解决问题就是只要每次接收中断都需要清除 RXEN 和 OR 这两个标志位就可以解决问题了。
▪ 解决办法
必须添加 if( UART1_GetITStatus(UART1_IT_RXNE ) != RESET ),若不添加,会导致 UART1->DR 被异常读取,不断的进入中断处理函数
若 UART 的 RXNE 状态位已经被置 1,串口又收到新的数据,将会进入OR(过载错误)中断
STM8内部机制:先读取 UART_SR,再读取 UART_DR 才可自动把 OR 位中断状态清零;调用 UART1_GetITStatus(UART1_IT_RXNE) 即是读取 UART_SR
在调用 UART1_ReceiveData8() 读取了 UART1->DR 后即可清除中断 UART1_IT_RXNE 标志位
INTERRUPT_HANDLER(UART1_RX_IRQHandler, 18)
{
if( UART1_GetITStatus(UART1_IT_RXNE) != RESET) UART1_ReceiveData8();
}