ModBusTcp与串行链路Modbus的数据域是一致的,具体数据域可以参考串行modbus。这里给出几个ModbusTcp的链路解析说明,帮助新人分析报文。
![a1a5f219a8ee96760c66328318bd6382.png](https://img-blog.csdnimg.cn/img_convert/a1a5f219a8ee96760c66328318bd6382.png)
用到2个常用的工具,modscan扫描工具、modsim仿真工具,我们在开启modsim后,设置ID 站号为2,功能码选择01号功能码,开始地址设置00100,数量100个;然后我们把开始5个地址设置为1;
![5a2d12b674c337170cbf3ecd03b677fd.png](https://img-blog.csdnimg.cn/img_convert/5a2d12b674c337170cbf3ecd03b677fd.png)
接下来打开modscan工具,设置参数ID站号与从一致,设置为2,功能码选择01号功能码,开始地址设置为00100,寄存器数量设置17个;
下图是modscan工具扫描modsim仿真的数据包报文
![7c1f5373d16f9cdb9b84921b00c09d11.png](https://img-blog.csdnimg.cn/img_convert/7c1f5373d16f9cdb9b84921b00c09d11.png)
1、数据请求
A5 00 00 00 00 06 02 01 00 63 00 11
![23797bb7b3d04461454a6d7669189fcb.png](https://img-blog.csdnimg.cn/img_convert/23797bb7b3d04461454a6d7669189fcb.png)
2.数据回复
a5 00 00 00 00 06 02 01 03 1f 00 00
![a47ce25897237226385d77cfc44baed2.png](https://img-blog.csdnimg.cn/img_convert/a47ce25897237226385d77cfc44baed2.png)
接下来读取模拟量的浮点数类型的数据分析下
modsim设置ID 站号为2,功能码选择03号功能码,开始地址设置00100,数量100个;然后我们把地址40100=12.2, 40102=23.3, 40104=99.98,40116=50.00;浮点数类型我们现在的是不交换的类型;
![5229ecf9e63af4eadc992350b7a49eac.png](https://img-blog.csdnimg.cn/img_convert/5229ecf9e63af4eadc992350b7a49eac.png)
modscan扫的数据设置的需要扫18个数据(注意浮点数是4个字节,可以了解下大小端2中模式,这里边有字交换和字节交换等问题,就产生了多种组合;)
![d2acdc108a0c019e62146e555a8ad315.png](https://img-blog.csdnimg.cn/img_convert/d2acdc108a0c019e62146e555a8ad315.png)
发送数据:22 01 00 00 00 06 02 03 00 63 00 12
前边6位为modbus TCP/IP固定格式 22 01 00 00 00 06 在上边已做分析
02 是ID站号;
03 为功能码是保持寄存器;
00 63开始地址为99;
00 12数据个数为十进制的18个;
(注意报文的数字全部为16进制,需要做转换)
回复数据:22 01 00 00 00 27 02 03 24 33 33 41 43 66 66 41 BA F5 C3 42 C7 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 42 48
前边6位为modbus TCP/IP固定格式:22 01 00 00 00 27 ;
02为ID站号;
03 为功能码是保持寄存器;
24为数据长度36个字节,9个浮点数;
第一组:33 33 41 43
第二组:66 66 41 BA
第三组:F5 C3 42 C7
第九组:00 00 42 48
要想把字节正确组合成浮点数,首先要了解数据在内存中是怎么存储的。存储方式有两种:
大端模式
大端模式是指数据的高字节保存在内存的低地址单元中,而数据的低字节保存在内存的高地址单元中,这样的存储模式有点类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;这和我们的阅读习惯一致。
小端模式
小端模式是指数据的高字节保存在内存的高地址单元中,而数据的低字节保存在内存的低地址单元中。
#include #include #include int main(void) { float freq; char recv[4] = {0x41, 0xbc, 0x00, 0x00}; //接收到的数据,高字节到低字节排列 char *Modbus_HoldReg[4]; //定义保持寄存器指针数组 //第一步:指针初始化 Modbus_HoldReg[0] = ((char*)(&freq)) + 3; //低地址指向高位 Modbus_HoldReg[1] = ((char*)(&freq)) + 2; Modbus_HoldReg[2] = ((char*)(&freq)) + 1; Modbus_HoldReg[3] = ((char*)(&freq)) + 0; //高地址指向低位 //第二步:给地址指定的内存单元赋值(对应Modbus协议中的数据解析) *Modbus_HoldReg[0] = recv[0]; *Modbus_HoldReg[1] = recv[1]; *Modbus_HoldReg[2] = recv[2]; *Modbus_HoldReg[3] = recv[3]; printf("%f