3、通讯协议入门:RS232/RS485串口通讯原理、Modbus RTU协议详解、Modbus TCP协议详解

做视觉控制器跟PLC打交道,通讯协议是绕不开的坎。我刚开始搞自动化那会儿,总觉得协议这东西太抽象,不就是两根线来回传数据嘛?后来被现实狠狠教育了一顿——线接对了,数据传不过来;数据传过来了,解析出来全是乱码。说白了,通讯协议就是双方约定好的「说话方式」,你说中文我说英文,鸡同鸭讲。

这一章,咱们就把串口通讯和Modbus协议彻底捋清楚。你想想看,工厂里90%以上的PLC都支持Modbus,搞懂了它,基本就能搞定大部分设备。

核心知识点速览

  • RS232 vs RS485:谁更适合工业现场?
  • Modbus RTU:数据怎么打包、校验、解析?
  • Modbus TCP:跟RTU有啥区别?
  • 实战中常见的坑和避坑方法
通讯协议入门 RS232/RS485串口 Modbus RTU Modbus TCP 点对点通讯 差分信号抗干扰 多站组网 CRC16校验 功能码03/06/16 寄存器寻址 以太网传输 无校验/无地址 MBAP报文头

3.1 RS232与RS485串口通讯原理

串口通讯,说白了就是一位一位地传数据。就像两个人打电话,一个字一个字地说。RS232和RS485是两种最常见的物理层标准,决定了信号怎么在线上跑。

RS232:老当益壮的点对点通讯

RS232是最早的串口标准之一。我记得十几年前调试第一台设备,用的就是RS232。它的特点是:

  • 传输距离短:一般不超过15米。我在一个项目里硬拉了20米,结果数据全乱套了。
  • 点对点通讯:一台设备只能跟另一台设备通信,不能多站组网。
  • 电压信号:用-3V~-15V表示逻辑1,+3V~+15V表示逻辑0。抗干扰能力一般。
  • 全双工:可以同时发送和接收数据。

实战小技巧

RS232的DB9接口,2脚是RXD(接收),3脚是TXD(发送),5脚是GND。我见过太多人把2和3接反了,结果死活通不上。记住:交叉连接——这边的TXD接那边的RXD。

RS485:工业现场的王者

RS485才是工业自动化里的主力。为什么?因为它能解决RS232的痛点。

  • 差分信号传输:用两根线(A+和B-)的电压差来表示数据。抗干扰能力极强,我曾在变频器旁边拉RS485线,一点问题没有。
  • 传输距离远:理论可达1200米。实际项目中我用到过800米,稳定得很。
  • 多站组网:一条总线上可以挂32个节点(用中继器可以更多)。
  • 半双工:同一时刻只能发送或接收,不能同时进行。

⚠️ 避坑指南

我曾经在一个项目里,RS485总线接了15台设备,结果通讯时好时坏。查了两天才发现——终端电阻没加!记住:总线两端必须各加一个120Ω的终端电阻,用来消除信号反射。不加的话,长距离通讯必出问题。

3.2 Modbus RTU协议详解

Modbus RTU是工业自动化领域最常用的通讯协议之一。它运行在RS232/RS485物理层之上,定义了数据怎么打包、怎么校验、怎么解析。

报文结构

Modbus RTU的报文结构很简单,就三部分:

地址码 功能码 数据区 CRC校验
1字节 1字节 N字节 2字节
设备地址 1~247 03读、06写、16批量写 寄存器地址+数据 CRC16低字节在前

举个例子,读取地址为1的PLC的3个寄存器,从起始地址0x0000开始:

请求报文:01 03 00 00 00 03 05 CB
  - 01:设备地址
  - 03:功能码(读保持寄存器)
  - 00 00:起始寄存器地址
  - 00 03:读取数量(3个寄存器)
  - 05 CB:CRC16校验

响应报文:01 03 06 00 01 00 02 00 03 9A 9B
  - 01:设备地址
  - 03:功能码
  - 06:数据字节数(3个寄存器×2字节)
  - 00 01 00 02 00 03:三个寄存器的值
  - 9A 9B:CRC16校验

常用功能码

实际项目中,90%的情况只用这三个功能码:

  • 03 (0x03):读取保持寄存器。读PLC的D寄存器、数据块都用这个。
  • 06 (0x06):写单个寄存器。适合设置参数、启停控制。
  • 16 (0x10):写多个寄存器。批量下数据时用,效率高。

寄存器地址的坑

Modbus协议里,寄存器地址从0开始编号。但很多PLC的编程软件里,地址是从1开始显示的。比如三菱PLC的D100,在Modbus里对应的地址是0x0063(99)。我刚开始做项目时,直接用了D100的编号100去读,结果读回来的数据完全不对。记住:协议地址 = PLC地址 - 1。

CRC16校验

CRC校验是Modbus RTU的保命符。没有它,数据传错了你都不知道。计算方法是:

uint16_t crc16(uint8_t *data, uint16_t len) {
    uint16_t crc = 0xFFFF;
    for (uint16_t i = 0; i < len; i++) {
        crc ^= data[i];
        for (uint8_t j = 0; j < 8; j++) {
            if (crc & 0x0001) {
                crc = (crc >> 1) ^ 0xA001;
            } else {
                crc >>= 1;
            }
        }
    }
    return crc;
}

这段代码我用了十年,从来没出过问题。注意:发送时低字节在前,高字节在后。

3.3 Modbus TCP协议详解

Modbus TCP就是把Modbus RTU搬到以太网上。说白了,去掉CRC校验,加上一个MBAP报文头,用TCP/IP传输。

Modbus TCP vs Modbus RTU

对比项 Modbus RTU Modbus TCP
物理层 RS232/RS485 以太网
传输速率 9600~115200 bps 10/100/1000 Mbps
设备地址 需要(1~247) 不需要(用IP区分)
校验 CRC16 TCP/IP自带校验
报文头 MBAP头(7字节)

MBAP报文头

Modbus TCP的报文结构:

MBAP头(7字节) + 功能码(1字节) + 数据区(N字节)

MBAP头结构:
- 事务处理标识符(2字节):用于匹配请求和响应
- 协议标识符(2字节):固定为0x0000
- 长度(2字节):后续字节数
- 单元标识符(1字节):相当于RTU的设备地址

举个例子,读取IP为192.168.1.100的PLC的3个寄存器:

请求报文:00 01 00 00 00 06 01 03 00 00 00 03
  - 00 01:事务ID
  - 00 00:协议ID
  - 00 06:后续长度(6字节)
  - 01:单元ID(设备地址)
  - 03:功能码
  - 00 00:起始地址
  - 00 03:读取数量

我的经验

Modbus TCP比RTU简单多了,不用算CRC,不用管地址冲突。但有个坑:很多PLC的Modbus TCP端口不是默认的502。我遇到过一台设备用的是5000端口,查了半天手册才发现。所以拿到设备第一件事——确认端口号。

3.4 实战中的通讯调试技巧

通讯调试是门手艺活。我总结了几条经验:

  1. 先确认物理层:用示波器看波形,或者用串口助手发数据看回显。物理层不通,上层协议再对也没用。
  2. 用Modbus调试工具:我常用ModScan(模拟主站)和ModSim(模拟从站)。先跟模拟器通,再跟真实设备通。
  3. 抓包分析:Wireshark抓Modbus TCP包,Serial Port Monitor抓串口数据。看原始报文,问题一目了然。
  4. 注意超时处理:PLC的响应时间一般在10~100ms。我习惯设500ms超时,重试3次。太短容易误判,太长影响效率。

⚠️ 我曾经踩过的坑

有一次调试视觉控制器跟西门子S7-1200通讯,Modbus TCP怎么都连不上。查了IP、端口、寄存器地址,全对。最后发现——S7-1200默认不开启Modbus TCP服务器功能,需要在程序里调用"MB_SERVER"指令块。嗯,这种软配置问题最坑人。

通讯协议这东西,说白了就是约定。你遵守约定,设备就听你的。RS232/RS485是物理层的约定,Modbus是应用层的约定。搞懂了这些,视觉控制器跟PLC对话就是小菜一碟。


公众号:蓝海资料掘金营,微信deep3321