1、协议基础:工业通信协议概述、OSI七层模型、RS-232/RS-485物理层、Modbus RTU协议帧结构
1.1 工业通信协议到底在解决什么问题?
各位工程师朋友,咱们开门见山。工业通信协议,说白了就是让不同厂家的设备能「说同一种语言」。我做了十几年嵌入式开发,见过太多因为协议不兼容导致的现场问题。有一次在化工厂调试,PLC和变送器就是死活对不上数据,折腾了两天,最后发现是校验位设置不一致。这种坑,踩过一次就记住了。
工业通信和咱们平时用的USB、以太网不太一样。工业现场环境恶劣,有强电磁干扰、有高温、有震动。所以工业协议的设计思路,第一条就是「抗造」。你想想看,一个传感器在电机旁边,要是通信动不动就断,那生产线还怎么跑?
核心要点:工业通信协议 = 物理层标准 + 数据格式约定 + 错误检测机制。三者缺一不可。
1.2 OSI七层模型——通信的「骨架」
OSI七层模型,很多教科书讲得特别复杂。我换个角度说——它就是把「从A设备发一个比特到B设备」这件事,拆成了七个步骤。每一层只管自己的事,上层不管下层怎么实现。
咱们做工业通信,最常用的是下面四层:
| 层级 | 名称 | 在工业通信中的作用 |
|---|---|---|
| 第7层 | 应用层 | Modbus的读写命令、数据格式定义 |
| 第4层 | 传输层 | Modbus RTU中的地址和校验 |
| 第2层 | 数据链路层 | 帧结构、起始/停止位、CRC校验 |
| 第1层 | 物理层 | RS-232/RS-485的电平、线缆、连接器 |
我个人习惯,做协议开发时只关注物理层和数据链路层。上面几层,Modbus协议已经帮我们封装好了。你不需要自己实现TCP/IP协议栈,那是做以太网的人才操心的事。
经验之谈:刚入行时我总想把七层模型背得滚瓜烂熟,后来发现没用。真正干活时,你只需要知道「物理层管电压,链路层管帧结构,应用层管数据含义」就够了。
1.3 RS-232 vs RS-485——物理层的「两条路」
物理层,就是信号怎么在线上跑。工业上最经典的两个标准,就是RS-232和RS-485。
RS-232:点对点通信,最远15米左右。用正负电压表示逻辑0和1。我记得第一次用RS-232调试时,焊了个DB9接头,结果把2脚和3脚接反了,数据死活收不到。后来养成了习惯——做串口线之前,先拿万用表量一下。
RS-485:这才是工业现场的主力。差分信号传输,抗干扰能力强,最远能到1200米,一条总线上可以挂32个设备(用中继器还能更多)。
为什么RS-485抗干扰?因为它用两根线(A和B)的电压差来表示数据。干扰信号同时作用在两根线上,差值不变。这个原理,说白了就是「有难同当,有福同享」。
避坑指南:我曾经在一个项目中,RS-485总线接了15个设备,通信时好时坏。查了两天,发现是终端电阻没加。记住:长线传输(超过100米)或者设备多(超过10个),一定要在总线两端各加一个120欧姆的终端电阻。
1.4 Modbus RTU协议帧结构——最经典的工业「信封」
Modbus RTU,是工业通信的「普通话」。几乎所有PLC、变频器、仪表都支持。它的帧结构,就像一封信:
| 地址码(1字节) | 功能码(1字节) | 数据区(N字节) | CRC校验(2字节) |
咱们拆开来看:
- 地址码:0x01到0xF7。0x00是广播地址,所有设备都要响应。我建议你从1开始编号,别用0,容易出乱子。
- 功能码:0x03读保持寄存器,0x06写单个寄存器,0x10写多个寄存器。这三个最常用。
- 数据区:具体要读写的寄存器地址和数值。注意,Modbus是大端模式——高位字节在前。
- CRC校验:16位循环冗余校验。这是Modbus RTU的「防伪标识」。数据在传输过程中哪怕只错了一个比特,CRC都能检测出来。
举个例子,我要读取地址为0x01的设备的寄存器0x0000开始的2个寄存器:
请求帧:01 03 00 00 00 02 C4 0B
响应帧:01 03 04 00 0A 00 14 7A 9D
解释一下:请求帧中,01是地址,03是读功能码,00 00是起始寄存器地址,00 02是读取数量,C4 0B是CRC。响应帧中,04表示数据长度(4字节),00 0A和00 14就是读到的两个寄存器的值。
关键点:Modbus RTU帧之间要有至少3.5个字符时间的静默间隔。这个时间很重要!如果间隔太短,接收方会把两帧当成一帧处理。我曾经在波特率9600时,用延时4ms就出过问题,后来改成5ms才稳定。
1.5 实战中的「坑」与「招」
做Modbus RTU开发,有几个地方特别容易翻车:
- CRC计算:别自己写,用现成的查表法。网上有标准实现,直接复制粘贴。我刚开始手算CRC,算一次错一次。
- 波特率匹配:主站和从站的波特率、数据位、停止位、校验位必须完全一致。少一个都不行。
- 超时处理:从站不响应时,主站要设置超时。一般100ms到1秒,看现场情况。别死等,否则一个设备挂了,整条总线都瘫痪。
- 地址冲突:同一总线上不能有两个相同地址的设备。这个看起来简单,但现场调试时经常有人忘记设置。
我的习惯:每次做Modbus调试,先用串口助手抓一下原始数据。看看发送和接收的十六进制对不对。CRC对不对。这一步能解决80%的问题。
好了,这一章的内容就到这里。物理层和帧结构是基础中的基础,后面所有章节都建立在这上面。下一章,咱们会深入Modbus的功能码和寄存器映射,那才是真正开始「写代码」的时候。