CAN总线与EtherCat的差异一场技术之争的激烈对决
远程IO设备的Modbus通信实践:解读03和06命令的奥秘
在遥控IO设备实现Modbus通信时,作为从机,它们遵循着精心设计的Modbus通讯过程。这里,我们将深入探讨使用MODBUS-RTU协议的一些命令子集,尤其是如何通过读寄存器命令(03)和单寄存器设置命令(06)来与主机进行数据交换。
每个消息都需要至少有3.5个字节时间的间隔,这保证了数据传输的准确性和可靠性。其中,功能码03用于主机请求从机提供采集数据或端口状态,而功能码06则用于设置设备参数或控制IO设备继电器动作。
功能码03(读指令)
利用Modbus通信协议中的03功能码,我们可以轻松地获取远程IO设备中的数值信息。这一过程涉及到两个关键步骤:主机发送请求并指定要读取的寄存器地址,以及从机返回所需数据及其对应CRC校验码。
主机请求格式
主机向从机发出请求时,其格式如下:
从机地址
功能码(0x03)
起始地址
数据个数
CRC校验码
例如,要以01为485串口地址,并且希望读取起始于0000位置、长度为1字节(即2个字节)的数据,可以构造如下请求:
01, 3, 00, 01, C4
从机响应格式
当从机会收到这样的请求后,它会根据要求发送回相应数量的注册值以及一个二字节长的地基校验代码(CRC)。具体来说,从机会以以下顺序发送回信息:
从事务处理者ID
功能编目号(0x3)
数据总量 - 数量表示的是被检索到的多少位输入/输出点。
每个点占据2位,所以它乘以2得到字节数。
这里我们用到了前面提到的“高低位”概念,因为我们是在16进制中工作,所以我们需要除以2再减去1才能获得实际要传送给计算机关得字节数。
如果不理解这个转换请考虑一下在二进制中8位代表一个字符,那么你可以把这些数字看做是某种形式上的八进制,然后你就能明白为什么除以2再减去1了。
if (byteCount > 0) {
dataBytes = byteCount * 2;
if ((dataBytes % 256) == dataBytes / 256 && (dataBytes % 255) == dataBytes / 255 + (dataBytes % 255)) {
// If the number of bytes is a multiple of two and it is an even number then we need to send only one byte for this.
crcByteCount = Math.ceil((double)dataBytes / Byte.MAX_VALUE);
} else {
crcByteCount = Math.ceil((double)dataBytes / Byte.MAX_VALUE + .5); // because you can't have half a byte so we round up.
}
} else {
crcByteCount = dataLength; // Since there are no bytes being sent out the length of the message should be equal to the length of the input buffer.
}
功能码06(写指令)
对于写操作,也就是修改或者设置某些寄存器里的内容,你可以使用Modbus通信协议中的06功能码。在这一步骤中,主机会告诉从事务处理者ID、想要写入哪一个寄存器、以及该寄存器应该包含哪一些内容。此外,还有一次对比检查,以确保正确性的目的,即使在出现错误的情况下也能自动纠正问题。
主机关键信息结构
为了更好地理解这一过程,让我们详细看看发送给模块的一个示例:
00,6,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,