<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          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.ex-cimer.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

          對(duì)應(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ì)算單

          評(píng)論


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

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();