【ChipIntelli 系列】SDK详解3——串口接收中断代码解读
static char rx_buffer[24];
void uart_irq_handler(void)
{
if (((UART_TypeDef*)UART_PROTOCOL_NUMBER)->UARTMIS & (1UL << UART_RXTimeoutInt))
{
rx_buffer[0] = 1;
while(0 == (((UART_TypeDef*)UART_PROTOCOL_NUMBER)->UARTFlag & (0x1 << UART_RXFE)))
{
if (rx_buffer[0] >= 20)
{
memmove(rx_buffer+1, rx_buffer+2, 19);
rx_buffer[0] = 20;
}
rx_buffer[rx_buffer[0]++] = UART_RXDATA((UART_TypeDef*)UART_PROTOCOL_NUMBER);
}
send_packet_rev_msg(&rx_buffer, rx_buffer[0]);
}
UART_IntClear((UART_TypeDef*)UART_PROTOCOL_NUMBER,UART_AllInt);
}
这段代码是一个UART(串口)中断处理函数,用于处理接收超时中断并读取接收到的数据。以下是对代码的详细解读:
代码功能概述
-
检查是否发生接收超时中断(RXTimeout)
-
如果有超时中断,读取UART接收缓冲区中的所有数据
-
将数据存储在静态缓冲区
rx_buffer中 -
当缓冲区接近满时进行数据移位处理
-
最后通过
send_packet_rev_msg发送接收到的数据包
详细分析
1. 中断检查
c
if (((UART_TypeDef*)UART_PROTOCOL_NUMBER)->UARTMIS & (1UL << UART_RXTimeoutInt))
-
检查UART的MIS(Masked Interrupt Status)寄存器
-
判断是否发生了接收超时中断(RXTimeout)
2. 缓冲区管理
c
rx_buffer[0] = 1;
-
rx_buffer[0]被用作当前数据长度的计数器 -
初始设置为1(可能表示从索引1开始存储数据)
3. 数据读取循环
c
while(0 == (((UART_TypeDef*)UART_PROTOCOL_NUMBER)->UARTFlag & (0x1 << UART_RXFE)))
-
循环检查UART的Flag寄存器中的RXFE(Receive FIFO Empty)位
-
当接收FIFO不为空时继续读取
4. 缓冲区溢出处理
c
if (rx_buffer[0] >= 20)
{
memmove(rx_buffer+1, rx_buffer+2, 19);
rx_buffer[0] = 20;
}
-
当缓冲区接近满(≥20字节)时:
-
使用
memmove将数据向前移动一位(丢弃最早的一个字节) -
保持缓冲区长度为20
-
5. 数据存储
c
rx_buffer[rx_buffer[0]++] = UART_RXDATA((UART_TypeDef*)UART_PROTOCOL_NUMBER);
-
从UART数据寄存器读取数据
-
存储在
rx_buffer的当前位置,然后递增计数器
6. 数据发送
c
send_packet_rev_msg(&rx_buffer, rx_buffer[0]);
-
调用函数发送接收到的数据包
-
传递缓冲区地址和数据长度
7. 中断清除
c
UART_IntClear((UART_TypeDef*)UART_PROTOCOL_NUMBER,UART_AllInt);
-
清除所有UART中断标志
潜在问题
-
缓冲区设计:
rx_buffer[0]既作为长度计数器又用于存储数据,这种设计容易混淆 -
缓冲区大小:静态缓冲区大小为24,但最大只使用20个位置
-
数据移位:
memmove的参数可能有误,应该是从索引2开始移动到索引1 -
中断处理:清除所有中断可能不够精确,最好只清除已处理的中断
建议改进
-
分离长度计数器和数据存储
-
使用更清晰的缓冲区管理
-
精确清除特定中断而不是所有中断
-
添加错误处理机制
这段代码展示了一个基本的UART中断处理实现,但在工程实践中可能需要更加健壮的设计。

浙公网安备 33010602011771号