色婷婷AⅤ一区二区三区|亚洲精品第一国产综合亚AV|久久精品官方网视频|日本28视频香蕉

          新聞中心

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

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

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

          本文引用地址:http://cafeforensic.com/article/201611/318839.htm

          下面先給個crc32的計算函數(shù),這個函數(shù)計算的結(jié)果與STM32F單片機上硬件單元的計算結(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)冗余校驗(CRC)算法入門引導(dǎo)》(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,用來計算的數(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,用來計算的數(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()*/

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

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

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



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

          評論


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

          關(guān)閉