mengf 发表于 2014-4-15 19:33:29

请教关于MODBUS查表法计算CRC校验码的问题

网上搜到MODBUS CRC查表校验的程序
uchCRCLo = uchCRCHi ^ auchCRCLo ;
??这个地方为什么需要进行两者的异或操作
不太理解,根据crc的计算过程描述,相当于把①-⑤的计算过程用查表来代替了,异或好像只有出现在第二步啊,已经由“uIndex = uchCRCLo ^ * puchMsg++ ;   ”这句程序执行了啊?
刚接触MODBUS,请大家帮忙看看



具体的计算步骤为:
① 设置CRC寄存器,并给其赋值FFFFH。
② 将被校验数据的第一个字节(8Bit)与CRC寄存器的低8位进行异或,结果存CRC寄存器。
③ CRC寄存器的值向右移一位,最高位(MSB)补零,检查移出的最低位(LSB)是否为1。
④ 如果LSB为0,重复第三步;若LSB为1,CRC寄存器与CRC16多项式值A001H相异或。
⑤ 重复第③与第④步,直到该字节的8次移位全部完成。
⑥ 如果被校验数据有多个字节,则重复第②至第⑤步直到所有数据全部处理完。
⑦ 最终CRC寄存器的内容即为CRC值。

unsigned short CRC16(puchMsg, usDataLen)
unsigned char * puchMsg ;                  
unsigned short usDataLen ;                  
{
unsigned char uchCRCHi = 0xFF ;            
unsigned char uchCRCLo = 0xFF ;            
unsigned uIndex ;                        
while (usDataLen--)                        
{
    uIndex = uchCRCLo ^ * puchMsg++ ;      
    uchCRCLo = uchCRCHi ^ auchCRCLo ;??这个地方为什么需要进行两者的异或操作
    uchCRCHi = auchCRCHi ;
}
return (uchCRCLo << 8 | uchCRCHi) ;
}


static char auchCRCHi[] = {
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x

mengf 发表于 2014-4-15 19:57:50

必须那样进行异或查表结果才是正确的,程序是对的。
就是那边异或不理解,当然这点跟下面这个版本的描述的第6点貌似是对的上的。
生成CRC-16校验字节的步骤如下:
1.装入一个16位寄存器,所有数位均为1。
2.装16位寄存器的低位字节与开始8位字节进行“异或”运算。运算结果放入这个16位寄
存器。
3.把这个16位寄存器向右移1位。
4.若向右(标记位)移出的数位是1,则生成多项式1010000000000001和这个寄存器进行
异或运算。若向右移出的数位是0,则返回(3)。
5.重复(3)和(4),直到移出8位。
6.另外8位与该16位寄存器进行“异或”运算。这里的另外8位指什么,16位寄存器是指第2点运算后的寄存器还是第5点移位后的寄存器,本人语文不好也没理解透{:lol:}
7.重复(3)-(6),直至该报文所有字节均与16位寄存器进行“异或”运算,并移位8次。
8.这个16位寄存器的内容即是2字节CRC校验值。
页: [1]
查看完整版本: 请教关于MODBUS查表法计算CRC校验码的问题