硬汉嵌入式论坛

 找回密码
 立即注册
搜索
查看: 1515|回复: 16
收起左侧

[UART] DMA+Modbus

  [复制链接]

4

主题

11

回帖

23

积分

新手上路

积分
23
发表于 2026-6-10 10:35:39 | 显示全部楼层 |阅读模式
各位大神好,

     大家知道Modbus协议是全宇宙设备免费通用的交互通信协议,在嵌入式单片机通信里,是绕不过去的协议。
     嵌入式工程师在实现Modbus从机时,通常会面临三种接收方案的选择:
      1 轮询方式:CPU不断查询USART接收寄存器状态,简单但CPU占用率极高
      2 基础中断接收:每个字节触发中断,频繁中断导致系统响应延迟
      3 DMA+空闲中断:DMA自动搬运数据,空闲中断精准判断帧结束
    以下是这三种方案的优略比较,很明显,第3种方案是最优选择。
       ScreenShot_2026-06-10_102347_765.png
    有哪位大神能系统讲讲DMA+空闲中断方式的Modbus通信啊,最好能有个实例辅助验证讲解,
    在网上也查了好多,好的讲解都是夸夸其谈或者AI生成的美文,应用起来各种问题,
    硬汉大神有好几版讲Modbus通信的实例+示例程序的,讲的非常好,非常仔细,
   也希望硬汉大神团队,能否更新版Modbus通信,把Modbus通信升级到DMA+空闲中断模式,给大家讲解讲解。
   
回复

使用道具 举报

1万

主题

7万

回帖

12万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
124427
QQ
发表于 2026-6-10 15:16:42 | 显示全部楼层
空闲中断方式不行,因为空闲中断是固定的一个字符间隔空闲,不是Modbus协议的3.5个字符,不符合协议规范。
回复

使用道具 举报

36

主题

351

回帖

459

积分

高级会员

积分
459
QQ
发表于 2026-6-10 15:54:33 | 显示全部楼层
如果是 modbusRTU 485 通信,那简直和 DMA 是天生绝配。

整个功能各个部分全都是“通道化”的思维。

modbusRTU 主->从 从->主 的通道
485 收通道 发通道
DMA 搬运通道

只是 1.5 字符和 3.5 字符,要额外增加一个轮询机制结合空闲中断来计时,推荐楼主深入研究。
回复

使用道具 举报

13

主题

24

回帖

68

积分

初级会员

积分
68
发表于 2026-6-10 16:10:19 | 显示全部楼层
合适的mcu(如stm32h743,基本上st新的ic的usart ip都很强大)可以做到硬件高效收发,减少软件处理:usart支持硬件控制485的en脚,支持硬件超时功能设置(非空闲中断),支持dma收发。
回复

使用道具 举报

19

主题

59

回帖

116

积分

初级会员

积分
116
发表于 2026-6-10 16:32:41 | 显示全部楼层
我来说说实际应用吧,用空闲中断确实不满足协议规定的3.5字符间隔,实际使用并没啥问题,我的项目都是115200,dma+idle,设备覆盖10余个品类,其中3个品类出货量2w+,其余零零散散也有1w+出货量,目前没发现问题,我设备的使用环境也包括电磁干扰比较强的地方,用于发动机启停控制

点评

对帧要求比较严格的场景就不行,你响应过快。它会收不到,比如新版本的施耐德PLC  详情 回复 发表于 2026-6-11 21:32
回复

使用道具 举报

60

主题

698

回帖

883

积分

金牌会员

积分
883
发表于 2026-6-11 21:28:51 | 显示全部楼层
jasonZJR 发表于 2026-6-10 16:32
我来说说实际应用吧,用空闲中断确实不满足协议规定的3.5字符间隔,实际使用并没啥问题,我的项目都是11520 ...

这个其实就不管这个T3.5时间间隔,反正收到完整的数据帧就处理是吧
回复

使用道具 举报

5

主题

18

回帖

33

积分

新手上路

积分
33
发表于 2026-6-11 21:32:50 | 显示全部楼层
jasonZJR 发表于 2026-6-10 16:32
我来说说实际应用吧,用空闲中断确实不满足协议规定的3.5字符间隔,实际使用并没啥问题,我的项目都是11520 ...

对帧要求比较严格的场景就不行,你响应过快。它会收不到,比如新版本的施耐德PLC
回复

使用道具 举报

5

主题

18

回帖

33

积分

新手上路

积分
33
发表于 2026-6-11 21:37:24 | 显示全部楼层
用空闲中断加硬件定时器方式来做,根据波特率的不同定时器的超时时间不同,这样可以做到很标准的帧间隔。另外,F7、H7串口有超时中断,但是要非常谨慎用,甚至不要用,因为它可能会误触发中断导致帧被破坏,导致该帧数据丢失,我们实际项目就遇到了,后来改成空闲中断+硬件定时器,非常稳,连续通信不会丢帧
回复

使用道具 举报

19

主题

59

回帖

116

积分

初级会员

积分
116
发表于 2026-6-12 08:39:39 | 显示全部楼层
ou513 发表于 2026-6-11 21:28
这个其实就不管这个T3.5时间间隔,反正收到完整的数据帧就处理是吧

我确实没管间隔,也没判断完整性,idle触发后,校验modbus,通过就处理,不通过就丢弃
回复

使用道具 举报

19

主题

59

回帖

116

积分

初级会员

积分
116
发表于 2026-6-12 08:40:49 | 显示全部楼层
gugugui 发表于 2026-6-11 21:32
对帧要求比较严格的场景就不行,你响应过快。它会收不到,比如新版本的施耐德PLC

嗯嗯,我这个肯定是非标做法,但能应付大多数场景了,要收发双方保持一致性就好
回复

使用道具 举报

9

主题

214

回帖

241

积分

高级会员

积分
241
发表于 2026-6-12 12:10:58 | 显示全部楼层
本帖最后由 死不低头 于 2026-6-12 12:12 编辑

这三个方式我都在F1 F4 H7 G0 RP2350 里试过。DMA+轮询也做过,也挺好用的。不要信任何国内AI,搞技术真的错误率99.9%以上。

最不建议是中断方式,因为频繁中断容易打断别的东西工作,如果波特率比较低,比如9600 19200其实轮询也非常靠谱,占用CPU其实非常低,特别是有硬件FIFO的H7 G0这些新型的MCU

DMA加空闲中断方式在高速通信里绝对是首选,DMA+轮询 实现500K波特率也没什么问题。

接收因为是不定的,所以一个接收需要一个DMA通道,发送是可控的,如果DMA通道不够用,可以几个串口共用一个DMA通道发送数据,只要每次发送前配置一下就行。

串口空闲中断有些MCU是没有的,有些是配合基本定时器来实现的 ,可以实现严格的3.5个字节空闲时间,这个可以参考HC32F4A0的串口空闲中断实现。

ST的话直接用空闲中断也可以的,我试过好像挺稳定。

总的来说我还是比较喜欢DMA+轮询,弄个1ms任务,每1ms去查询一下接收到个数是否有变化,只要1-4个ms数据个数没变化自然就完成了,所有支持DMA的MCU应该都能通用,速度和稳定性当然也是不错的,我记得去年用F4试过,500K波特率用上位机快速收发MODBUS数据一点问题都没有,而且占用资源也不多,逻辑还非常简单。


点评

这才是大神啊!! 不但知道,而且还知道好几种方法,各自的优缺点, 厉害啊!!  详情 回复 发表于 2026-6-15 17:02

评分

参与人数 1金币 +20 收起 理由
hqgboy + 20 很给力!

查看全部评分

回复

使用道具 举报

0

主题

9

回帖

9

积分

新手上路

积分
9
发表于 2026-6-12 17:58:59 | 显示全部楼层
最好DMA+轮询,不要回太快,太快时上位机来不及接收,慢几ms都没关系,上位机一般都会有接收超时,
我一般是10ms轮询DMA状态。
回复

使用道具 举报

9

主题

214

回帖

241

积分

高级会员

积分
241
发表于 2026-6-13 12:36:38 | 显示全部楼层
水沝淼 发表于 2026-6-12 17:58
最好DMA+轮询,不要回太快,太快时上位机来不及接收,慢几ms都没关系,上位机一般都会有接收超时,
我一般 ...

DMA+轮询确实非常适合这些不要求高速高实时的通信,适应性也非常好。

就是串口没有附带专门的硬件CRC,不然可比CAN舒服多了。

开4个串口加一堆ADC和IO扫描滤波和逻辑判断,F103这种MCU,用个软定时器实现1ms定时任务完全没压力,就怕多个高频中断,那是真的耗资源。

所以现在的主流MCU我觉得完全不需要使劲堆什么性能和牛逼配置,把DMA通道多弄几个,就好用很多。
真要高性能就堆核,两个核一个就用来专门高频中断任务,比当个高主频的要高效。
回复

使用道具 举报

2

主题

115

回帖

121

积分

初级会员

积分
121
发表于 2026-6-13 16:02:25 | 显示全部楼层
死不低头 发表于 2026-6-13 12:36
DMA+轮询确实非常适合这些不要求高速高实时的通信,适应性也非常好。

就是串口没有附带专门的硬件CRC ...

现在的 mcu 也有硬件 crc,可以计算 modbus crc

外接的串口控制器,有的也自带 crc 计算和校验,自动分包、组包、过滤,甚至还支持 CAN 总线的按位仲裁,譬如 CDCTL01A,速率最高 50 Mbps,可装载的数据量也比 CAN 大很多,payload 最大 253 字节
回复

使用道具 举报

9

主题

214

回帖

241

积分

高级会员

积分
241
发表于 2026-6-13 17:51:22 | 显示全部楼层
dukelec 发表于 2026-6-13 16:02
现在的 mcu 也有硬件 crc,可以计算 modbus crc

外接的串口控制器,有的也自带 crc 计算和校验,自动 ...

有是有,就是不太好用,有的还好几个CRC单元,要将数据装载进去算一下,只能说比软件算快一点,没法自动添加CRC和校验,这点比CAN和SPI确实差了不少。
回复

使用道具 举报

4

主题

11

回帖

23

积分

新手上路

积分
23
 楼主| 发表于 2026-6-15 17:02:51 | 显示全部楼层
死不低头 发表于 2026-6-12 12:10
这三个方式我都在F1 F4 H7 G0 RP2350 里试过。DMA+轮询也做过,也挺好用的。不要信任何国内AI,搞技术真的 ...

这才是大神啊!!
不但知道,而且还知道好几种方法,各自的优缺点,
厉害啊!!
回复

使用道具 举报

1

主题

22

回帖

25

积分

新手上路

积分
25
发表于 2026-6-18 08:56:37 | 显示全部楼层
modbus强制要3.5个空闲吗(码代码的时候真没考虑过,)?我都是用空闲中断+DMA。有什么特殊要求下,需要在串口上跑高负载的通讯吗?用中断+定时器好像也没啥区别。
而且在115200下轮询或者中断啥的真占这么多cpu资源???4MHz下,也没这么多吧。。。。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2026-10-24 10:37 , Processed in 0.614800 second(s), 29 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表