技术论坛

 CRC16-Modbus 实现的三种方法

返回主题列表
作者 主题
1Shadow1
侠士

经验值:1130
发帖数:81
精华帖:4
楼主    2023-09-02 13:10:43
主题:CRC16-Modbus 实现的三种方法

做这个的目的主要是作为练习,CRC练习对数组的边界掌控和西门子字节存储的记忆有帮助;


本来打算再做一篇STL的,因为STL的指针计算比较适合对字节中的移位的操作,昨天看公众号里面西门子后期可能会淘汰这门语言就算了.


下面程序段完成的是CRC校验 ,这样的话同一个程序块就可以方便切换,生成CRC和校验CRC 了;

计算的思路:

一种情况是剩下的位数量等于多项式位数的时候,判断是不是和多项式一样或者全为0;

另一种情况就是剩下的位数不够下一次计算了,判断是不是全为0;以上2种都可以认为校验成功;

(



下面说一下生成CRC 校验码的三种方法:

第一种, 就是在数据上做异或计算,把生成的结果替换到原来的数据位置,然后挤掉左边的0;



第二种.利用 异或取反的特性, 直接按位取反,就不用前面提到的结果替换步骤.(上传图片太小这个限制挺不方便的....)




第三种, 利用了查表法.所谓查表法就是把提前算好的数据放到DB 里面, 然后在需要异或操作的时候,直接去数组里面提取对应的结果作为整个结果的一部分;

为什么说是一部分呢 ,因为涉及到数组大小的问题, 比如16位CRC, 每次异或的数值可能为0000-FFFF,也就是说要建立一个65536大小的数组才能满足; 去这么大的数组里面查询显然很费时间; 折中的做法就是根据多项式16#8005, 分成80 和 05 两个256 大小的数组;查询2次, 另外会在网上看到A001,这是8005 位的反向值;因为中间变换成字和还原成位的过程中需要把位顺序反向才能得到和源数据一样的顺序;这个动作也直接把多项式反转,就避免了2次字的反转;


额外的,如果把前面很长的字节换成3个字节(因为被除数(多项式)是17位,所以二个字节不够),每次计算后移位,在数量不够不够17 位的时候,呼叫更换下一个字节,就可以实现不对字节数量的限制了。有人说就只有一个字节要计算,这时候不要忘记还有后面要补的16个0,也就是说最少会有三个字节会等待被计算;


网上还有一种更简洁的计算,不是很理解公式是如何推导的,结果是对的。

基本步骤如下:

1. 初始化CRC寄存器:0xFFFF。

2. 取出一个新字节和当前crc 值计算生成新的CRC 值;;

3.右移动移位,判断是不是下一位是不是1;是1的话,再和A001 异或一次;

4.完成8次移位后,切换到第二步骤;只到最后一个字节结束;



以上程序经过了几个数测试了,相信始终有更简洁的方法等待去理解;












谋定而后动,精益求精。
您收到0封站内信:
×
×
信息提示
很抱歉!您所访问的页面不存在,或网址发生了变化,请稍后再试。