尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

数据采集卡从入门到精通(21):Modbus协议详解——从帧结构到寄存器点表设计

数据采集卡从入门到精通(21):Modbus协议详解——从帧结构到寄存器点表设计 Modbus诞生于1979年是工业自动化领域最长寿、最通用的协议。任何一块想接入PLC、组态软件、SCADA的采集卡都必须说好这门工业普通话。本文从零讲起RTU与TCP两种形态、四大寄存器区、帧结构逐字节解剖、CRC校验最后设计一张完整的采集卡点表并给出Python主站实现。全文约4500字。一、为什么是Modbus三条硬理由免费开放无授权费、无专利墙、极简可靠主从问答、CRC校验30年现场验证、生态通吃任何PLC/组态/SCADA都原生支持。对采集卡厂商说Modbus等于一句买我就能接进你现有的系统对用户会Modbus等于手握打开一切工业设备的钥匙。两种主流形态Modbus RTU跑在RS485或RS232上二进制紧凑帧CRC16校验——车间现场标准Modbus TCP跑在以太网上RTU帧外面包一层MBAP头TCP端口502——远程与组网标准。两者数据语义完全同构同样的寄存器地址、同样的功能码学会一种即通两种。二、数据模型四大寄存器区Modbus把设备数据组织成四个区每区65536个地址区名称读写常用功能码采集卡对应线圈Coils读/写01读/05写单/0F写多DO数字输出离散输入Discrete Inputs只读02读DI数字输入输入寄存器Input Registers只读04读AI模拟输入只读型保持寄存器Holding Registers读/写03读/06写单/10写多配置参数、AO输出、可写数据命名记忆法线圈和离散输入是位bit输入/保持寄存器是16位字word输入是别人写给我读的保持是我存着可改的。对采集卡的典型映射0x (线圈, 00001~00016) → DO1~DO8 预留 1x (离散输入, 10001~10016) → DI1~DI8 报警位 3x (输入寄存器, 30001~30064)→ AI1~AI8原始码/工程量 4x (保持寄存器, 40001~40100)→ 采样率/量程/标定系数/AO值三、RTU帧逐字节解剖主站读保持寄存器功能码03请求帧[01] [03] [00C8] [0002] [CRC_L CRC_H] 从站 功能 起始地址 数量 CRC16 地址 码 40009 2个字从站正常应答[01] [03] [04] [13 88] [0B B8] [CRC_L CRC_H] 从站 功能 字节数 寄存器值1 值2 CRC 地址 码 2字×2B 5000 3000从站异常应答功能码0x80标志异常[01] [83] [02] [CRC...] ↑功能码80h ↑异常码02非法数据地址常用异常码01非法功能、02非法地址、03非法数据值、04从站故障、06忙。RTU帧的静默定界RTU没有帧头帧尾字符靠字符间静默≥3.5个字符时间分帧。115200bps下一个字符约87μs静默阈值约0.3ms——这就是RTU对主站发送节拍的要求不能在帧中间插入3.5字符的停顿。CRC16算法CRC-16/MODBUS多项式0xA001反转的0x8005初值0xFFFF低字节在前发送。接收端重算比对不一致即丢弃该帧。四、TCP帧MBAP包头Modbus TCP把RTU的应用数据去掉CRC——TCP自己有校验包进7字节MBAP头[事务ID 2B][协议ID 0000][长度 2B][单元ID 1B][功能码][数据...]事务ID主站自增序号应答原样带回——多请求并发时的配对钥匙RTU做不到并发单元ID替代RTU的从站地址网关场景下指向网关后的485从站去掉CRCTCP链路本身有校验和重传应用层CRC冗余。TCP形态还带来多主站并发多个客户端可同时连接502端口各自读写写操作需应用层协调。五、实战点表设计一块8通道采集卡好的点表设计遵循三条原则按数据性质分区、预留扩展空间、工程量与原始码双轨。示例设计 线圈区 0x 00001~00008 DO1~DO8输出状态 00009~00016 (预留) 离散输入区 1x 10001~10008 DI1~DI8实时状态 10009 任意通道超量程标志 10010 标定有效标志 10011~10016 (预留) 输入寄存器区 3x (只读) 30001~30008 AI1~AI8 电压×1000(有符号,单位mV) 30009 DI状态打包(bit0~7DI1~8) 30010~30011 帧计数器32位 30012 固件版本×100 保持寄存器区 4x (读写) 40001 采样率(Hz) 40002 通道使能位图(bit0~7) 40003 量程代码(0±5V,1±10V,24-20mA) 40004 触发阈值×1000 40005 触发通道号 40010~40017 AO1~AO4输出×1000(mV) 40020~40031 标定系数M/N(每通道2字×8通道) 40090 命令寄存器(写特定值触发动作)设计细节解析工程量定点化浮点数Modbus也能传两字拼IEEE754但定点×1000更通用组态软件整数处理无歧义5V→50001LSB1mV语义清晰DI打包8个DI可以8个离散地址组态方便1个打包字轮询高效双轨提供——按上位机习惯取用命令寄存器写魔术数触发动作如0x5A5A启动采集、0xA5A5停止把操作也塞进寄存器模型保持协议纯一帧计数器从站每次数据更新自增——主站轮询时读它判断数据是否刷新避免重复处理旧值这是无时间戳环境下的轻量新鲜度方案。六、Python主站实战# pip install pymodbusfrompymodbus.clientimportModbusSerialClient clientModbusSerialClient(portCOM7,baudrate9600,parityN,stopbits1,timeout1)client.connect()# 读8路AI(30001~30008 → 功能码04)rrclient.read_input_registers(0,8,slave1)volts[r/1000forrinrr.registers]print(AI:,[f{v:.3f}Vforvinvolts])# 读DI状态字(30009)rrclient.read_input_registers(8,1,slave1)dirr.registers[0]print(DI:,.join(str((dii)1)foriinrange(8)))# 写采样率400011000Hzclient.write_register(1000,1000,slave1)# 命令: 启动采集(400900x5A5A)client.write_register(4089,0x5A5A,slave1)client.close()TCP版本只需换一行frompymodbus.clientimportModbusTcpClient clientModbusTcpClient(192.168.1.50,port502)# 其余代码不变——寄存器语义跨传输层一致七、轮询周期预算485轮询的周期下限由单次往返延迟×从站数决定单次往返 ≈ 帧发送时间 从站处理 应答时间 9600bps读8字: ≈ 8ms发3ms处理10ms答 ≈ 21ms 单从站最快轮询: ~47Hz 16从站全轮一遍: ~3Hz(每个从站3次/秒)启示轮询频率与从站数量此消彼长。要快就提波特率、减轮询项只读变化部分、或分散到多条总线。八、常见问题FAQQ1为什么我的读返回异常码02地址越界——检查点表的协议地址与寄存器号差1问题40001对应协议地址0x0000。组态软件与代码里常差一位。Q2CRC错误频发怎么排查按序查波特率/校验位匹配→布线星型终端电阻→干扰源变频器滤波→共模隔离器。Q3Modbus能主动上报吗标准RTU/TCP不能纯问答。需要主动上报用Modbus UDP变体或换MQTT类发布订阅协议。Q4浮点数怎么传双寄存器拼IEEE754大端字序注意厂商字序约定AB CD还是CD AB——两字交换错误是浮点读出天文数字的头号原因。九、总结Modbus四区四码一CRC线圈与离散管bit输入与保持管word功能码03/04读、06/10写、01/02/05管位CRC16守住最后一道正确性。对采集卡用户读懂点表完全掌握设备数据主权对开发者一张设计良好的点表是产品易用性的隐形骨架。下一篇回到卡的功能侧数字IO与编码器接口。下一篇预告《数字IO与编码器接口PNP/NPN、去抖与正交解码》
返回列表