使用C语言位运算 计算CRC循环冗余校验码尾码的一种尝试:
直接上程序:
#include <stdio.h>
/*
** 用于计算数码有效位
*/
unsigned char length(unsigned char i)
{
unsigned char len;
while(i)
{
i = i>>1;
len++;
}
return len;
}
int main()
{
/*
* 由于char类型的变量最大支持255,所以实际上可以参加本运算时,最大支持0x3F,即0011 1111,也就是说要为冗余码预留位置
* 当然如果超过了,其计算也是正确的,但是只显示完整数码的后八位,剩下的需要前后段拼接一下
*
*/
unsigned char P = 0x06; //被除数
unsigned char A = 0x9C; //目标码
unsigned char n;
//
printf("除数P = %x(%d)\t 数据A = %x (%d)\t\n\r",P,P,A,A);
//
/*
* @用途:计算R的位数,也就是n,这个取决于P的位数,n = Length(P)-1
* @利用左移位进行计算,对于一个2进制非数码数,其最高位必定是1
* @变量:PTEMP =:临时存放P的值 lengthP P的长度
*/
unsigned char lengthP;
unsigned char PTEMP = P;
n=length(PTEMP)-1;
//
printf("lengthP = %x(%d) 将添加 %x(%d) 位冗余码",length(PTEMP),length(PTEMP),n,n);
//
/*//第一步
* @用途:将A进行2^n*M的运算,位数相当于A原来的位数加了n位 0(也就是P的位数减一+n)
* @变量:ATMP: A进行补位运算之后的值
*/
unsigned char ATMP = A<<n;
//
printf("\r\n变更位数之后的数据:%x(%d)",ATMP,ATMP);
printf("\n\r\n\r");
//
/*
* @ 计算其长度 和移动长度 ,将数据进行移位,并与除数进行异或,之后对原数据进行长度移位清除,先向右移动‘
* 8-length+(n+1)位,之后再向左移动8-length+(n+1)位,实现前位置零
* 然后将临时余数向左移length-(n+1)位,在高位表示,从而与上面做好准备的数据进行或运算,得到模二第一次运算的值
* @事实上这样的运算要进行length(A)-n次,所以放入while中执行即可。
* @变量:LE:每次运算的剩余数据长度 ,MLE:LE-n,第一次计算需要移动的位数,实际上每进行一次运算,MLE就减一
* ATMP2:继承ATMP; ATMPN为异或之后的临时余数 ;
* 运算的次数I = length(A)-n;
* SM: 每次异或完成之后,ATMP需要将有效位的高三位置0,才能接收临时的余数,作为下次运算的ATMP2
* 但是,只有当本次运算时的除数不为0时才能这样算,否则本次除数为0,就相当于啥都没做,所以此时SM为0
* 意思是继承上次的ATMP,不需要接收余数,只不过下次运算由于MLE减一的缘故少右移一位罢了
*/
unsigned char ATMP2 = ATMP;
unsigned char LE =length(ATMP2);
unsigned char MLE = LE -(n+1);
unsigned char ATMPN;
unsigned char I;
unsigned char Px;
I=LE-n;
int SM;
while(I>0)
{
printf("\r\n\r\n\t数据需要移动长度为%d\r\n",MLE);
ATMP2 = ATMP2>>MLE;
printf("移动后的数值为%x(%d) \t\r\n",ATMP2,ATMP2);
if((ATMP2>>n)>0){Px=P;SM=8-length(ATMP)+(n+1);}
else {Px=0;SM = 0;} //SM=0;
printf("ATMP2置位参量%d\r\n",SM);
printf("本次除数为%x(%d)",Px,Px);
ATMPN = ATMP2^Px;
printf("临时余数:%x(%d)\r\n",ATMPN,ATMPN);
ATMP2 = ATMP;
ATMP2 = ATMP2<<SM;
ATMP2 = ATMP2>>SM;
ATMP2 |= (ATMPN<<MLE);
ATMP = ATMP2;
printf("%d次计算后的数值:%x(%d) ",8-I-n+1,ATMP2,ATMP2);
I--;
MLE--;
}
printf("\r\n\r\nFCS码为%0x(%d)",ATMP,ATMP);
A = (A<<n)|ATMP;
printf("\r\n\t\t\t\t 得到的真实数据为 %0x(%d)",A,A);
}
{
由于本人也不是计算机专业,所以只能写到这样了。
此程序可以实现对6位(即最大0x3F的数据)添加2位FSC,超过6位的情况下计算出的FSC是正确的,但是最后无法显示添加后的数码。至于实现CRC只需要将while中的步骤反过来就行了。
具体思路参照注释。