新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > STM32F10x 學習筆記4(CRC計算單元 續)

        STM32F10x 學習筆記4(CRC計算單元 續)

        作者: 時間:2016-11-20 來源:網絡 收藏
        上篇博客給出了 STM32F10X 系列單片機CRC 單元的用法。還指出了這個CRC 單元計算的結果與常見的CRC32 算法得到的結果不相同。但是為什么不相同,是什么原因造成的卻沒有寫出來。這里再補一篇,把這些都說清楚。

        本文引用地址:http://www.104case.com/article/201611/318839.htm

        下面先給個crc32的計算函數,這個函數計算的結果與STM32F單片機上硬件單元的計算結果相同。

        1. uint32_tcrc32(uint32_t*addr,intnum,uint32_tcrc)
        2. {
        3. inti;
        4. for(;num>0;num--)
        5. {
        6. crc=crc^(*addr++);
        7. for(i=0;i<32;i++)
        8. {
        9. if(crc&0x80000000)
        10. crc=(crc<<1)^POLY;
        11. else
        12. crc<<=1;
        13. }
        14. crc&=0xFFFFFFFF;
        15. }
        16. return(crc);
        17. }

        在我寫的文章《寫給嵌入式程序員的循環冗余校驗(CRC)算法入門引導》(http://blog.csdn.net/liyuanbhu/article/details/7882789)中給了個利用查表法計算crc的程序。那個程序稍微修改一點就能計算CRC32。下面給出改動后的程序。

        1. //crc32.h
        2. #ifndefCRC32_H_INCLUDED
        3. #defineCRC32_H_INCLUDED
        4. #ifdef__cplusplus
        5. #if__cplusplus
        6. extern"C"{
        7. #endif
        8. #endif/*__cplusplus*/
        9. #include
        10. /*
        11. *TheCRCparameters.CurrentlyconfiguredforCRC32.
        12. *CRC32=X32+X26+X23+X22+X16+X12+X11+X10+X8+X7+X5+X4+X2+X1+X0
        13. */
        14. #definePOLYNOMIAL0x04C11DB7
        15. #defineINITIAL_REMAINDER0xFFFFFFFF
        16. #defineFINAL_XOR_VALUE0x00000000
        17. /*
        18. *ThewidthoftheCRCcalculationandresult.
        19. *Modifythetypedefforan8or32-bitCRCstandard.
        20. */
        21. typedefuint32_twidth_t;
        22. #defineWIDTH(8*sizeof(width_t))
        23. #defineTOPBIT(1<<(WIDTH-1))
        24. /**
        25. *InitializetheCRClookuptable.
        26. *ThistableisusedbycrcCompute()tomakeCRCcomputationfaster.
        27. */
        28. voidcrcInit(void);
        29. /**
        30. *ComputetheCRCchecksumofabinarymessageblock.
        31. *@paramessage,用來計算的數據
        32. *@paranBytes,數據的長度
        33. *@noteThisfunctionexpectsthatcrcInit()hasbeencalled
        34. *firsttoinitializetheCRClookuptable.
        35. */
        36. width_tcrcCompute(unsignedchar*message,unsignedintnBytes,width_tremainder);
        37. #ifdef__cplusplus
        38. #if__cplusplus
        39. }
        40. #endif
        41. #endif/*__cplusplus*/
        42. #endif//CRC32_H_INCLUDED

        對應的C程序如下:

        1. #include"crc32.h"
        2. /*
        3. *Anarraycontainingthepre-computedintermediateresultforeach
        4. *possiblebyteofinput.Thisisusedtospeedupthecomputation.
        5. */
        6. staticwidth_tcrcTable[256];
        7. /**
        8. *InitializetheCRClookuptable.
        9. *ThistableisusedbycrcCompute()tomakeCRCcomputationfaster.
        10. */
        11. voidcrcInit(void)
        12. {
        13. width_tremainder;
        14. width_tdividend;
        15. intbit;
        16. /*Performbinarylongdivision,abitatatime.*/
        17. for(dividend=0;dividend<256;dividend++)
        18. {
        19. /*Initializetheremainder.*/
        20. remainder=dividend<<(WIDTH-8);
        21. /*ShiftandXORwiththepolynomial.*/
        22. for(bit=0;bit<8;bit++)
        23. {
        24. /*Trytodividethecurrentdatabit.*/
        25. if(remainder&TOPBIT)
        26. {
        27. remainder=(remainder<<1)^POLYNOMIAL;
        28. }
        29. else
        30. {
        31. remainder=remainder<<1;
        32. }
        33. }
        34. /*Savetheresultinthetable.*/
        35. crcTable[dividend]=remainder;
        36. }
        37. }/*crcInit()*/
        38. /**
        39. *ComputetheCRCchecksumofabinarymessageblock.
        40. *@paramessage,用來計算的數據
        41. *@paranBytes,數據的長度
        42. *@noteThisfunctionexpectsthatcrcInit()hasbeencalled
        43. *firsttoinitializetheCRClookuptable.
        44. */
        45. width_tcrcCompute(unsignedchar*message,unsignedintnBytes,width_tremainder)
        46. {
        47. unsignedintoffset;
        48. unsignedcharbyte;
        49. //width_tremainder=INITIAL_REMAINDER;
        50. /*Dividethemessagebythepolynomial,abyteatatime.*/
        51. for(offset=0;offset
        52. {
        53. byte=(remainder>>(WIDTH-8))^message[offset];
        54. remainder=crcTable[byte]^(remainder<<8);
        55. }
        56. /*ThefinalremainderistheCRCresult.*/
        57. return(remainder^FINAL_XOR_VALUE);
        58. }/*crcCompute()*/

        不過用這個程序直接計算得到的CRC值與STM32給出的并不相同。之所以會這樣是因為字節序的原因。可以舉個例子來說明這個問題。比如我們有一片內存區域要計算CRC值。這片內存區域的起始地址是0x1000,共有8個字節。用crcCompute()函數計算時是按照地址順序依次傳入各個字節。也就是先計算0x1000處的字節,再計算0x0001處的字節,以此類推最后計算0x1007地址處的字節。而STM32的硬件CRC單元是以32位的字為單位計算的。我們知道CRC實際上是個多項式的除法運算,而除法運算是從高位算起的。也就是相當于它是按照0x1003、0x1002、0x1001、0x1000這個順序計算第一個字,然后按照0x1007、0x1006、0x1005、x1004的順序計算第二個字。因此。我們要是預先將字節序調換一下得到結果就沒有問題了。這就有了下面的改造。其中remainder傳入0xffffffff。因為STM32中的CRC余數初始值為0xffffffff。

        1. uint32_tstm32crc32(uint32_t*message,unsignedintnWords,uint32_tremainder)
        2. {
        3. unsignedintoffset;
        4. unsignedcharbyte;
        5. unsignedchar*p=(unsignedchar*)message;
        6. //width_tremainder=INITIAL_REMAINDER;
        7. /*Dividethemessagebythepolynomial,abyteatatime.*/
        8. for(offset=0;offset
        9. {
        10. byte=(remainder>>(WIDTH-8))^p[3];
        11. remainder=crcTable[byte]^(remainder<<8);
        12. byte=(remainder>>(WIDTH-8))^p[2];
        13. remainder=crcTable[byte]^(remainder<<8);
        14. byte=(remainder>>(WIDTH-8))^p[1];
        15. remainder=crcTable[byte]^(remainder<<8);
        16. byte=(remainder>>(WIDTH-8))^p[0];
        17. remainder=crcTable[byte]^(remainder<<8);
        18. p+=4;
        19. }
        20. /*ThefinalremainderistheCRCresult.*/
        21. return(remainder);
        22. }/*crcCompute()*/

        大家可以驗證這個函數的計算結果與STM32上的結果完全一樣。

        寫到這里本該就結束了,不過我要多說一句,之所以要這么麻煩的調換字節序,都是小端(littleendian)惹的禍。要是都采用大端格式就沒這些麻煩的轉換了。



        關鍵詞: STM32F10xCRC計算單

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 佳木斯市| 宜兰县| 芜湖县| 屏山县| 柳州市| 湟源县| 广水市| 广河县| 定陶县| 宜君县| 莆田市| 宜章县| 叙永县| 彰化县| 墨竹工卡县| 克山县| 怀来县| 阜宁县| 柳林县| 苏尼特右旗| 布尔津县| 轮台县| 西林县| 长宁区| 葵青区| 石首市| 宣化县| 济阳县| 昌黎县| 孟津县| 陵水| 青州市| 天全县| 二连浩特市| 湘潭市| 宕昌县| 保德县| SHOW| 宁波市| 新泰市| 怀化市|