3、通信协议入门:RS232/RS485串口通信、Modbus RTU协议详解、报文结构
各位同学,咱们今天聊点硬核的。做HMI开发,说白了就是跟设备打交道。设备怎么跟你说话?靠的就是通信协议。我见过太多新手,一上来就写界面,结果连PLC的数据都读不上来,折腾一整天。嗯,今天咱们就把串口通信和Modbus RTU这两个基本功打扎实。
3.1 串口通信:RS232 vs RS485
先说说串口通信。这东西看着简单,但坑不少。我刚开始做项目时,就因为在RS232和RS485之间选错了,多花了两天改硬件。
RS232:点对点的老前辈
RS232是最早的串口标准之一。它的特点就是简单粗暴——一根线发,一根线收,再加一根地线,完事。
- 传输距离:一般15米以内。再远信号就衰减得厉害。
- 速率:最高115200bps,实际常用9600或19200。
- 信号电平:±12V,逻辑1是-12V,逻辑0是+12V。跟TTL电平不兼容,得用转换芯片。
- 连接方式:一对一,只能连两个设备。
我的经验:RS232适合短距离、低速率的场景,比如调试口、老式仪表。我曾经在一个项目里用RS232连了一台30米外的设备,结果数据全是乱码。后来换成RS485,问题立马解决。
RS485:工业现场的主力军
RS485就不一样了。它用差分信号传输,抗干扰能力强得多。你想想看,工厂里电机一启动,电磁干扰满天飞,RS232早就趴下了,RS485还能稳稳地传数据。
- 传输距离:理论1200米,实际看速率和线缆质量。
- 速率:最高10Mbps,但距离越长速率越低。
- 信号电平:差分信号,A-B电压差大于200mV为逻辑1,小于-200mV为逻辑0。
- 连接方式:总线型,最多可挂256个设备(实际看驱动芯片)。
| 参数 | RS232 | RS485 |
|---|---|---|
| 传输方式 | 单端 | 差分 |
| 最大距离 | 15米 | 1200米 |
| 最大节点数 | 2 | 256 |
| 抗干扰能力 | 弱 | 强 |
| 典型应用 | 调试口、短距通信 | 工业现场、多设备组网 |
注意:RS485总线两端必须加120Ω终端电阻。我曾经在一个项目中忘了加,结果总线反射严重,数据时不时就丢包。加了电阻后,稳如老狗。
3.2 Modbus RTU协议详解
好了,物理层搞定了,咱们聊聊应用层。Modbus RTU是工业自动化领域最常用的协议之一。为什么?因为它简单、可靠、占用资源少。我做过几十个项目,90%的PLC和仪表都支持Modbus RTU。
协议特点
- 主从架构:一个主机(通常是HMI或上位机),多个从机(PLC、仪表、变频器等)。
- 半双工:同一时刻只能一方发数据。
- 报文格式:二进制传输,效率高。
- 功能码:定义操作类型,比如读线圈、读寄存器、写线圈等。
报文结构
Modbus RTU的报文结构非常清晰。说白了就是:地址 + 功能码 + 数据 + 校验。咱们一条一条拆开看。
| 从机地址 (1字节) | 功能码 (1字节) | 数据 (N字节) | CRC校验 (2字节) |
- 从机地址:0x01~0xF7,0x00是广播地址。每个从机必须有一个唯一地址。
- 功能码:比如0x03读保持寄存器,0x06写单个寄存器,0x10写多个寄存器。
- 数据:根据功能码不同,数据长度和格式也不同。
- CRC校验:循环冗余校验,确保数据在传输过程中没被篡改。
常用功能码
| 功能码 | 名称 | 说明 |
|---|---|---|
| 0x01 | 读线圈 | 读取开关量输出状态 |
| 0x02 | 读离散输入 | 读取开关量输入状态 |
| 0x03 | 读保持寄存器 | 读取模拟量输出或参数 |
| 0x04 | 读输入寄存器 | 读取模拟量输入 |
| 0x06 | 写单个寄存器 | 写入一个16位数据 |
| 0x10 | 写多个寄存器 | 连续写入多个16位数据 |
3.3 报文实例解析
光说不练假把式。咱们来看一个实际例子。假设HMI要读取地址为0x01的PLC中,起始地址为0x0000的2个保持寄存器。
主机发送报文
01 03 00 00 00 02 C4 0B
- 01:从机地址
- 03:功能码,读保持寄存器
- 00 00:起始寄存器地址(高字节在前)
- 00 02:读取寄存器数量(2个)
- C4 0B:CRC校验(低字节在前)
从机响应报文
01 03 04 00 0A 00 14 7A 5E
- 01:从机地址
- 03:功能码
- 04:数据字节数(2个寄存器 × 2字节 = 4字节)
- 00 0A:第一个寄存器的值(10)
- 00 14:第二个寄存器的值(20)
- 7A 5E:CRC校验
关键点:Modbus RTU的数据是高位在前(Big-Endian)。比如寄存器值0x000A,先发0x00,再发0x0A。这个顺序搞反了,读出来的数据就是错的。我见过有人因为这个bug查了一整天。
3.4 避坑指南
做串口通信,有几个坑是新手必踩的。我当年也没少吃亏,今天一并告诉你。
- 波特率必须一致:主机和从机的波特率、数据位、停止位、校验位必须完全一样。差一点都不行。
- CRC校验不能省:有些偷懒的程序员直接忽略CRC,结果数据错了都不知道。我建议你老老实实算CRC。
- 超时处理要合理:从机可能不响应,或者响应延迟。一般设100ms~500ms超时,超时后重试3次。
- 地址冲突是大忌:总线上两个从机地址相同,数据就乱套了。上电前先检查一遍地址。
我的习惯:调试串口通信时,先用串口助手抓报文。看看主机发了什么,从机回了什么。报文对了,问题就解决了一半。我曾经用这个方法,半小时就定位了一个通信故障——原来是CRC计算函数写错了。
3.5 小结
今天咱们把RS232、RS485和Modbus RTU的核心内容过了一遍。说白了,RS485是物理层的好选择,Modbus RTU是应用层的标准答案。两者结合,能解决90%的工业通信需求。
下一章,咱们会深入Modbus TCP,看看以太网环境下的通信怎么做。到时候你会发现,很多思路跟RTU是相通的。
好了,今天就到这儿。回去把报文结构背熟,下次咱们直接上手写代码。