最近发现一个比较好的练手题目-CRC 校验;
循环冗余校验码(CRC),简称循环码,是一种常用的、具有检错、纠错能力的校验码,在早期的通信中运用广泛。循环冗余校验码常用于外存储器和计算机同步通信的数据校验。奇偶校验码和海明校验码都是采用奇偶检测为手段检错和纠错的(奇偶校验码不具有纠错能力),而循环冗余校验则是通过某种数学运算来建立数据位和校验位的约定关系的。---------百度百科;
CRC 手动校验的步骤:
1. 确定要使用的多项式,常用的多项式有好多,如下;

2.多项式相关的参数有width, Poly, Init, RefIn/out,XorOut; .比如此次拿CRC-4/ITU为例,
Poly:=X4+X+1=10011,扣掉首位后位0x03;Init=0x00; RefIn/out:=true; XorOut:=0x00;
3,以数据0x11为例;
0x11=0b00010001,
Init=0x00,不需要对数据前width位进行异或0xFF(取反)操作;
RefIn/Out=true; bit按MSB排列,西门子字节本身就是MSB;In的时候注意1.5个byte和2个byte的时候需要处理一下;输出的时候要MSB 切换到LSB,另外最后输出的时候需要偏移一位再输出;
XorOut:=false,不用对结果取反;
MOD2: 模2 取余;网上给有好多;下面是我手算的一些;


下面是TIA程序,目前只能计算0x0-0Xffff,;
IF #TestTrigger THEN
#step := 1;
#TestTrigger := false;
END_IF;
CASE #step OF
1://Init
FOR #i := 0 TO 23 DO
IF #i < 3 THEN
#tempIndex[#i] := 0;
END_IF;
IF #i <= 7 THEN
#bCurrentDividend[#i] := FALSE;
#bCurrentResult[#i] := FALSE;
END_IF;
IF #i <= 15 THEN
#bArray2[#i] := false;
END_IF;
#bArray3[#i] := false;
END_FOR;
#Result := 0;
#PreIndex := 5;//First index No. after the dividend;
#step := 2;
2: //
SCATTER(IN := #Input_test,
OUT => #bArray2);
FOR #i := 15 TO 0 BY -1 DO //Check Number of digits entered
IF #bArray2[#i] THEN
IF (#i + 1) MOD 4 > 0 THEN
#Space:=(#i + 1)/4+1;
ELSE
#Space:=(#i + 1)/4;
END_IF;
EXIT;
END_IF;
END_FOR;
#step := 3;
3: //RefIn
IF #Space = 3 THEN
FOR #i := 0 TO 7 DO
#tempb1 := #bArray2[#i];
#bArray2[#i]:=#bArray2[4 + #i] ;
#bArray2[4 + #i] := #tempb1;
END_FOR;
ELSIF #Space=4 THEN
FOR #i := 0 TO 7 DO
#tempb1 := #bArray2[#i];
#bArray2[#i] := #bArray2[8 + #i];
#bArray2[8 + #i] := #tempb1;
END_FOR;
END_IF;
IF #Space <= 1 THEN
#Space := 2;
ELSIF #Space = 3 THEN
#Space := 4;
END_IF;
#Inventory := #Space * 4 + #Width;
#step := 4;
4://Mod2
FOR #i := 0 TO 15 DO
#bArray3[#i] := #bArray2[#i];
END_FOR;
FOR #i := 0 TO #Space*4 DO //Get Non-0 bits to bCurrentDividend from bArray3 for the first time;
IF #bArray3[#i] THEN
FOR #j := 0 TO 4 DO
#bCurrentDividend[#j] := #bArray3[#i+#j];
END_FOR;
#PreIndex := #PreIndex + #i;
EXIT;
END_IF;
END_FOR;
WHILE #PreIndex <= #Inventory DO
FOR #i := 0 TO 4 DO
#bCurrentResult[#i] := #bCurrentDividend[#i] XOR #bPoly[#i]; //MOD 2
END_FOR;
#ComplementNo := -1;
FOR #i := 0 TO 4 DO //Get supplement No.
IF #bCurrentResult[#i] THEN
#ComplementNo := #i;
EXIT;
END_IF;
END_FOR;
IF #ComplementNo = -1 THEN
#ComplementNo := 5;
END_IF;
IF #ComplementNo < 5 THEN
FOR #i := 0 TO 4 - #ComplementNo DO //Move the rest NON-0 bit to currentDividend as first part;
#bCurrentDividend[#i] := #bCurrentResult[#ComplementNo + #i];
END_FOR;
END_IF;
//Check inventory before take out new bits
IF (#PreIndex + #ComplementNo) > #Inventory THEN
IF #Inventory - #PreIndex - 1 < 0 THEN
EXIT;
END_IF;
FOR #i := 0 TO #Inventory - #PreIndex - 1 DO
FOR #j := 0 TO 4 DO //#bCurrentResult[5] is zero and stand for the newbits from Array3;
#bCurrentResult[#j] := #bCurrentResult[#j + 1];
END_FOR;
END_FOR;
EXIT;
END_IF;
FOR #i := (4+1-#ComplementNo) TO 4 DO//Move new bits to dividend;
#bCurrentDividend[#i] := #bArray3[#PreIndex]; //Move new bits from bArray to currentDividend as second part;
#PreIndex := #PreIndex + 1; //Point to next available bit
IF #PreIndex > #Inventory THEN
EXIT;
END_IF;
END_FOR;
//If last time ComplementNo is 5,then need check the new moved 5 numbers have at least one 1, otherwise the 5 numbers is useless;
FOR #i := 0 TO 4 DO
IF #bCurrentDividend[#i] THEN
IF #i > 0 THEN
FOR #j := 0 TO 4-#i DO
#bCurrentDividend[#j] := #bCurrentDividend[#i+#j];
END_FOR;
FOR #j := 4 - #i + 1 TO 4 DO
#bCurrentDividend[#j] := #bArray3[#PreIndex];
#PreIndex := #PreIndex + 1;
IF #PreIndex >= #Inventory THEN
EXIT;
END_IF;
END_FOR;
EXIT;
ELSE
EXIT;
END_IF;
END_IF;
END_FOR;
//It's better to make a EXCEL file to have methods for any possible numbers for CRC16;
END_WHILE;
#step := 5;
5: //RefOut
GATHER(IN := #bCurrentResult, //#bCurrentResult[0]=0;[1]->Result.%X0;
OUT => #Result);
#Result := SHR(IN := #Result, N := 1);
END_CASE;
结果对比:



验证的网站
CRC(循环冗余校验)在线计算_ip33.comhttp://www.ip33.com/crc.html
CRC校验工具-ME2在线工具 (metools.info)http://www.metools.info/code/c15.html
最好用第二个,第一个可能不准确。。。
后面练习的方向:
1. 不限长度,用字节数组存储;
2. 简化程序;
3. 用STL 实现;
4. 尝试练习不同种类的Poly;
不准确的地方欢迎指出,有兴趣的小伙伴可以一起练习;