【发布时间】:2019-01-21 05:26:02
【问题描述】:
我需要帮助计算功能代码 1 的 modbus CRC 校验。即读取线圈寄存器。我有用于功能代码 3 的 CRC 检查的示例代码,即模拟输入的保持寄存器。
# Read Coil Status (FC=01)
## Request
此命令正在请求离散线圈#20 到 56 的 ON/OFF 状态 来自地址为 17 的从设备。
11 01 0013 0025 0E84
- 11:从地址(17 = 11 hex)
- 01:功能代码(读取线圈状态)
- 0013:要读取的第一个线圈的数据地址。 (线圈 20 - 1 = 19 = 13 hex)
- 0025:请求的线圈总数。 (线圈 20 到 56 = 37 = 25 hex)
- 0E84:用于错误检查的 CRC(循环冗余校验)。
响应
11 01 05 CD6BB20E1B 45E6
- 11:从地址(17 = 11 hex)
- 01:功能代码(读取线圈状态)
- 05:后面的数据字节数(37 个线圈/每字节 8 位 = 5 个字节)
- CD:线圈 27 - 20 (1100 1101)
- 6B:线圈 35 - 28 (0110 1011)
- B2:线圈 43 - 36 (1011 0010)
- 0E:线圈 51 - 44 (0000 1110)
- 1B:3 个空间支架和线圈 56 - 52 (0001 1011)
- 45E6:CRC(循环冗余校验)。
读取保持寄存器 (FC=03)
请求
此命令请求模拟输出保持寄存器#40108 的内容到 40110 来自地址为 17 的从设备。
11 03 006B 0003 7687
- 11:从地址(17 = 11 hex)
- 03:功能代码(读取模拟输出保持寄存器)
- 006B:请求的第一个寄存器的数据地址。 (40108-40001 = 107 = 6B 十六进制)
- 0003:请求的寄存器总数。 (读取 3 个寄存器 40108 到 40110)
- 7687:用于错误检查的 CRC(循环冗余校验)。
响应
11 03 06 AE41 5652 4340 49AD
- 11:从地址(17 = 11 hex)
- 03:功能代码(读取模拟输出保持寄存器)
- 06:后面的数据字节数(3 个寄存器 x 2 个字节,每个 = 6 个字节)
- AE41:寄存器 40108 的内容
- 5652:寄存器40109的内容
- 4340:寄存器40110的内容
- 49AD:CRC(循环冗余校验)。
我对获得 FC3 的响应没有问题。因为我正确发送了 2 字节地址,但我不知道如何发送单字节并修改 FC1 的 crc 函数 ->读取线圈寄存器
Discription of read coil register
unsigned int crc_fn(unsigned char *dpacket,unsigned int len) { // CRC Function(Error calcualtion)
unsigned int crc = 0xffff,poly = 0xa001;
unsigned int i=0;
for(i=0; i<len; i++) {
crc^= dpacket[i];
for(j=0; j<8; j++) {
if(crc & 0x01) {
crc >>= 1;
crc ^= poly;
} else
crc >>= 1;
}
}
return (crc);
}
【问题讨论】:
-
“我不知道如何发送单字节并修改 FC1 的 crc 函数” 请说明您的问题。如有必要,请显示您的消息构造代码。 FC1 和 FC3 的请求 CRC 计算方法相同:只需对消息帧的前 6 个字节运行 crc 函数。
-
我还是找不到问题。你的问题是什么? (请注意,问题以问号结尾。)请阅读MVCE 是什么。提供一个给出错误答案的示例,正确答案应该是什么,以及您如何知道这是正确答案。
-
我为 FC3 添加了 msg 构造。现在我会修改功能代码1。我不知道 CRC 函数是如何运行的。我从一个论坛中获取的代码。其中 50byte 可以使用。无符号整数 crc = 0xffff,poly = 0xa001;必须为功能代码更改此值1 应该是多项式值
-
这个问题还是没有问题的。