C语言CRC-8 MAXIM格式校验函数

C语言CRC-8 MAXIM格式校验函数

CRC校验基于前处理和后处理的不同,由不同的公司推出了一些不同格式的版本。这里介绍CRC-8 MAXIM格式的校验函数。

CRC-8 MAXIM格式特征

标准CRC-8的校验函数参考: C语言标准CRC-8校验函数
CRC-8 MAXIM格式有如下的不同:

  1. 输入数据的每个字节做反转,这里的反转不是指每个字节里的位反(取~),而每个字节里的位序反。也就是0x01需要反转为0x80。这里的反转是对每个字节单独进行反转,再形成新数组,不是对整个数组的所有位一起反转,所以0x01 0x02的反转是0x80 0x40而不是0x40 0x80。
  2. CRC计算完成得到的余数,还要做一次反转,仍然是位序反转,作为最后的输出结果
  3. 最后的结果要异或0x00,但任何字节数异或0x00等于其自身,故此条可省略。
  4. 计算的多项式为X^8 + X^5 + X^4 + 1, 不同于标准CRC-8采用的X^8 + X^2 + X^1 +1
    由上面的介绍可知,从标准CRC校验函数,调整三个方面的设计,就可形成CRC-8 MAXIM校验函数。

CRC-8 MAXIM校验函数正向算法

正向算法是符合标准CRC-8的计算理论,从左向右计算,也即计算过程中移位时,向左移出。几种正向算法的实现如下:

CRC-8 MAXIM格式校验函数一(8位输入数据格式,64位装载计算):

#include <stdio.h>
#include <stdlib.h>

uint8_t PY_CRC_8_MAXIM(uint8_t *di, uint32_t len)
{   //Written by Pegasus Yu 2022/09/07
	uint16_t crc_poly = 0x0131; //X^8+X^5+X^4+1 total 9 effective bits. Computed total data shall be compensated 8-bit '0' before CRC computing.
	uint8_t *datain;
	uint64_t cdata = 0; //Computed total data
	uint16_t data_t = 0; //Process data of CRC computing

	uint16_t index_t = 63;  ///bit shifting index for initial '1' searching
	uint16_t index = 63;    //bit shifting index for CRC computing
	uint8_t rec = 0; //bit number needed to be compensated for next CRC computing

	uint32_t cn=(len+1)/7;
	uint32_t cr=(len+1)%7;

	uint32_t j;

	datain = malloc(len+1);
	for(j=0;j<len;j++)  //bit sequence inversion for input bytes
	{
		datain[j]=0;
		for(uint32_t m=0; m<8; m++)
		{
			datain[j] <<= 1;
			datain[j] |= ((di[j]>>m)&0x01);
		}
	}
	    datain[len]=0; //Compensate 8-bit '0' for input data

     if(len<=7)
     {
    	 for(j=0;j<=len;j++)
    	 {
    		 cdata = (cdata<<8);
    		 cdata = cdata|datain[j];
    	 }
    	 cn = 1;
     }
     else
     {
    	 if(cr==0)
    	 {
    		 cr=7;
    	 }
    	 if(cr==1)
    	 {
    		 cr=8;
    	 }
    	 else
    	 {
    		 cn++;
    	 }

    	 for(j=0;j<cr;j++)
    	 {
    		 cdata = (cdata<<8);
    		 cdata = cdata|datain[j];
    	 }
     }

     do
     {
 		cn--;

 		while(index_t>0)
 		{
 			if( (cdata>>index_t)&1 )
 			{
 				index = index_t;
 				index_t = 0;

 				data_t |= (cdata>>(index-8));
 				{
 					data_t = data_t ^ crc_poly;
 				}

 	            while((index!=0x5555)&&(index!=0xaaaa))
 	            {
 	            	/*
 	    			if ((data_t>>7)&1) rec = 1;
 	    			else if ((data_t>>6)&1) rec = 2;
 	    			else if ((data_t>>5)&1) rec = 3;
 	    			else if ((data_t>>4)&1) rec = 4;
 	    			else if ((data_t>>3)&1) rec = 5;
 	    			else if ((data_t>>2)&1) rec = 6;
 	    			else if ((data_t>>1)&1) rec = 7;
 	    			else if ((data_t>>0)&1) rec = 8;
 	    			else rec = 9; */

	 	    		for(uint8_t n=1;n<9;n++)
	 	    		{
	 	    			if ((data_t>>(8-n))&1) {rec = n;break;}
	 	    			if (n==8) rec=9;
	 	    		}

 	    			if((index-8)<rec)
 	    			{
 	    				data_t = data_t<<(index-8);
 	    				data_t |=  (uint16_t)((cdata<<(64-(index-8)))>>(64-(index-8)));
 	    				index = 0x5555;
 	    			}
 	    			else
 	    			{
 	        			for(uint8_t i=1;i<=rec;i++)
 	        			{
 	        				data_t = (data_t<<1)|((cdata>>(index-8-i))&1) ;
 	        			}

 	        			if(rec!= 9)
 	        			{
 	        				data_t = data_t ^ crc_poly;
 	        				index -= rec;
 	        			}
 	        			else
 	        			{
 	        				data_t = 0;
 	        				index_t = index-8-1;
 	        				index = 0xaaaa;

 	        			}

 	    			}

 	            }
 				if(index==0x5555) break;
 			}
 			else
 			{
 				index_t--;
 				if(index_t<8) break;
 			}
         }

 		if(cn>0)
 		{
  			cdata = data_t&0x00ff;

 			for(uint8_t k=0;k<7;k++)
 			{
 	    		 cdata = (cdata<<8);
 	    		 cdata = cdata|datain[j++];

 			}

 	    	data_t = 0;
 	 		index_t = 63;  ///bit shifting index for initial '1' searching
 	 		index = 63;    //bit shifting index for CRC computing
 	 		rec = 0; //bit number needed to be compensated for next CRC computing
 		}

     }
     while(cn>0);

     //bit sequence inversion for output byte
     datain[0] = data_t;
     data_t = 0;
	 for(uint32_t m=0; m<8; m++)
	{
		data_t <<= 1;
		data_t |= ((datain[0]>>m)&0x01);
	}

     free(datain);
     return data_t;

}

CRC-8 MAXIM格式校验函数二(8位输入数据格式):

#include <stdio.h>
#include <stdlib.h>
uint8_t PY_CRC_8_S_MAXIM(uint8_t *di, uint32_t len)
{
	uint8_t crc_poly = 0x31; //X^8+X^5+X^4+1 total 8 effective bits without X^8. Computed total data shall be compensated 8-bit '0' before CRC computing.

	uint32_t clen = len+1;
	uint8_t cdata[clen] ;

	for(uint32_t j=0;j<len;j++)  //bit sequence inversion for input bytes
	{
		cdata[j]=0;
		for(uint32_t m=0; m<8; m++)
		{
			cdata[j] <<= 1;
			cdata[j] |= ((di[j]>>m)&0x01);
		}
	}
	cdata[len]=0; //Compensate 8-bit '0' for input data

	uint8_t data_t = cdata[0]; //CRC register

    for (uint32_t i = 1; i < clen; i++)
    {
        for (uint8_t j = 0; j <= 7; j++)
        {
            if(data_t&0x80)
            	data_t = ( (data_t<<1) | ( (cdata[i]>>(7-j))&0x01) ) ^ crc_poly;
            else
            	data_t = ( (data_t<<1) | ( (cdata[i]>>(7-j))&0x01) ) ;
        }
    }

    //bit sequence inversion for output byte
    cdata[0] = data_t;
    data_t = 0;
	 for(uint32_t m=0; m<8; m++)
	{
		data_t <<= 1;
		data_t |= ((cdata[0]>>m)&0x01);
	}
    return data_t;
}

CRC-8 MAXIM格式校验函数三(8位输入数据格式):

uint8_t PY_CRC_8_T_MAXIM(uint8_t *di, uint32_t len)
{
	uint8_t crc_poly = 0x31; //X^8+X^5+X^4+1 total 8 effective bits without X^8.
	uint32_t clen = len+1;
	uint8_t cdata[clen] ;

	for(uint32_t j=0;j<len;j++)  //bit sequence inversion for input bytes
	{
		cdata[j]=0;
		for(uint32_t m=0; m<8; m++)
		{
			cdata[j] <<= 1;
			cdata[j] |= ((di[j]>>m)&0x01);
		}
	}
	cdata[len]=0; //Compensate 8-bit '0' for input data

	uint8_t data_t = 0; //CRC register

    for (uint32_t i = 0; i < len; i++)
    {
    	data_t ^=  cdata[i];
        for (int8_t i=8; i>0; --i)
        {
            if (data_t & 0x80)
            	data_t = (data_t<<1) ^ crc_poly;
            else
            	data_t = (data_t<<1);
        }
    }

    //bit sequence inversion for output byte
    cdata[0] = data_t;
    data_t = 0;
	 for(uint32_t m=0; m<8; m++)
	{
		data_t <<= 1;
		data_t |= ((cdata[0]>>m)&0x01);
	}
    return data_t;
}

反向算法

反向算法是从由右向左计算,也即计算过程中移位时,向右移出。而计算过程中的输入数据高优先计算位和校验参数的对齐关系不变。因此把一个字节放在CRC计算寄存器的最低字节时,对于MAXIM格式,最右侧最低位实际上是高优先计算位,而校验参数要相应倒序,从而计算位置对照关系不变。

CRC-8 MAXIM格式校验函数四(反向算法,8位输入数据格式):

uint8_t PY_CRC_8_T_MAXIM_i(uint8_t *di, uint32_t len)
{
	uint8_t crc_poly = 0x8C; //Bit sequence inversion of 0x31
	uint8_t data_t = 0; //CRC register

    for(uint32_t i = 0; i < len; i++)
    {
    	data_t ^= di[i]; //8-bit data

        for (uint8_t j = 0; j < 8; j++)
        {
            if (data_t & 0x01)
            	data_t = (data_t >> 1) ^ crc_poly;
            else
            	data_t >>= 1;
        }
    }

    return data_t;
}

可见对于CRC-8 MAXIM格式校验函数,反向算法最简洁。

算法验证

4种算法结果相同:

在这里插入图片描述

通过在线CRC工具对照验证成功:
在这里插入图片描述

–End–

CRC-8-MAXIM是一种常用的循环冗余校验(Checksum)算法,它在8位数据上生成一个校验位用于检测数据传输过程中的错误。C语言中实现CRC-8-MAXIM的步骤如下: 1. 定义常数:CRC-8-MAXIM使用固定的寄存器长度(通常是8位),以及特定的多项式。例如,MAXIM公司的标准多项式可能是0x31(二进制为100001),对应于十进制的5。 2. 初始化:创建一个初始值(通常是一个全零字节),这个值会在计算过程中按位异或操作,直到达到CRC状态。 3. 应用比特流:对于每个输入的数据位,将其按位左移并与CRC当前值做异或运算,同时将最高位丢弃(因为CRC-8采用的是奇偶校验)。 4. 计算循环:重复上述步骤,直到所有数据位处理完毕。 5. 纠错:如果接收到的CRC校验码与本地计算的结果不符,则表明数据可能有误。 以下是简单的C代码示例: ```c #include <stdio.h> #include <stdint.h> // CRC-8-MAXIM多项式 uint8_t crc_poly = 0x31; uint8_t crc8_update(uint8_t data, uint8_t *crc) { // 高位丢弃 data >>= 1; uint8_t temp = *crc ^ data; // 更新CRC *crc = (temp << 1) ^ crc_poly; return *crc; } uint8_t crc8_calculate(const uint8_t *data, size_t len) { uint8_t crc = 0xFF; // 初始值全1,等效于全0,取决于多项式 for (size_t i = 0; i < len; ++i) { crc = crc8_update(data[i], &crc); } return crc; } int main() { const uint8_t input[] = {0x1A, 0x2B, 0x3C}; uint8_t calculated_crc = crc8_calculate(input, sizeof(input)); printf("Calculated CRC: %02X\n", calculated_crc); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

PegasusYu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值