STM32H7 RS485空闲中断例程
如果你用过STM32 的串口做RS485通信,大概率遇到过两个让人头疼的问题。第一个是数据长度不固定,你不知道对方设备什么时候会发完一帧数据,用传统的接收中断,每来一个字节就进一次中断,CPU被频繁打断,效率低不说,程序逻辑还特别复杂。第二个问题更烦人,RS485是半双工的,发送和接收要切换方向,那个使能引脚(DE/RE)的切换时机要是没把握好,轻则数据丢失,重则整个总线通信瘫痪。我早期做项目就踩过这个坑,发送完数据立马切回接收,结果最后一个字节还没从串口移位寄存器 里完全发出去,就被自己“掐断”了,对方根本收不全。
后来我发现,把串口DMA和空闲中断这两个功能组合起来,简直就是为RS485不定长通信量身定做的方案。我来给你打个比方:DMA就像一个不知疲倦的“搬运工”,串口每收到一个字节,它就自动把这个字节从串口的数据寄存器“搬”到你事先指定好的内存数组 里,整个过程完全不需要CPU插手。而“空闲中断”就像是一个敏锐的“监工”,它一直在监听串口接收线的状态。当一帧数据发送完毕后,串口接收线会保持高电平(即“空闲”状态)超过一个字节的时间,这时“监工”就会立刻拉响警报(产生中断),通知CPU:“这一批货(一帧数据)搬完了,快来处理!”
这种组合带来的好处是实实在在的。首先,CPU被彻底解放了。无论这一帧数据是5个字节还是50个字节,CPU只在整帧数据接收完毕时才被中断一次,而不是每个字节都中断一次。在9600波特率下,接收50个字节,传统方式CPU要被打断50次,而用DMA+空闲中断,只中断1次。省下来的CPU时间可以去处理更重要的业务逻辑,或者干脆进入低功耗模式省电。其次,编程模型变得极其清晰。你的主循环里只需要检查一个“接收完成”标志位,一旦置位,就去处理uart1RecvData数组里的数据,数组长度uart1RecvLen已经自动计算好了。代码结构从“中断驱动”变成了“事件驱动”,可读性和可维护性大大提升。
对于RS485来说,这个方案还有一个隐藏优势:能完美配合发送完成中断来安全切换方向。发送数据时,我们启动DMA发送,然后等待串口的“发送完成”(TC)中断。只有在TC中断里,我们才能100%确定最后一个字节已经彻底离开了串口移位寄存器,此时再将485芯片从发送模式切换到接收模式,时序上就万无一失了。
https://pan.baidu.com/s/1wUHQJ8LCnBRYMO2PsThQhQ?pwd=6ygy 提取码: 6ygy
更多推荐


所有评论(0)