wxleasyland@139.com
2022.7
以前写过《我学习CRC32、CRC16、CRC原理和算法的总结(与WINRAR结果一致)》长篇。经过十几年又忘记了。
这次碰到DS18B20进行CRC校验(以前都没校的),重新温了一下,补充了一下。
DS18B20是反着算的,有点难理解,所以花了点时间。
为什么反着算,如何做正算等效,这是重点。
DS18B20的CRC有很多人已经写过了,就不列举了。
这里把正算、反算CRC原理详细说明一下,算是原来文章的补充。精华都在这里了。
=========================================
【
- 直接计算法:传统计算方式计算,按位计算,一次计算1位,待测数据要先加0扩展,数据要移入寄存器,寄存器初始值必须是0。
- 驱动表法:查表就一次可以计算1字节8位,待测数据要先加0扩展,数据要移入寄存器,寄存器初始值必须是0,用“直接查询表”。
- 不扩0直接计算法:传统方式变种后快速计算,按位计算,一次计算1位,待测数据不需要加0扩展,数据不移入寄存器,寄存器可直接先放INIT预置值。
- 不扩0直驱表法:变种查表,一次可计算1字节8位,待测数据不需要加0扩展,数据不移入寄存器,寄存器可直接先放INIT预置值,用“直接查询表”(表不变)。
- 不扩0颠倒的直接计算法:用于很多硬件在发送时先发送最低位LSB的情况,一次计算1位。等同于REFIN=TRUE并且REFOUT=TRUE。
- 不扩0颠倒的直驱表法:用于REFIN=TRUE并且REFOUT=TRUE。用“正规查询表”(即“颠倒的直接查询表”)。
】
【通用简单的 按比特位 传统直接计算程序:
“计算一串字节流的8位CRC”,POLY是单片机中常见的X8+X5+X4+1(比如HTU31D湿度传感器):
再次强调一下,不要把扩展的0和数据中的0搞混:
输入数据流68 3A,则扩展00后是68 3A 00,算出CRC是7C。
输入数据流68 3A,则扩展CRC后是68 3A 7A,算出CRC是00,即校验成功。
输入数据流68 3A 00,则扩展00后是68 3A 00 00,算出CRC是85H !
即数据流68 3A和68 3A 00,CRC值是不一样的!
unsigned char CRC1_add0(unsigned char *addr, unsigned char len)
//计算8位CRC,输入是一串字节流数据。 按原始计算方式,数据需要扩展CRC位的0(或CRC值)。
//注意:这里的addr[]中已经放好了扩展的一字节0,len长度包含了扩展的0!! 即原始数据是n字节,则len=n+1!! 重要!!
//扩展的0也可以是CRC值,这样计算出来CRC值就是0
{
unsigned char crc = 0, inbyte, i;
while (len--)
{
// inbyte 存储当前参与计算的新字节
inbyte = *addr++;
for (i = 8; i; i--)
{
if(crc & 0x80) //如果要移出的高位是1,则要XOR
{
crc<<=1; //移出高位
crc+=( (inbyte & 0x80)>0 ); //移入数据位到CRC寄存器,看移入的数据位是1还是0
crc^=0x31; //POLY生成项
}