C语言CRC-8 ROHC格式校验函数
CRC校验基于前处理和后处理的不同,由不同的协会标准推出了一些不同格式的版本。这里介绍CRC-8 ROHC格式的校验函数。
CRC-8 ROHC格式特征
标准CRC-8的校验函数参考: C语言标准CRC-8校验函数
CRC-8 ROHC格式有如下的不同:
- 初始值预设为0xFF
- 输入数据的每个字节做反转,这里的反转不是指每个字节里的位反(取~),而是每个字节里的位序反。也就是0x01需要反转为0x80。这里的反转是对每个字节单独进行反转,再形成新数组,不是对整个数组的所有位一起反转,所以0x01 0x02的反转是0x80 0x40而不是0x40 0x80。
- CRC计算完成得到的余数,还要做一次反转,仍然是位序反转,作为最后的输出结果
- 最后的结果要异或0x00,但任何字节数异或0x00等于其自身,故此条可省略。
- 计算的多项式为X^8 + X^2 + X^1 + 1
由上面的介绍可知,从标准CRC校验函数,调整几个方面的设计,就可形成CRC-8 MAXIM校验函数。
CRC-8 ROHC校验函数正向算法
正向算法是符合标准CRC-8的计算理论,从左向右计算,也即计算过程中移位时,向左移出。几种正向算法的实现如下:
CRC-8 ROHC格式校验函数一(8位输入数据格式,64位装载计算):
#include <stdio.h>
#include <stdlib.h>
uint8_t PY_CRC_8_ROHC(uint8_t *di, uint32_t len)
{
uint16_t crc_poly = 0x0107; //X^8+X^2+X^1+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
datain[0] ^= 0xff;
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 ROHC格式校验函数二(8位输入数据格式):
#include <stdio.h>
#include <stdlib.h>
uint8_t PY_CRC_8_S_ROHC(uint8_t *di, uint32_t len)
{
uint8_t crc_poly = 0x07; //X^8+X^2+X^1+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] ^ 0xff; //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 ROHC格式校验函数三(8位输入数据格式):
uint8_t PY_CRC_8_T_ROHC(uint8_t *di, uint32_t len)
{
uint8_t crc_poly = 0x07; //X^8+X^2+X^1+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 = 0xff; //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计算寄存器的最低字节时,对于ROHC格式,最右侧最低位实际上是高优先计算位,而校验参数要相应倒序,从而计算位置对照关系不变。
CRC-8 ROHC格式校验函数四(反向算法,8位输入数据格式):
uint8_t PY_CRC_8_T_ROHC_i(uint8_t *di, uint32_t len)
{
uint8_t crc_poly = 0xE0; //Bit sequence inversion of 0x07
uint8_t data_t = 0xff; //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 ROHC格式校验函数,反向算法最简洁。
算法验证
4种算法结果相同:
通过在线CRC工具对照验证成功:
–End–