20130718-调试设备通信常遇见的两种错误——Overrun和Underrun

http://wen.dingyuan.blog.163.com/blog/static/40452473201021923046512/

 

Underrun(underflow)

      In computing, buffer underrun or buffer underflow is a state occurring when a buffer used to communicate between two devices or processes is fed with data at a lower speed than the data is being read from it. This requires the program or device reading from the buffer to pause its processing while the buffer refills. This can cause undesired and sometimes serious side effects, since the data being buffered is generally not suited to stop-start access of this kind.

 

Overrun(overflow)

      A buffer overflow occurs when data written to a buffer, due to insufficient bounds checking, corrupts data values in memory addresses adjacent to the allocated buffer.

 

### 串口 DMA 空闲中断 Overrun 错误标志位的含义及解决方案 #### 1. **Overrun 错误标志位的含义** Overrun 错误(简称 ORE)是 UART 接收过程中的一种错误状态,表示在 MCU 尚未从接收寄存器中读取数据时,新的数据已经到达并覆盖了旧的数据。这种错误发生在接收速率过快或处理逻辑延迟的情况下。当发生 Overrun 错误时,UART 的硬件会设置 ORE 标志位,并可能阻止后续的正接收[^1]。 #### 2. **Overrun 错误的影响** 如果 Overrun 错误未被及时清除,可能会导致以下问题: - 串口接收功能异,例如空闲中断无法再次触发。 - 数据丢失或损坏,因为新数据覆盖了尚未处理的旧数据。 - 在某些情况下,可能导致 DMA 接收停止或进入错误状态。 #### 3. **解决方案** 以下是解决 Overrun 错误的几种方法: ##### (1) **清除 Overrun 错误标志位** 确保在初始化阶段中断回调函数中清除 ORE 标志位。例如,在 `HAL_UART_ErrorCallback` 函数中添加以下代码: ```c __HAL_UART_CLEAR_OREFLAG(huart); // 清除 Overrun 错误标志位 ``` 这一步骤可以防止 ORE 标志位积累导致的中断失效问题[^1]。 ##### (2) **优化数据处理逻辑** 如果主函数或中断回调函数中的数据处理逻辑过于复杂或耗时,可能会导致接收缓冲区溢出。可以通过以下方式优化: - 简化中断回调函数中的操作,仅执行必要的数据存储标志位设置。 - 将复杂的数据处理任务移至主循环中进行。 示例代码如下: ```c void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) { __HAL_UART_CLEAR_IDLEFLAG(huart); // 清除 IDLE 标志位 __HAL_UART_CLEAR_OREFLAG(huart); // 清除 Overrun 错误标志位 if (huart == &huart2) { uwbDecodeISR(0, Size); // 解码接收到的数据 HAL_UARTEx_ReceiveToIdle_DMA(huart, uwb_buff[0], 60); // 重新启动 DMA 接收 } } ``` ##### (3) **调整接收缓冲区大小** 如果接收数据量较大,而当前的缓冲区大小不足以容纳所有数据,可能会导致 Overrun 错误。可以通过增加接收缓冲区的大小来避免此问题。例如: ```c uint8_t uwb_buff[128]; // 增加缓冲区大小 HAL_UARTEx_ReceiveToIdle_DMA(&huart2, uwb_buff, sizeof(uwb_buff)); ``` ##### (4) **启用 DMA 半传输中断** 通过启用 DMA 半传输中断(Half Transfer Interrupt),可以在接收缓冲区一半满时提前处理数据,从而降低 Overrun 错误的发生概率。例如: ```c __HAL_DMA_ENABLE_IT(&hdma_usart2_rx, DMA_IT_HT); // 启用半传输中断 ``` ##### (5) **检查系统时钟配置** 如果系统时钟配置不当,可能导致串口接收速率与实际数据发送速率不匹配,从而引发 Overrun 错误。确保串口波特率时钟分频器配置正确。 #### 4. **完整示例代码** 以下是一个完整的初始化中断处理示例: ```c // 初始化串口 DMA MX_USART2_UART_Init(); MX_DMA_Init(); __HAL_UART_CLEAR_IDLEFLAG(&huart2); // 清除 IDLE 标志位 __HAL_UART_CLEAR_OREFLAG(&huart2); // 清除 Overrun 错误标志位 HAL_UARTEx_ReceiveToIdle_DMA(&huart2, uwb_buff, sizeof(uwb_buff)); // 空闲中断回调函数 void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) { __HAL_UART_CLEAR_IDLEFLAG(huart); // 清除 IDLE 标志位 __HAL_UART_CLEAR_OREFLAG(huart); // 清除 Overrun 错误标志位 if (huart == &huart2) { uwbDecodeISR(0, Size); // 解码接收到的数据 HAL_UARTEx_ReceiveToIdle_DMA(huart, uwb_buff, sizeof(uwb_buff)); // 重新启动 DMA 接收 } } // 错误回调函数 void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) { __HAL_UART_CLEAR_OREFLAG(huart); // 清除 Overrun 错误标志位 __HAL_UART_CLEAR_FEFLAG(huart); // 清除 Framing 错误标志位 __HAL_UART_CLEAR_NEFLAG(huart); // 清除 Noise 错误标志位 HAL_UARTEx_ReceiveToIdle_DMA(huart, uwb_buff, sizeof(uwb_buff)); // 重新启动 DMA 接收 } ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值