技术论坛

 CRC 练习一. CRC4-ITU_1

返回主题列表
作者 主题
1Shadow1
侠士

经验值:1130
发帖数:81
精华帖:4
楼主    2023-08-25 09:20:38
主题:CRC 练习一. CRC4-ITU_1

最近发现一个比较好的练手题目-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;

不准确的地方欢迎指出,有兴趣的小伙伴可以一起练习;

 


谋定而后动,精益求精。
您收到0封站内信:
×
×
信息提示
很抱歉!您所访问的页面不存在,或网址发生了变化,请稍后再试。