1、Modbus 通讯在坛子中看到很多弟兄们在做 Modbus 通讯时遇到很多问题,包括 Modbus 的请求或响应的基本知识,包括编程等等,现将我的一点拙见写出来,供大家参考和批评指正。Modbus 协议最早有施耐德旗下的 Modicon 公司与 1978 年提出,目前已经称为国际标准和国家、行业标准。该协议是典型的串行通讯协议,支持 CRC 或 LRC 校验。通讯速率支持 2.4kbps115.2kbps,更快也可以,但是误码率较高。支持 RTU 或 ASCII 通讯凡是,支持奇 /偶/无校验。RTU 通讯时标准通讯参数为支持 8 个数据位、1 个停止位、偶校验;ASCII 通讯时标准通讯参数
2、为支持 7 个数据位、1 个停止位、偶校验;Modbus 总线理论上支持的从站个数可达 248 个(单条总线、不加中继时连接的设备个数与通讯端口和连接的设备有关,有的可连接 16 个设备,最大连接 32 个设备) ,不加中继双绞线距离可达 1200 米。Modbus 通讯时最常用的是 RTU 通讯方式:1.通讯时读请求格式如下:从站地址(1 个字节) 、功能代码(1 个字节) 、从站数据起始地址(2 个字节) 、读数据长度(2 个字节) 、CRC 校验(2 个字节) 。2.读响应格式如下:从站地址(1 个字节) 、功能代码(1 个字节) 、读数据长度(1 个字节) 、数据(长度与数据长度中的字
3、节数相同) 、CRC 校验( 2 个字节) 。3. 写请求格式:从站地址(1 个字节) 、功能代码(1 个字节) 、从站数据起始地址(2 个字节) 、写出数据长度(1 个字节) 、写出数据(长度与数据长度字节相同) 、CRC 校验(2 个字节) 。4. 写响应格式:从站地址(1 个字节) 、功能代码(1 个字节) 、从站数据起始地址(2 个字节) 、写数据长度(2 个字节) 、CRC 校验(2 个字节) 。如果为 RTU 通讯,校验方式为 CRC 校验;ASCII 通讯时,校验方式为 LRC 校验方式。功能代码有很多:01:读单个线圈(0*地址)数据02:读输入信号(1*地址)数据03:读连续
4、多个寄存器地址(4* )04:读连续多个输入模拟量地址(3* )05:写单个线圈(0*地址)数据06:写单个寄存器数据(4* )07:读以外状态信息08:诊断:15:写多个连续线圈(0*地址)数据16:写多个连续寄存器(4* )数据17:返回从站 ID:20:读参考信息(文件记录)21:写参考信息(文件记录)23:读写 FIFO 队列不同的 Modbus 设备支持的功能代码也有区别,总的来说 Modbus 设备可分为三类:1. 基本型:支持 03 和 16 功能码2. 标准型:支持 03 和 16、01、02、08、15 功能码3. 扩展型:支持除标准型的功能码外,还支持 20、21、23 功
5、能码。Modbus 读寄存器时最大可连续读取 125 个字的数据,写 100 个子的数据。读位时可读 2000 个位信息,写 1600 个位信息。 (位的数据与字的数据是 16 倍的关系)很多人认为做 Modbus 读写位操作时,所有数据应该保存在位地址中。其实不是,在做Modbus 通讯时,由于所有数据都是按照字节方式打包的,因此,所有位数据都是存储到字节中发送或读取的(这就是个别通讯一直疑问为什么做位读写时数据还要存储到字地址中的原因) 。最后,由于 Modbus 通讯同时支持字读写和位读写(在施耐德所有 PLC 中,所有地址都是按照“字 ”地址和 “位”地址定义的,字地址和位地址没有任何
6、关系,可以任意调用,而西门子所有PLC 地址都是按照 “字节”方式定义的。 )在存储数据时,西门子 PLC 中的数据是按照“低字节、高字节 ”顺序存储的,如果读取浮点数数据,顺序为:低字低字节、低字高字节、高字低字节、高字高字节。而施耐德所有 PLC 由于按照“ 字 ”地址和“ 位”地址定义的,所有数据存储时与西门子 PLC 完全相反,即如果读取浮点数数据,顺序为:低字高字节、低字低字节、高字高字节、高字低字节的顺序。这就是为什么有些数据上传到西门子 PLC 或 HMI 时,所有数据都不正确的原因,是因为高低字节顺序反了。如果出现上述问题,只需将高低字节编程做个转换即可。刚开始应用 MODBU
7、S 通讯的时候,犯过错,拿出来分享下。功能码 03 16 对应的 4*x(寄存器) 应用最多。 一般起始地址对应的 40001。 例如仪表的地址是 0x1F0 。容易对应成 40496 。实际是40497.采用 Modbus 通讯读写数据时,数据内容中并不包含数据的地址,数据地址包含在Modbus 读写的请求中。如下所示:通讯时读请求格式如下:从站地址(1 个字节) 、功能代码(1 个字节) 、从站数据起始地址(2 个字节) 、读数据长度(2 个字节) 、CRC 校验(2 个字节) 。因此,需要注意如下内容:1. 从 Modbus 地址编码来说,最小地址为 1,如 1*、0*、3*、4*地址中
8、最小地址都为1,如 10001,00001,30001,40001 等。但是很多厂家的设备在编码时都是按照最小地址为 0来编码的,所以,写设备的数据区地址时必须加 1,这就是“瘦锅”提到的问题;2. 另外有的 SCADA 软件读取 Modbus 设备数据时,有的要求地址长度必须为 6 位(如 ifix,所有地址必须为 6 位) ,而有的要求为 5 为(如 intouch 软件,读施耐德 Quantum PLC 时为 6位,其它中端 PLC 为 5 位) 。其实,从 Modbus 响应来说,所有数据中不包含地址,因此,在显示时输入 6 位或 5 位地址没有任何区别。ifix 或 intouch 软件中要求的 6 位或 5 位只是各自厂家按照自己的习惯来要求的。常见的测试 Modbus 通讯的软件除了常见的串口调试工具以外,最常用的是 Modscan,可以测试 Modbus 和 Modbus TCP/IP。我做过 MODBUS RTU 从站的程序,当时是完成了 FC03 和 FC16 的功能寄存器起始地址的 2 个字节正好被我定义为 DB 块号和 DBB 的号比如如果主站发 01 03 01 02 00 04 CRC_H CRC_L我就把从 DB1.DBW2 开始的四个字打包加上 CRC 校验发出去。