当前位置: 首页>編程日記>正文

STM32硬件CRC计算CRC8

STM32硬件CRC计算CRC8

最重要收获:了解到同一个寄存器按字节,半字和字访问的区别。同一个内存寄存器地址,强转为volitale uint8_t *类型,volitale uint16_t *类型和volitale uint32_t *类型时,若其支持按字节,半字和字访问时,这三个类型写入的结果对CPU来说是不一致的。感觉支持多类型访问的寄存器,写入低字节时,CPU记录低字节有数据更新,然后只进行低字节数据运算。低2字节有数据更新,CPU记录低2字节有变化,然后只进行低2字节数据计算。当写入4字节数据时,cpu记录4个字节均有变化,然后进行4字节数据运算。感觉一个寄存器,在CPU测有多个写入记录。

1.STM32L071单片机的硬件CRC使用,单片机手册见CRC章节介绍;

2.需注意的点:CRC输入数据按字节,半字和字反转,反转的含义即数据bit位置互换,即原数据从高位开始计算bit,则反转后从低位开始计算bit。如0x51的bit如图,其二级制为0b0101 0001,则反转即原来的0-7bit位置,依次用7-0bit位置替换,反转后结果为0x8A=0b1000 1010。如图:原来的bit0反转后变为bit7,bit1反转后为bit6,依次bit7反转后为bit0。图示的是按字节反转的结果。按半字反转即原始数据bit15变为反转后bit0,原始数据bit14变为反转后bit1,....,原始数据bit1变为反转后bit14,0原始数据bit1变为反转后bit15;按字反转即31原始数据bit变为反转后bit0,原始数据bit30变为反转后bit1,....,原始数据bit1变为反转后bit30,0原始数据bit1变为反转后bit31。如0x5128,按半字反转后结果为0x148A;数据0x51286983按字反转后结果为0xC196148A。

STM32硬件CRC支持对输入数据按字节,半字和字反转,支持对输出结果进行反转。

3.重点在于STM32硬件CRC的DR寄存器理解,手册上指出该寄存器可以按字访问,右对齐的按半字和右对齐按字节访问,需理解该访问含义。

手册上的给出DR寄存器如下描述,最后红线部分描述数据写入时的操作,可动态调整数据大小,从而减少写入的访问次数。此处的动态调整数据大小指动态调整写入DR寄存器数据的大小,DR寄存器可以按字节、半字和字访问,动态调整即为可以在写入时采用按字节,半字或字的访问方式把数据写入DR寄存器,写入访问大小在计算不同多项式因子的结果时尤为重要。如用该硬件CRC计算CRC8结果时,使用CRC8/ROHC,多项式因子为0x07,初始值0XFF,结果异或值0x00,输入数据反转,输出数据反转。

用于初始化和计算的数据代码如下

void MX_CRC_Init(void)
{hcrc.Instance = CRC;hcrc.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_DISABLE;   //不使用默认的多项式因子hcrc.Init.GeneratingPolynomial = 0x07;                         //自定义多项式因子0x07hcrc.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_DISABLE;    //不使用默认初始化值hcrc.Init.InitValue           = 0xFF;                          //自定义初始值0xFFhcrc.Init.CRCLength           = CRC_POLYLENGTH_8B;             //CRC多项式因子宽度为8hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_BYTE; //使能输入数据反转hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_ENABLE; //使能输出数据反转hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES;                  //输入数据格式为字节序if (HAL_CRC_Init(&hcrc) != HAL_OK){Error_Handler();}}uint8_t crc_buf[] = {0x55,0xaa,0x99,0x88,0x66,0x88,0x77,0x44,0x55,0x33};   //CRC结果为0xFC,正确
uint32_t crc_buf[] = {0x55,0xaa,0x99,0x88,0x66,0x88,0x77,0x44,0x55,0x33};  //CRC结果为0x8B,相当于如下数组数据,结果与每个字节后都增加了3个0x00数据
//{0x55,0x00,0x00,0x00,0xaa,0x00,0x00,0x00,0x99,0x00,0x00,0x00,0x88,0x00,0x00,0x00,0x66,0x00,0x00,0x00,0x88,0x00,0x00,0x00,0x77,0x00,0x00,0x00,0x44,0x00,0x00,0x00,0x55,0x00,0x00,0x00,0x33,0x00,0x00,0x00}
//是由于函数在写入时,数组的每个数据都会左移24位后写到DR寄存器中,此时写入DR寄存器中的数据宽度为32bit,进行CRC计算时会把DR寄存器中的所有数据均进行计算,故得出的结果与实际想要的结果不同
uint32_t crc_result = 0;
int main(void)
{MX_CRC_Init();       //初始化CRC寄存器,见上述第1行函数定义/* USER CODE BEGIN 2 */crc_result = HAL_CRC_Calculate(&hcrc,(uint32_t *)crc_buf,sizeof(crc_buf));      //CRC计算,见第32行
}uint32_t HAL_CRC_Calculate(CRC_HandleTypeDef *hcrc, uint32_t pBuffer[], uint32_t BufferLength)
{uint32_t index;      uint32_t temp = 0U;  hcrc->State = HAL_CRC_STATE_BUSY; __HAL_CRC_DR_RESET(hcrc);   //重新复位CRC寄存器,不会累积上次的CRC计算结果switch (hcrc->InputDataFormat){case CRC_INPUTDATA_FORMAT_WORDS:/* Enter 32-bit input data to the CRC calculator */for (index = 0U; index < BufferLength; index++){hcrc->Instance->DR = pBuffer[index];}temp = hcrc->Instance->DR;break;case CRC_INPUTDATA_FORMAT_BYTES:   //使用该逻辑部分计算CRC结果,按字节序格式写入数据/* Specific 8-bit input data handling  */temp = CRC_Handle_8(hcrc, (uint8_t *)pBuffer, BufferLength); //见第63行原始库代码和100行自己修改后代码break;case CRC_INPUTDATA_FORMAT_HALFWORDS:/* Specific 16-bit input data handling  */temp = CRC_Handle_16(hcrc, (uint16_t *)(void *)pBuffer, BufferLength);    /* Derogation MisraC2012 R.11.5 */break;default:break;}hcrc->State = HAL_CRC_STATE_READY;return temp;
}static uint32_t CRC_Handle_8(CRC_HandleTypeDef *hcrc, uint8_t pBuffer[], uint32_t BufferLength)//原始库代码
{uint32_t i; /* input data buffer index */uint16_t data;__IO uint16_t *pReg;uint32_t temp = 0;for (i = 0U; i < (BufferLength / 4U); i++){temp =               ((uint32_t)pBuffer[4U * i] << 24U) | \((uint32_t)pBuffer[(4U * i) + 1U] << 16U) | \((uint32_t)pBuffer[(4U * i) + 2U] << 8U)  | \(uint32_t)pBuffer[(4U * i) + 3U];hcrc->Instance->DR = temp;  //首先按字写入数据,所有写入DR寄存器的数据均进行CRC计算}if ((BufferLength % 4U) != 0U) //数据长度不是4字节对齐{if ((BufferLength % 4U) == 1U)  //余1个字节数据{*(__IO uint8_t *)(__IO void *)(&hcrc->Instance->DR) = pBuffer[4U * i]; //按字节写入,此时仅对单字节进行CRC运算,高3字节不参与CRC运算}if ((BufferLength % 4U) == 2U){data = ((uint16_t)(pBuffer[4U * i]) << 8U) | (uint16_t)pBuffer[(4U * i) + 1U];pReg = (__IO uint16_t *)(__IO void *)(&hcrc->Instance->DR);         //按半字写入,此时仅对低半字进行CRC运算,高2字节不参与CRC运算*pReg = data;}if ((BufferLength % 4U) == 3U){data = ((uint16_t)(pBuffer[4U * i]) << 8U) | (uint16_t)pBuffer[(4U * i) + 1U];pReg = (__IO uint16_t *)(__IO void *)(&hcrc->Instance->DR);                    /* Derogation MisraC2012 R.11.5 */*pReg = data;*(__IO uint8_t *)(__IO void *)(&hcrc->Instance->DR) = pBuffer[(4U * i) + 2U];  /* Derogation MisraC2012 R.11.5 */}}return hcrc->Instance->DR;
}
static uint32_t CRC_Handle_8(CRC_HandleTypeDef *hcrc, uint8_t pBuffer[], uint32_t BufferLength)//自己修改的代码
{uint32_t i; /* input data buffer index */for (i = 0U; i < BufferLength; i++){*(__IO uint8_t *)(__IO void *)(&hcrc->Instance->DR) = pBuffer[i]; //按字节写入,此时仅对单字节进行CRC运算,高3字节不参与CRC运算}return hcrc->Instance->DR;
}

最初把crc_buf类型设置为uint32_t类型,最后计算得出的CRC结果不正确结果为0x8B,实际与如下图结果一致,把类型设置为uint8_t类型后结果正确结果为0xFC。

使用CRC_Handle_8原始库代码和自己修改的代码,计算结果都是0xFC。从中可以清楚的看到DR寄存器按字节,按半字和按字访问的区别。按字访问时,写入DR寄存器中的所有数据均参与运算,即32bit数据均参与运算。按半字访问时,DR寄存器的低2字节参与CRC运算;按字访问时,DR寄存器的低字节参与CRC运算。按字节访问即把hcrc->Instance->DR地址强转为volitale uint8_t *类型,按半字访问即把hcrc->Instance->DR地址强转为volitale uint16_t *类型.


https://www.fengoutiyan.com/post/15571.html

相关文章:

  • stc算法
  • STM32硬件SPI扩展
  • stm32的硬件
  • stc单片机编程100例
  • stc烧写
  • crc32 verilog
  • stc有32位单片机吗
  • 如何计算电脑电源需求
  • 鏡像模式如何設置在哪,圖片鏡像操作
  • 什么軟件可以把圖片鏡像翻轉,C#圖片處理 解決左右鏡像相反(旋轉圖片)
  • 手機照片鏡像翻轉,C#圖像鏡像
  • 視頻鏡像翻轉軟件,python圖片鏡像翻轉_python中鏡像實現方法
  • 什么軟件可以把圖片鏡像翻轉,利用PS實現圖片的鏡像處理
  • 照片鏡像翻轉app,java實現圖片鏡像翻轉
  • 什么軟件可以把圖片鏡像翻轉,python圖片鏡像翻轉_python圖像處理之鏡像實現方法
  • matlab下載,matlab如何鏡像處理圖片,matlab實現圖像鏡像
  • 圖片鏡像翻轉,MATLAB:鏡像圖片
  • 鏡像翻轉圖片的軟件,圖像處理:實現圖片鏡像(基于python)
  • canvas可畫,JavaScript - canvas - 鏡像圖片
  • 圖片鏡像翻轉,UGUI優化:使用鏡像圖片
  • Codeforces,CodeForces 1253C
  • MySQL下載安裝,Mysql ERROR: 1253 解決方法
  • 勝利大逃亡英雄逃亡方案,HDU - 1253 勝利大逃亡 BFS
  • 大一c語言期末考試試題及答案匯總,電大計算機C語言1253,1253《C語言程序設計》電大期末精彩試題及其問題詳解
  • lu求解線性方程組,P1253 [yLOI2018] 扶蘇的問題 (線段樹)
  • c語言程序設計基礎題庫,1253號C語言程序設計試題,2016年1月試卷號1253C語言程序設計A.pdf
  • 信奧賽一本通官網,【信奧賽一本通】1253:抓住那頭牛(詳細代碼)
  • c語言程序設計1253,1253c語言程序設計a(2010年1月)
  • 勝利大逃亡英雄逃亡方案,BFS——1253 勝利大逃亡
  • 直流電壓測量模塊,IM1253B交直流電能計量模塊(艾銳達光電)
  • c語言程序設計第三版課后答案,【渝粵題庫】國家開放大學2021春1253C語言程序設計答案
  • 18轉換為二進制,1253. 將數字轉換為16進制
  • light-emitting diode,LightOJ-1253 Misere Nim
  • masterroyale魔改版,1253 Dungeon Master
  • codeformer官網中文版,codeforces.1253 B
  • c語言程序設計考研真題及答案,2020C語言程序設計1253,1253計算機科學與技術專業C語言程序設計A科目2020年09月國家開 放大學(中央廣播電視大學)
  • c語言程序設計基礎題庫,1253本科2016c語言程序設計試題,1253電大《C語言程序設計A》試題和答案200901
  • 肇事逃逸車輛無法聯系到車主怎么辦,1253尋找肇事司機