新聞中心

        EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > STM32F10x 學(xué)習(xí)筆記4(CRC計(jì)算單元 續(xù))

        STM32F10x 學(xué)習(xí)筆記4(CRC計(jì)算單元 續(xù))

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

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

        下面先給個(gè)crc32的計(jì)算函數(shù),這個(gè)函數(shù)計(jì)算的結(jié)果與STM32F單片機(jī)上硬件單元的計(jì)算結(jié)果相同。

        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. }

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

        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,用來計(jì)算的數(shù)據(jù)
        32. *@paranBytes,數(shù)據(jù)的長度
        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

        對應(yīng)的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,用來計(jì)算的數(shù)據(jù)
        41. *@paranBytes,數(shù)據(jù)的長度
        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()*/

        不過用這個(gè)程序直接計(jì)算得到的CRC值與STM32給出的并不相同。之所以會(huì)這樣是因?yàn)樽止?jié)序的原因??梢耘e個(gè)例子來說明這個(gè)問題。比如我們有一片內(nèi)存區(qū)域要計(jì)算CRC值。這片內(nèi)存區(qū)域的起始地址是0x1000,共有8個(gè)字節(jié)。用crcCompute()函數(shù)計(jì)算時(shí)是按照地址順序依次傳入各個(gè)字節(jié)。也就是先計(jì)算0x1000處的字節(jié),再計(jì)算0x0001處的字節(jié),以此類推最后計(jì)算0x1007地址處的字節(jié)。而STM32的硬件CRC單元是以32位的字為單位計(jì)算的。我們知道CRC實(shí)際上是個(gè)多項(xiàng)式的除法運(yùn)算,而除法運(yùn)算是從高位算起的。也就是相當(dāng)于它是按照0x1003、0x1002、0x1001、0x1000這個(gè)順序計(jì)算第一個(gè)字,然后按照0x1007、0x1006、0x1005、x1004的順序計(jì)算第二個(gè)字。因此。我們要是預(yù)先將字節(jié)序調(diào)換一下得到結(jié)果就沒有問題了。這就有了下面的改造。其中remainder傳入0xffffffff。因?yàn)镾TM32中的CRC余數(shù)初始值為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()*/

        大家可以驗(yàn)證這個(gè)函數(shù)的計(jì)算結(jié)果與STM32上的結(jié)果完全一樣。

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



        關(guān)鍵詞: STM32F10xCRC計(jì)算單

        評論


        技術(shù)專區(qū)

        關(guān)閉
        主站蜘蛛池模板: 大城县| 紫金县| 聂拉木县| 烟台市| 呼玛县| 田林县| 吉首市| 曲沃县| 阜宁县| 吉水县| 兴山县| 稻城县| 丁青县| 札达县| 黑水县| 舞钢市| 洪湖市| 溧水县| 关岭| 汉阴县| 神农架林区| 台东县| 读书| 丹棱县| 武冈市| 汉沽区| 宣汉县| 和顺县| 宜宾市| 武强县| 云安县| 伊宁县| 太康县| 金塔县| 萍乡市| 梁平县| 萨嘎县| 吕梁市| 三门县| 阳信县| 应城市|