STM32 Modbus通信学习笔记——通信流程

张开发
2026/4/9 16:15:39 15 分钟阅读

分享文章

STM32 Modbus通信学习笔记——通信流程
文章目录前言Modbus协议硬件连接基于RS485的Modbus通信Modbus拓扑结构Modbus通信流程Modbus主机帧结构传输方式RTU传输方式ASC传输方式数据帧格式ASCII 帧RTU 帧设备地址找谁功能码干什么校验CRC-16循环冗余错误校验LRC纵向冗余错误校验总结合集前言上一篇中介绍了不同硬件层协议传输逻辑0和逻辑1的方式也知道了软件层协议是需要依托这些硬件层的传输才能实现的。此篇将介绍Modbus的整个通信流程以及数据帧的结构。Modbus协议硬件连接根据之前的理论我们知道Modbus作为一种上层协议其底层其实可以是任意一种硬件层板级通信的协议UART、IIC、SPI亦或是现场级总线RS485、RS232、CAN总线这些来实现。基于RS485的Modbus通信笔者这里采用板级RS485进行描述学习过232和485的同学肯定都有一个感觉就是在编程的时候单片机端的配置其实和普通的UART串口配置没什么太大的区别以485为例通过观察下面的代码可以看见整个485初始化只是在串口初始化的基础上增加了一个接收和发送的模式控制。//模式控制#defineRS485_TX_ENPDout(7)//485模式控制.0,接收;1,发送.//如果想串口中断接收请不要注释以下宏定义#defineEN_USART2_RX1//0,不接收;1,接收.上一篇中我们知道单片机与485协议的设备通信时需要有硬件电路进行转换通过观察下面这个硬件电路可以看出在传统UART的TX、RX两个引脚上多了个RE这个脚就是用来控制发送和接收过程的。因为UART通信是一种全双工的通信模式通信双发都可以主动发送数据给对方而RS485采用的是半双工的通信方式也有全双工RS422采用主从通信同一时间只能主机发送或者只能从机发送不能主机和从机同时发送所以需要通过一个控制器来实现发送和接收控制。SP3485的2号引脚为低电平接收使能3号引脚为高电平发送使能。在这里我们将两个引脚连接在一起只需要通过一个信号RS485_RE即可控制收发过程当RS485_RE为高电平时SP3485 处于发送状态当RS485_RE为低电平时SP3485处于接收状态。RS485_RE状态1发送0接收Modbus拓扑结构Modbus采用主从通信结构即1.从机不能主动发送数据2.系统中只有一个主机。作为工业控制中一个通用的控制协议Modbus理论上可以有248个节点根据地址而定但是实际使用中只能挂接32个节点挂载设备数跟接口芯片的驱动能力有关不唯一这些节点之间只有唯一的一个主机其余都是从机连接示意图如下Modbus通信流程1.系统开机后所有设备都进入接收模式监听状态2.主机根据需求发送数据包到数据总线上发送完毕后释放总线重新进入接收模式3.从机检测总线状态并接收数据包4.从机判断主机发送数据包是否与自己的地址对应1地址对应就对数据包进行CRC校验CRC校验通过就开始处理主机发送的消息并按照约定的格式给主机打包数据并发送如果CRC校验不通过则说明数据丢失或者接收异常需要反馈给主机错误信息2地址不对应不对此数据包做处理也不需要回应主机5.如果主机发送的数据后超过设定的时间没有回应则说明从设备掉线需要检查地址是否正确以及线路连接是否正常。Modbus主机帧结构Modbus有两种传输方式一种是RTU另外一种是ASC。传输方式RTU传输方式RTU是以16进制形式或者说是2进制方式传输数据例如需要发送 “0x30”这个数据在485传输初始化是定义的是8位数据位一位停止位无校验位其发送格式如下ASC传输方式而ASC传输则是采用的ASCLL码表的形式例如需要传输30则实际发送的数据是‘3’和’0’的ascll码表的值及0x33和0x30。其传输形式如下通过上面两个例子可以看出ASCLL的传输方式明显比RTU的传输方式数据量大传输效率肯定不如RTU方式但是ASCLL得方式可以很方便调试调试时只需要将PC接入总线就可以实时获取数据包内容进而进行分析所以ASCLL的传输方式常用于调试用。而RTU则作为实际生产所用。数据帧格式ASCII 帧用 ASCII 模式 消息以冒号 : 字符 ASCII 码 3AH 开始 以回车换行符结束 ASCII 码 0DH,0AH。其它域可以使用的传输字符是十六进制的 0…9,A…F。 网络上的设备不断侦测“ :” 字符 当有一个冒号接收到时每个设备都解码下个域地址域来判断是否发给自己的。消息中字符间发送的时间间隔最长不能超过 1 秒否则接收的设备将认为传输错误。RTU 帧用 RTU 模式消息发送至少要以 3.5 个字符时间的停顿间隔开始。 在网络波特率下多样的字符时间这是最容易实现的(如下图的 T1-T2-T3-T4 所示)。传输的第一个域是设备地址。可以使用的传输字符是十六进制的 0…9,A…F。网络设备不断侦测网络总线包括停顿间隔时间内。当第一个域地址域接收到每个设备都进行解码以判断是否发往自己的。在最后一个传输字符之后一个至少 3.5 个字符时间的停顿标定了消息的结束。一个新的消息可在此停顿后开始。整个消息帧必须作为一连续的流转输。如果在帧完成之前有超过 1.5 个字符时间的停顿时间接收设备将刷新不完整的消息并假定下一字节是一个新消息的地址域。同样地如果一个新消息在小于 3.5 个字符时间内接着前个消息开始接收的设备将认为它是前一消息的延续。这将导致一个错误因为在最后的CRC 域的值不可能是正确的。此模式没有类似ASCLL模式的固定的起始位和结束位而是通过时钟周期来判断发送开始和结束的当开始接收数据时定时器开始准备计时当接收完毕后定时器开始计时当时间超过3.5个字节接收周期后则认为接收完毕。例如当波特率为9600bit/s时每位数据传输的时间t为t1s/9600bit104us则传输一个字节数据所用时间8位数据位加1位停止位Tt9936us约等于1ms时间那么3.5个字节所需时间T13.513.5MS也就是说在接受不到数据后开始计时记录没有数据传输的时间如果大于3.5ms(3.5个字符周期)则接收完毕如果小于3.5ms则说明此帧数据有误丢弃不做处理。设备地址找谁modbus中一共有0~247个地址其中0号地址作为广播地址即主机向0号地址发送数据时所有从设备都需要接收此数据包从设备不需要回应。功能码干什么modbus中一共有128个功能码每个功能码都有其对应的功能功能码不同后面的数据位的定义也各不相同常用的几个功能码如下所示需要进一步了解的可以自己去搜索详细介绍。校验数据包的传输过程中一般都会包括校验位目的是为了验证数据包的正确性在打包前主机会对数据位按照约定进行计算得到一个校验位并放在包内指定位置从机接收到数据包后也会再按照约定计算一遍数据位得到一个校验码此时对比两个校验位如果一致则说明数据包正确如果不一致则说明数据有误这个数据包应该被丢弃。可以发现acsll方式和RTU方式的校验方法不同一个是使用的LRC校验另外一个是CRC校验有关两种校验方式的具体实现形式如下可以参考实际使用中已经有前辈做好了封装可以直接调用。CRC-16循环冗余错误校验CRC-16 校验字节的步骤如下①装如一个 16 位寄存器所有数位均为 1。②该 16 位寄存器的高位字节与开始 8 位字节进行“异或” 运算。运算结果放入这个 16 位寄存器。③把这个 16 寄存器向右移一位。④若向右标记位 移出的数位是 1 则生成多项式 1010000000000001 和这个寄存器进行“异或” 运算若向右移出的数位是 0则返回③。⑤重复③和④直至移出 8 位。⑥另外 8 位与该十六位寄存器进行“异或” 运算。⑦重复③~⑥直至该报文所有字节均与 16 位寄存器进行“异或” 运算并移位 8 次。⑧这个 16 位寄存器的内容即 2 字节 CRC 错误校验被加到报文的最高有效位。另外在某些非 ModBus 通信协议中也经常使用 CRC16 作为校验手段而且产生了一些 CRC16 的变种他们是使用 CRC16 多项式 X↑ 16X↑ 15X↑ 21单首次装入的 16 位寄存器为 0000使用 CRC16 的反序X↑ 16X↑ 14X↑ 11首次装入寄存器值为 0000 或 FFFFH。LRC纵向冗余错误校验LRC 错误校验用于 ASCII 模式。这个错误校验是一个 8 位二进制数可作为 2 个 ASCII 十六进制字节传送。把十六进制字符转换成二进制加上无循环进位的二进制字符和二进制补码结果生成 LRC 错误校验。 这个 LRC 在接收设备进行核验 并与被传送的 LRC 进行比较 冒号 、 回车符号 CR 、换行字符 LF和置入的其他任何非 ASCII 十六进制字符在运算时忽略不计。LRC校验码~(地址功能码数据1…数据n)%2561实际上LRC校验码是一个0-255的数据。总结有关modbus的通信流程就介绍到此如有问题欢迎指正后面还会再出一篇基于STM32的RTU通信实例。合集STM32 Modbus通信学习笔记——理论基础STM32 Modbus通信学习笔记——通信流程STM32 Modbus通信学习笔记—— 代码及示例STM32 使用MODBUS与维控屏通信modbus系列代码

更多文章