新手上路
- 积分
- 23
- 金钱
- 23
- 注册时间
- 2018-3-20
- 在线时间
- 2 小时
|
最近在研究modbus协议,通讯协议流程搞明白后开始写程序~文档上面有现成的CRC查表法实现代码,但是就想自己试着写一个计算的代码,按照文档上的流程写出来测试怎么都不对。上网查查看别人的代码,发现了问题,第3步“将 CRC 寄存器右移 1 位 (向 LSB 方向), MSB 充零. 提取并检测 LSB.”检测的应该是移出的那一位,而不是检测移出后CRC寄存器的最低位。
生成 CRC 的过程为:
1. 将一个 16 位寄存器装入十六进制 FFFF (全 1). 将之称作 CRC 寄存器.
2. 将报文的第一个 8 位字节与 16 位 CRC 寄存器的低字节异或,结果置于 CRC 寄存器.
3. 将 CRC 寄存器右移 1 位 (向 LSB 方向), MSB 充零. 提取并检测 LSB.
4. (如果 LSB 为 0): 重复步骤 3 (另一次移位).
(如果 LSB 为 1): 对 CRC 寄存器异或多项式值 0xA001 (1010 0000 0000 0001).
5. 重复步骤 3 和 4,直到完成 8 次移位。当做完此操作后,将完成对 8 位字节的完整操作。
6. 对报文中的下一个字节重复步骤 2 到 5,继续此操作直至所有报文被处理完毕。
7. CRC 寄存器中的最终内容为 CRC 值.
8. 当放置 CRC 值于报文时,如下面描述的那样,高低字节必须交换。 我写的代码
[mw_shl_code=c,true]unsigned short my_crc16(unsigned char *buffer, unsigned short buffer_length)
{
uint16_t crc = 0xFFFF;
while (buffer_length--) {
crc ^= *buffer++;
for (int i = 0; i < 8; i++) {
crc >>= 1;
if (crc & 0x01)
crc ^= 0xA001;
}
}
crc = ((crc & 0xff) << 8) + (crc >> 8);
return crc;
}[/mw_shl_code]
修改后的代码
[mw_shl_code=applescript,true]unsigned short cal_crc16(unsigned char *buffer, unsigned short buffer_length)
{
uint16_t crc = 0xFFFF;
while (buffer_length--) {
crc ^= *buffer++;
for (int i = 0; i < 8; i++) {
if (crc & 0x01)
crc = crc >> 1 ^ 0xA001;
else
crc >>= 1;
}
}
crc = ((crc & 0xff) << 8) + (crc >> 8);
return crc;
}[/mw_shl_code]
|
|