1. STM32串口DMA技术基础与核心价值
在实际嵌入式开发中,串口通信是最常用的外设之一,但传统的串口收发方式需要CPU全程参与数据搬运,当数据量大或频率高时,CPU会被严重拖累。我在多个工业传感器采集项目中就深刻体会到了这个问题——CPU占用率经常超过60%,导致其他任务无法及时响应。
后来我转向了DMA技术,彻底解决了这个痛点。DMA(直接存储器访问)就像是给STM32配备了一个专职的"数据搬运工",它可以在不需要CPU干预的情况下,自动在外设和内存之间传输数据。想象一下,原本需要你亲自把货物从仓库搬到卡车(CPU参与),现在你只需要告诉搬运工(DMA)货物的位置和目的地,它就会自动完成所有工作,而你就可以去处理其他更重要的事情了。
STM32的DMA控制器支持四种传输方向:
- 外设到内存(串口接收)
- 内存到外设(串口发送)
- 内存到内存(数据缓冲处理)
- 外设到外设(特殊应用场景)
在串口通信中,我们最常用的就是前两种方向。HAL库为我们封装了一系列便捷的DMA函数:
HAL_UART_Transmit_DMA(); // DMA模式发送
HAL_UART_Receive_DMA(); // DMA模式接收
HAL_UART_DMAPause(); // 暂停DMA传输
HAL_UART_DMAResume(); // 恢复DMA传输
HAL_UART_DMAStop(); // 停止DMA传输
这些API让DMA的使用变得非常简单,但要想真正发挥DMA的威力,还需要结合一些高级特性,比如空闲中断和循环模式。我在实际项目中测试过,使用DMA后CPU占用率从60%降到了不到5%,而且数据传输的稳定性也大大提升,特别是在115200甚至更高的波特率下。
2. 空闲中断与DMA接收的完美结合
串口接收不定长数据一直是个让人头疼的问题。传统的做法要么是使用特定帧头帧尾,要么是使用超时判断,但这些方法都有各自的局限性。帧头帧尾需要数据格式固定,超时判断则难以选择合适的超时时间——设短了容易截断数据,设长了又影响实时性。
STM32的串口空闲中断(IDLE)完美解决了这个问题。空闲中断的原理很简单:当串口总线上有数据传输时,RX线会持续变化;当数据传输结束,总线保持空闲状态超过一个字符传输时间(在1M波特率下约为10μs)时,就会触发空闲中断。
这个特性非常适合与DMA接收配合使用。我们可以设置DMA接收一个足够大的缓冲区,然后开启空闲中断。当数据到来时,DMA会自动将数据搬运到缓冲区,完全不需要CPU参与。当数据传输结束触发空闲中断时,我们再在中断服务程序中处理接收到的数据。
HAL库提供了两个重要的API来处理这种场景:
// 高级API:自动处理空闲中断标志
HAL_UARTEx_ReceiveToIdle_DMA(&huart1, rx_buffer, BUFFER_SIZE);
// 低级API:需要手动管理中断标志
HAL_UART_Receive_DMA(&huart1, r


2069

被折叠的 条评论
为什么被折叠?



