你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

基于STM32CubeIDE的CRC计算及HAL库经验分享

[复制链接]
攻城狮Melo 发布时间:2023-4-6 14:41
一、stm32的CRC7 C. ?# j) {: `% C0 p- N
        1.1 CRC的简介及MCU关联说明
' U9 V* h" }  w
        STM32的CRC(Cyclic Redundancy Check,循环冗余校验)计算单元使用一个固定的多项式发生器,从一个32位的数据字产生一个CRC码。在业务开发应用中,会基于CRC的技术用于验证数据传输或存储完整性。在EN/IEC60335-1标准的范围内,它们提供了一种验证闪存(flash)完整性的方法。CRC计算单元帮助计算运行时软件的签名,并与在链接和生成该软件时产生的签名比较验证。# g8 X) F  K; Q5 F) n# X9 y
cubeIDE开发, stm32调试信息串口通信输出显示_py_free的博客-CSDN博客_调试信息输出到串口
% ?' M! c/ G; L3 _* M# l% u
" t/ u! |; ^; K6 G2 h        现双击.ioc文件,打开CubeMX配置界面,开启CRC计算功能,参数保持默认设置。8 d. _) Q! q+ L+ E) r2 Q8 T; X% w
0 {/ f( V. }3 `, d: Z
c2c4d48e9acf416aa8e43b1cf9391ed5.png / Q* [- ?4 S# a9 L7 x* ^0 `1 \' K5 L
: N. D0 |  T5 N% a' l
         保存及生成输出代码) m; ~3 }; F, H! d% [
4 n0 w  D5 ?- w  w1 a8 c  K
        2.2 CRC的HLA库分析
/ U9 `7 c, P* l/ ?# ?        cubeMX生成代码时,会在Core源码目录下的Inc及Src目录,分别生成crc.h和crc.c驱动文件。" a  |* H- a0 n" z8 p7 r

. A# h: x8 g- K        在crc.c文件中,主要定义了MX_CRC_Init函数和HAL_CRC_MspInit函数。MX_CRC_Init主要做两件事情,一是将CubeMX上配置的参数传递给CRC缓存Init和生成CRC句柄Instance(寄存器),二是调用HLA库的HAL_CRC_Init来实现真正的初始化设定。HAL_CRC_MspInit是HLA内的弱函数,根据实际配置CubeMX会生成新的函数,完成真正的MCU底层设置任务(MspInit,MCU Specific Package init,即指和MCU相关的初始化),覆盖原来的弱函数,而在HAL_CRC_Init函数中会调用到HAL_CRC_MspInit函数。( Z& ^8 l/ A! P8 r2 N  N. q# h
/ q# {. j1 \' j# u' P
d447f0adad3c4f9aa48ac88d10bf3b9e.png
7 [& r  d! M/ ^. C# H- t) i0 u6 A/ V" m7 r& b
         在stm32l4xx_hal_crc.c源文件中定义了HAL_CRC_Init函数,它做以下事情:诊断配置参数是否合规;调用HAL_CRC_MspInit函数完成CRC时钟开启;最后将依据参数写入CRC寄存器,如果采用默认多项式参数,写入默认多项式数值,否则调用多项式配置函数,写入用户定义数值。
& t7 f' x  ]: t. p1 h
1 x' k4 q1 J3 ~) y/ F$ y3 r
fa9844c76e13484bbe0f4e62143ef7d2.png + {2 c8 j( B1 v$ I
* ?& b0 F2 x* H& [" ~# m
         再回到crc.c内,HAL_CRC_MspInit函数实现了CRC时钟启动设置。
5 U% g# b1 t3 |6 K+ a$ i' j1 M/ R7 S3 A' a
aa24df14830748a89db2472c225db0b4.png ) n, k; M; [. |) P- w

$ ^0 h; |* p/ K; e& m) R         另外HLA库提供了用户自定义设置多项式参数、输入数据反转及输入数据反转的函数,方便开发这在程序代码中按需变更CRC计算方式,这些函数作为扩展功能放置在stm32l4xx_hal_crc_ex.h/c内。
0 X' p+ p! h: M, p/ s" P. B3 ^4 l
, q4 T8 ^( s+ n2 W
51d647ac690f4e0dbc794e47689c52c0.png , l, p2 x8 e: W0 E1 v
! `+ J- O. V% i
         2.3 CRC计算功能及调用设计
  O. ]- m! O! I+ H/ j3 ^        在stm32l4xx_hal_crc.c源文件除了定义初始化功外,还定义了CRC计算功能函数HAL_CRC_Accumulate和HAL_CRC_Calculate,HAL_CRC_Accumulate函数使用先前的CRC值和新的CRC值的组合来计算8、16或32位数据缓冲器的7、8、16和32位CRC值;HAL_CRC_Calculate独立于先前的CRC值,计算8、16或32位数据缓冲器的7、8、16和32位CRC值,因此它不同于HAL_CRC_Accumulate的部分是每次计算一组数据前,都会进行数据寄存器重置
# H  W5 h- J/ u0 t; `; T; X0 w, s3 y( ~
49ccb6008c534c3a9a559f9fa892450c.png
# N1 J: _. ^: U  j% b# q
2 v+ G& s0 r; }+ R& A) b
c8d3148af0fb4b1f9d90b0eab6e72fa8.png 9 N, {! T1 w; M- ]( S

$ c, H  v3 i4 u  A  ]  R         在main.c文件中,加入驱动文件支持
' d3 p$ m/ J( k! G+ i2 V1 a9 a
  1. /* Private includes ----------------------------------------------------------*/
    ( R8 `( W8 R9 }6 i& r0 g
  2. /* USER CODE BEGIN Includes */
    8 F! \4 b2 k: Q" F# C0 T
  3. #include "../../ICore/key/key.h"1 e2 j( M0 h$ i; A# v1 q; K8 s. s% y
  4. #include "../../ICore/led/led.h"& h5 v6 h/ ?! [" X' n
  5. #include "../../ICore/print/print.h"& d$ g# a* Z1 L) K# u
  6. #include "../../ICore/usart/usart.h"
    ( v* n- `8 g' K, p# T6 q7 Q
  7. #include "../../ICore/delay/delay.h"
    ' `7 n' i0 S0 T
  8. /* USER CODE END Includes */
复制代码
+ k8 q) {( l, r& H' a5 i6 u
% i4 F4 p* O: E- B/ J% `8 c
        在main.c文件中,加入CRC句柄(寄存器)声明
1 O, |. P1 q9 I
  1. /* Private user code ---------------------------------------------------------*/
    0 z9 @! I* k' R
  2. /* USER CODE BEGIN 0 */
    9 `9 \+ f- u& P  S! z
  3. extern CRC_HandleTypeDef hcrc;
    8 w, Q  t* W8 t
  4. /* USER CODE END 0 */
复制代码

' @, R% b6 H" @3 `# {( _        在main函数中,加入外设驱动启用(主要是串口调试中断开启)及相关初始设置,添加了一组3个长度32bit宽的数据数组用于测试。, m& O4 d0 W( s; v5 [2 h
  1. /* Initialize all configured peripherals */7 H% {$ {$ x6 F' H/ q
  2.   MX_GPIO_Init();
    / Z* q# w' J) }$ }1 R
  3.   MX_LPUART1_UART_Init();* D+ K, r0 D) l, k4 n/ x
  4.   MX_CRC_Init();
    # G" [9 l- C) S5 N
  5.   /* USER CODE BEGIN 2 */0 a* _2 q2 E" w
  6.   ResetPrintInit(&hlpuart1);8 M: ]6 V6 t* |6 m: _$ n! A
  7.   HAL_UART_Receive_IT(&hlpuart1,(uint8_t *)&HLPUSART_NewData, 1); //再开启接收中断) F2 J6 n8 Y2 _" H) e! T( K% i1 ~
  8.   HLPUSART_RX_STA = 0;
    * K9 H4 L& K* ~
  9.   //
    8 t9 t: ^. \$ G7 a
  10.   printf("app restart now!\r\n");9 G. D( l& q; J8 `& B
  11.   uint32_t crc_input[3] = {0X12345678,0X23456789,0X34567890};
    % E" I# f  Z# ]2 \0 Y! X$ t
  12.   uint32_t crc_output = 0x00;2 I: {, I0 T/ N7 H) p/ s- N, Z* h+ Y
  13.   uint32_t crc_index = 0;
    : Y, }' Y) D4 l) c. N
  14.   uint8_t crc_mode = 0;
    * K; B0 I$ ?  ^- Y
  15.   /* USER CODE END 2 */
复制代码
       在main函数循环体中,通过按钮调用CRC计算功能,并通过lpuar1串口输出显示计算结果。
# m5 j( B" N& c- {! e
  1. /* Infinite loop */& n" x8 r6 A! K+ E" e1 i. T
  2.   /* USER CODE BEGIN WHILE */
    1 a7 W# X) g9 O
  3.   while (1): l* G, L: ~$ a8 G" W
  4.   {
    5 ~; y" n" b5 L  N& ?, U
  5.             if(HLPUSART_RX_STA&0xC000){//溢出或换行,重新开始% ^# K4 Y; d: q) i- K0 m
  6.                     //printf("%.*s\r\n",HLPUSART_RX_STA&0X0FFF, HLPUSART_RX_BUF);0 B3 l% x) A5 E: J1 M/ M
  7.                     HLPUSART_RX_STA=0;//接收错误,重新开始
    - h' P  q7 P, I+ B+ r+ z2 G
  8.                     HAL_Delay(100);//等待& \, X% e7 }. r& C% Q) P
  9.             }0 v2 L( h) T* ~! P: y
  10.           if(KEY_0())) ^% L  B0 V8 m1 u& ^* t7 W* w* t2 q
  11.           {
    % ~! M# l5 Z0 s, a% g1 X/ [/ L7 \
  12.                   crc_output = HAL_CRC_Accumulate(&hcrc,crc_input,3);
    6 C; W) h3 v; _, X; G; l; x
  13.                   printf("crc_Accumulate_output:0X%08lX\r\n",crc_output);0 M, ~2 \6 K& _- b- E( k
  14.           }
    9 e7 H7 Z% Z1 b. x& i: ?
  15.           if(KEY_1())6 A/ v/ h/ i# Y4 t0 j* l; u' _
  16.             {
    + b) J, q0 S& ~# t7 `
  17.                   crc_output = HAL_CRC_Calculate(&hcrc,crc_input,3);
    ! n9 @5 ~: l4 V7 j; ^$ F; l# y
  18.                   printf("crc_Calculate_output:0X%08lX\r\n",crc_output);9 g3 \6 ~5 h0 H: q4 s% y+ _
  19.             }' J5 F6 Y1 m: N) i6 s4 _' G
  20.           if(KEY_2())( n! N+ R) y. D( P) d
  21.             {6 Q, f( z4 o* g$ X4 a- N% G
  22.                   crc_mode = (crc_index)%6;
    7 K( v  m6 U0 e2 ?: W* |" w, y
  23.                   switch(crc_mode){* X  H, m; A5 Z, A3 A9 z' ^: v4 {
  24.                   case 0:3 D& H* T6 j, x9 a, H# ~5 K' G
  25.                           HAL_CRCEx_Output_Data_Reverse(&hcrc,CRC_OUTPUTDATA_INVERSION_ENABLE);
    " v: A' |" e, F$ ^  B9 ~
  26.                           printf("Output_Data_Reverse:0X%08lXU\r\n",CRC_OUTPUTDATA_INVERSION_ENABLE);7 ?1 ~* ]' Y4 B# S' U
  27.                           break;0 |, ]( l4 q5 c* q: P; u% h
  28.                   case 1:
    + T' {4 K% ^2 b
  29.                           HAL_CRCEx_Output_Data_Reverse(&hcrc,CRC_OUTPUTDATA_INVERSION_DISABLE);
    : v* T3 u7 e4 `6 x/ s5 a
  30.                           printf("Output_Data_Reverse:0X%08XU\r\n",CRC_OUTPUTDATA_INVERSION_DISABLE);. @6 t  k) p7 D2 d( D
  31.                           break;+ O) B! D3 j! k
  32.                   case 2:: Y! d; [- a/ A; x1 K
  33.                           HAL_CRCEx_Input_Data_Reverse(&hcrc,CRC_INPUTDATA_INVERSION_BYTE);) C9 l# N" d  h9 L
  34.                           printf("Input_Data_Reverse:0X%08lXU\r\n",CRC_INPUTDATA_INVERSION_BYTE);
    : }0 d. q0 r4 B! ~( P- O6 v' ]2 N/ P
  35.                             break;& [5 l; E0 {0 h' K6 S" X. ?4 s
  36.                   case 3:
    7 \1 O2 `3 x8 g+ K5 E
  37.                           HAL_CRCEx_Input_Data_Reverse(&hcrc,CRC_INPUTDATA_INVERSION_HALFWORD);
    - c1 f; w3 W4 g9 y( h
  38.                           printf("Input_Data_Reverse:0X%08lXU\r\n",CRC_INPUTDATA_INVERSION_HALFWORD);! W6 i3 C0 L2 y$ N  C
  39.                           break;
    5 C9 J6 _7 g9 |# g4 A
  40.                   case 4:) C0 \9 }' d/ H! o+ z, f2 @( d
  41.                           HAL_CRCEx_Input_Data_Reverse(&hcrc,CRC_INPUTDATA_INVERSION_WORD);$ u  {' Y8 _7 k  j. e9 r+ y
  42.                           printf("Input_Data_Reverse:0X%08lXU\r\n",CRC_INPUTDATA_INVERSION_WORD);
    / Z! s' B$ K0 K% K1 W" b
  43.                             break;, n1 v# @% n! j7 W/ \5 y- p
  44.                   case 5:
    ( W7 ^* d+ O9 t$ C5 s
  45.                           HAL_CRCEx_Polynomial_Set(&hcrc,DEFAULT_CRC32_POLY,CRC_POLYLENGTH_16B);% R* W9 G5 [( z4 J# r
  46.                           printf("Polynomial_Set:0X%04XU\r\n",DEFAULT_CRC32_POLY);5 I! z# b3 {8 S$ Z7 h% N3 A
  47.                             break;
    ( ]/ h2 s1 Q7 Z6 D) I( W
  48.                   default:
    # h; X  F2 B$ G* s
  49.                           break;
    ' Q5 Y. I; Y* c( Y! D; l, L! Z
  50.                   }* Q2 H5 }& c$ k/ N+ t
  51.                   crc_index++;+ o, i" n3 x. G1 C
  52.             }
    ; B8 P8 f, [8 \/ |( R0 N! w8 `2 ?
  53.     /* USER CODE END WHILE */
复制代码
$ ~) O! z4 f4 C6 l
三、编译及测试
6 z. ~0 a9 W& I' ?        3.1 编译下载
9 P  Q) ~" x( J  z/ _7 A

- {$ D( c# k& U
2f90fd2c88724e4fb13b8f1519dc258b.png : _, R% V* b2 x( C! h

# x4 P. M7 X* h$ m: @, @        3.2 测试
8 a2 b) y" V( f/ S" T( {8 _4 H  d( v        程序开启时,默认多项式参数是0x04C11DB7U,无输入、输出反转。每按键一次KEY2改变输入反转模式或输出反转模式或多项式参数 ,然后各按键一次KEY0和KEY1, log输出如下:& D. }) F4 @$ T4 W& E% _9 t$ O0 P, F
# {) O( H- N5 ^+ Z  O: |3 W
11bedbc3fabc45af9a5b6994f93756d8.png . Y1 L! e6 a5 ?. Y
1 b$ s; E# ?1 {  }  q% N
         案例只是抛砖引玉,更多CRC功能及应用拓展请自行上手代码实践。
" e# q9 {. h0 v3 j————————————————' d- G: L! P3 T7 a
版权声明:py_free-物联智能5 F1 L3 w( o9 Q4 m( c4 |# L
如有侵权请联系删除
$ j7 e0 C/ p" q
' K0 P0 c9 e9 G% ~. r# T8 I0 d$ q: E( V: e, W& l; w& K
95e75996ff634be49a0bdafe213fd714.png
9d05f96509f146cba1ad0e0173c0923f.png
2f6ac844f7204475a733919129f29f72.png
4042774bbead4d149cc6f77becd178f4.png
47c61625b35c47a9a195d49d9fea6816.png
9c8aaa5f064a4682a3008c3b3f719478.png
e080d4f00f0c4e96b60c20d0abcab316.png
10a2e9189ff54e4b9e56fb7a81cd7bdd.png
d2bfcb5550e3433b83f52a06009840ba.png
3375d9c11b994ce8b8b7bcc88fb265e7.png
44de2117e5d64f13929724cf8a947de2.png
35ff3ea4e1844acc8c7ca553941a5fc6.png
收藏 1 评论1 发布时间:2023-4-6 14:41

举报

1个回答
过去痕迹 回答时间:2023-4-14 16:34:27

感谢分享 我想请问一下怎么用自带的CRC计算CRC16 数组类型是uint8的

uint32_t HAL_CRC_Calculate(CRC_HandleTypeDef *hcrc, uint32_t pBuffer[], uint32_t BufferLength); //只允许调用这个
static uint32_t CRC_Handle_16(CRC_HandleTypeDef *hcrc, uint16_t pBuffer[], uint32_t BufferLength);//调用需要修改static属性 不然不让用

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版