3. 工业设备通信基础
在工业设备应用开发中,上位机与 PLC、变频器、仪表、传感器之间的通信是数据采集与指令控制的基础。串口通信因其简单、稳定、实时性好,至今仍是工业现场最普遍的物理层通信方式之一。本节从串口通信的基本原理出发,梳理 RS232 与 RS485 的电气差异,讲解 Modbus 协议的数据组织方式,并给出 Qt 串口模块的使用方法。
一、串口通信的基本原理
串口通信(UART)是一种异步串行通信方式,数据按位依次在一根信号线上传输。通信双方不需要共享时钟线,而是依靠预先约定的波特率进行采样同步。一次完整的数据帧由起始位、数据位、校验位和停止位组成,常见的配置为 8 位数据位、无校验、1 位停止位,即常说的“8N1”。
关键参数包括:
- 波特率:每秒传输的位数,如 9600、19200、115200,双方必须一致。
- 数据位:通常为 7 或 8 位,表示单个字符的有效数据长度。
- 校验位:无校验、奇校验、偶校验,用于简单检错。
- 停止位:1 位或 2 位,标志一帧结束。
串口通信是“字节流”通信,没有天然的消息边界。因此在实际应用中,必须依靠协议(如 Modbus)或自定义帧头帧尾来划分数据包,否则会出现粘包、半包问题。
二、RS232 与 RS485 的电气差异
UART 只定义了数据格式,而 RS232 和 RS485 定义的是电气层的物理接口标准。RS232 采用单端信号,逻辑 1 为负电压、逻辑 0 为正电压,传输距离一般不超过 15 米,适合点对点通信,常见于老式仪表和调试口。RS485 采用差分信号,用两根线 A、B 的电压差表示逻辑,抗干扰能力强,传输距离可达 1200 米,支持多点总线,是工业现场的主流选择。
| 对比项 | RS232 | RS485 |
|---|---|---|
| 信号方式 | 单端对地 | 差分 A/B |
| 传输距离 | 约 15 米 | 约 1200 米 |
| 拓扑结构 | 点对点 | 多点总线 |
| 抗干扰能力 | 较弱 | 较强 |
| 典型场景 | 调试口、短距设备 | PLC、仪表总线 |
三、Modbus 协议原理
Modbus 是工业领域最广泛使用的应用层协议之一,采用主从(Master/Slave)模式。主站发起请求,从站响应,从站之间不会主动通信。Modbus 常见两种传输形式:Modbus RTU 运行在串口上,使用二进制编码和 CRC16 校验;Modbus TCP 运行在以太网上,使用 MBAP 报文头。
Modbus 的数据模型由四类寄存器组成:
- 线圈(Coils):可读写开关量,地址 00001 起。
- 离散输入(Discrete Inputs):只读开关量,地址 10001 起。
- 保持寄存器(Holding Registers):可读写 16 位数据,地址 40001 起。
- 输入寄存器(Input Registers):只读 16 位数据,地址 30001 起。
以读取保持寄存器为例,主站发送的 RTU 帧结构为:从站地址 + 功能码 0x03 + 起始地址 + 寄存器数量 + CRC16。从站返回:从站地址 + 功能码 + 字节数 + 数据 + CRC16。功能码 0x01 读线圈、0x05 写单线圈、0x06 写单寄存器、0x10 写多寄存器,是工程中最常用的几个。
请求:01 03 00 00 00 02 C4 0B
含义:从站 01,读保持寄存器,起始 0x0000,读 2 个
响应:01 03 04 00 64 00 C8 3A 5E
含义:返回 4 字节数据,寄存器 0 = 100,寄存器 1 = 200
四、Qt 串口模块的使用
Qt 从 5.1 开始提供 QtSerialPort 模块,核心类为 QSerialPort 和 QSerialPortInfo。使用前需在工程文件中加入 QT += serialport。QSerialPortInfo 用于枚举可用串口,QSerialPort 负责打开、配置和读写。
QSerialPort serial;
serial.setPortName("COM3");
serial.setBaudRate(QSerialPort::Baud9600);
serial.setDataBits(QSerialPort::Data8);
serial.setParity(QSerialPort::NoParity);
serial.setStopBits(QSerialPort::OneStop);
if (!serial.open(QIODevice::ReadWrite)) {
qDebug() << "打开失败:" << serial.errorString();
}
connect(&serial, &QSerialPort::readyRead, [&]() {
QByteArray data = serial.readAll();
// 解析 Modbus 响应帧
});
QByteArray cmd = QByteArray::fromHex("010300000002C40B");
serial.write(cmd);
在工业场景中,串口数据到达是异步的,必须使用 readyRead 信号驱动接收,不能阻塞等待。建议将接收缓冲区与协议解析分离:先累积字节,再按帧长或超时判断完整帧,最后交给 Modbus 解析函数处理。
五、典型场景与排障思路
假设上位机通过 RS485 读取一台温控仪表,波特率 9600、8N1、从站地址 1。若通信失败,可按以下顺序排查:
- 确认串口号、波特率、校验位与仪表一致。
- 用串口助手发送相同报文,验证硬件链路是否通。
- 检查 A/B 线是否接反,终端电阻是否匹配。
- 确认从站地址与功能码正确,寄存器地址是否偏移 1。
- 查看返回帧 CRC 是否正确,判断是否受干扰。
掌握串口通信、RS232/RS485 电气特性和 Modbus 协议后,再结合 QtSerialPort 的异步读写机制,就能构建稳定可靠的工业设备通信层。实际项目中,建议把协议解析封装为独立类,便于复用和单元测试。