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

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

[复制链接]
攻城狮Melo 发布时间:2023-4-6 14:41
一、stm32的CRC0 [0 o! v3 s/ Q) }. M& e
        1.1 CRC的简介及MCU关联说明

$ I( x" s2 e5 W# Z4 P        STM32的CRC(Cyclic Redundancy Check,循环冗余校验)计算单元使用一个固定的多项式发生器,从一个32位的数据字产生一个CRC码。在业务开发应用中,会基于CRC的技术用于验证数据传输或存储完整性。在EN/IEC60335-1标准的范围内,它们提供了一种验证闪存(flash)完整性的方法。CRC计算单元帮助计算运行时软件的签名,并与在链接和生成该软件时产生的签名比较验证。
6 D; B6 q" |0 _7 ~cubeIDE开发, stm32调试信息串口通信输出显示_py_free的博客-CSDN博客_调试信息输出到串口
8 E. g+ f( @1 i3 X
; Q1 A' t+ l1 b- j0 ^( ]        现双击.ioc文件,打开CubeMX配置界面,开启CRC计算功能,参数保持默认设置。
" T. }( v( M* E1 ^+ k4 b0 [1 l( n3 M0 m4 `4 p0 K. B
c2c4d48e9acf416aa8e43b1cf9391ed5.png 7 h8 `$ b9 G' B. |' i9 b

4 b9 b# y( h9 ]- U+ I6 M         保存及生成输出代码
3 y- B& Q% Q; m% R7 L" G; @' p6 {

5 b4 n" H/ G  a; I6 q        2.2 CRC的HLA库分析- Q: _) y9 J4 i7 B. o/ @
        cubeMX生成代码时,会在Core源码目录下的Inc及Src目录,分别生成crc.h和crc.c驱动文件。
3 ]1 _3 k( e, p+ M2 g& b% w/ y% |! E/ q
        在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函数。; f: ]4 g% D! T
* u9 a6 H9 K# O2 H& v
d447f0adad3c4f9aa48ac88d10bf3b9e.png
# R' i1 W' W) m9 n" R! p# l% O6 d/ G1 q4 X; S- e. I3 K
         在stm32l4xx_hal_crc.c源文件中定义了HAL_CRC_Init函数,它做以下事情:诊断配置参数是否合规;调用HAL_CRC_MspInit函数完成CRC时钟开启;最后将依据参数写入CRC寄存器,如果采用默认多项式参数,写入默认多项式数值,否则调用多项式配置函数,写入用户定义数值。; U4 o9 [1 H. a* i- M2 ?; k9 v1 v
& E: D6 q+ G# f" o4 m/ p: \
fa9844c76e13484bbe0f4e62143ef7d2.png + q; o: ^) T! f# h* Y6 z# o

+ I6 t9 }7 r3 e! ]- z. X         再回到crc.c内,HAL_CRC_MspInit函数实现了CRC时钟启动设置。4 T) }' s( ]& g7 M* c
3 p( q+ L' q) V0 o
aa24df14830748a89db2472c225db0b4.png ) p$ W4 }  Y3 B  O) t& D# \
5 ~% n& A, v: q3 D2 E
         另外HLA库提供了用户自定义设置多项式参数、输入数据反转及输入数据反转的函数,方便开发这在程序代码中按需变更CRC计算方式,这些函数作为扩展功能放置在stm32l4xx_hal_crc_ex.h/c内。4 z. ^' K8 o& v/ ]
/ ~. D- S' w* j$ p% f0 F: S5 V
51d647ac690f4e0dbc794e47689c52c0.png $ o* S! @! G% D# W( X6 b  \
$ h1 G/ M! d, G4 d* A# u( C6 C3 H& N
         2.3 CRC计算功能及调用设计) E+ K' H9 E' V0 H$ @) |+ X
        在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的部分是每次计算一组数据前,都会进行数据寄存器重置7 |  b# J& k  [7 M& `
) j+ K! @$ j+ V0 {) l5 F& a3 `/ f
49ccb6008c534c3a9a559f9fa892450c.png + w* k8 b# j- k1 r7 K' q
' a# L( y" u4 Q  i; L3 T2 K) g
c8d3148af0fb4b1f9d90b0eab6e72fa8.png : Z4 ?6 ]& Z( i/ x- ^" ]3 x

  x# V9 H; L  ^" Y+ O6 D1 I         在main.c文件中,加入驱动文件支持
# y1 o0 w4 @9 _' w$ X7 p
  1. /* Private includes ----------------------------------------------------------*/
    ; T( T2 T, F& d( v# q  N) i3 c+ E
  2. /* USER CODE BEGIN Includes */
    8 V# Z" L, @9 {+ ^/ g1 |% I
  3. #include "../../ICore/key/key.h"/ m0 e2 j+ f# n* O4 h& {
  4. #include "../../ICore/led/led.h"5 `% f0 n. u1 J5 ?9 c
  5. #include "../../ICore/print/print.h"! x2 d5 T# T$ O1 A( A* q
  6. #include "../../ICore/usart/usart.h"
    $ B2 e  s; [5 r& @$ Q# o+ g0 I! \
  7. #include "../../ICore/delay/delay.h"
    $ a# E7 \" _# S6 V5 ^. x6 A+ Q
  8. /* USER CODE END Includes */
复制代码
3 U8 O: u- V* v1 o+ K: A' y

" K4 T8 I. S2 V1 U3 x/ ]        在main.c文件中,加入CRC句柄(寄存器)声明
# u5 c6 b* C* H( c( }$ l5 `
  1. /* Private user code ---------------------------------------------------------*/5 y- s4 @6 e8 h6 p
  2. /* USER CODE BEGIN 0 */8 O8 ~& [' a5 Y. b7 }6 x4 H6 k
  3. extern CRC_HandleTypeDef hcrc;
    & f5 z% d0 w. k+ O. T' y5 _- n
  4. /* USER CODE END 0 */
复制代码
( R4 S/ ?6 ~$ x5 P! v) M* q  ?2 E6 G. u
        在main函数中,加入外设驱动启用(主要是串口调试中断开启)及相关初始设置,添加了一组3个长度32bit宽的数据数组用于测试。3 ?7 e* S; `3 a
  1. /* Initialize all configured peripherals */# F2 O! s1 s7 q" w- H- o
  2.   MX_GPIO_Init();
    % c; O* F: h) q" n
  3.   MX_LPUART1_UART_Init();
    $ C' J" V. R  Q% M
  4.   MX_CRC_Init();
    . p; t) _* V! {- n8 e9 R
  5.   /* USER CODE BEGIN 2 */
    7 W& b$ p' t2 k3 j: ?
  6.   ResetPrintInit(&hlpuart1);
      M7 \0 j' x1 b1 V! Q, X, Y2 K% y
  7.   HAL_UART_Receive_IT(&hlpuart1,(uint8_t *)&HLPUSART_NewData, 1); //再开启接收中断
    & c4 j9 `+ W# S4 m5 V
  8.   HLPUSART_RX_STA = 0;, s- H* y/ P) z9 _: o1 W
  9.   //
    / M: n0 N3 }" x9 v1 y: D. z- D
  10.   printf("app restart now!\r\n");+ y2 t0 r$ V! N5 A/ v) g
  11.   uint32_t crc_input[3] = {0X12345678,0X23456789,0X34567890};
    . s3 N4 l  r; q6 Q2 C# o  M+ N% |8 a
  12.   uint32_t crc_output = 0x00;. h* n+ E0 W( s- n. @8 |) i
  13.   uint32_t crc_index = 0;
    6 d( J, Z. c* t# n% W9 |
  14.   uint8_t crc_mode = 0;
    8 d4 o  w3 q- N: y  n: n
  15.   /* USER CODE END 2 */
复制代码
       在main函数循环体中,通过按钮调用CRC计算功能,并通过lpuar1串口输出显示计算结果。" u# _: e/ v$ K
  1. /* Infinite loop */
    ; ~" [3 {' h) K3 H
  2.   /* USER CODE BEGIN WHILE */3 ]7 z5 B7 Y4 p* y; d$ k
  3.   while (1)
    ' i' A8 l7 R- Y& k6 N5 j
  4.   {
    9 N8 z2 J  ^  G/ P! a7 e
  5.             if(HLPUSART_RX_STA&0xC000){//溢出或换行,重新开始7 K% Y3 ]3 R8 I1 r4 c
  6.                     //printf("%.*s\r\n",HLPUSART_RX_STA&0X0FFF, HLPUSART_RX_BUF);" S3 N3 ]" n) c
  7.                     HLPUSART_RX_STA=0;//接收错误,重新开始
    & r* [! h; c; z
  8.                     HAL_Delay(100);//等待
    5 a% Z+ a6 c; d- ?" K
  9.             }
    3 l. c5 b; J' j' u  K
  10.           if(KEY_0())
    1 N" {" o: ]) Z5 h/ \& t, r
  11.           {9 }) V/ f8 k" i! ~" p4 e$ ~
  12.                   crc_output = HAL_CRC_Accumulate(&hcrc,crc_input,3);; `: o# |$ o& Q& F# z2 A( ~
  13.                   printf("crc_Accumulate_output:0X%08lX\r\n",crc_output);/ O6 i/ q, G  @; J1 V( E
  14.           }: M& s0 P& N+ M+ k. ~0 I1 ^
  15.           if(KEY_1())
    & e( H$ f( @% i, P
  16.             {/ c* r! z% s. W: T+ x5 @7 U9 z
  17.                   crc_output = HAL_CRC_Calculate(&hcrc,crc_input,3);- i7 I; [1 L/ V+ _3 Z) r
  18.                   printf("crc_Calculate_output:0X%08lX\r\n",crc_output);
    . |8 w$ W2 `) v' t( T. Q$ @6 L
  19.             }
    ; G- V7 ~9 H% ?( X
  20.           if(KEY_2())
    4 F( K, I' ?. U1 J
  21.             {
    2 w5 _4 p  w0 l9 l3 d6 y/ x
  22.                   crc_mode = (crc_index)%6;
    - G. {" y, b& ~. ]% b* h0 m2 p
  23.                   switch(crc_mode){
    1 u/ |; Z* e; V2 N7 p) Z& J
  24.                   case 0:
    4 z5 `" t- F8 `
  25.                           HAL_CRCEx_Output_Data_Reverse(&hcrc,CRC_OUTPUTDATA_INVERSION_ENABLE);4 Q' n2 N8 {3 v) U' p- g1 v
  26.                           printf("Output_Data_Reverse:0X%08lXU\r\n",CRC_OUTPUTDATA_INVERSION_ENABLE);3 a, u! E4 e6 W7 h, x6 p* N
  27.                           break;9 x: B$ W" v. X1 o  ^, ^
  28.                   case 1:& S( r  H2 x6 ^. s
  29.                           HAL_CRCEx_Output_Data_Reverse(&hcrc,CRC_OUTPUTDATA_INVERSION_DISABLE);) F9 _* M4 L4 b6 [7 g. z8 a
  30.                           printf("Output_Data_Reverse:0X%08XU\r\n",CRC_OUTPUTDATA_INVERSION_DISABLE);
    " }' K& z3 s: ?: M% K+ }
  31.                           break;6 `. \* W. J3 H' q
  32.                   case 2:
    & v0 o/ p& i, L5 k
  33.                           HAL_CRCEx_Input_Data_Reverse(&hcrc,CRC_INPUTDATA_INVERSION_BYTE);4 g+ M# ^7 v! T0 s3 ?8 S1 U1 b
  34.                           printf("Input_Data_Reverse:0X%08lXU\r\n",CRC_INPUTDATA_INVERSION_BYTE);4 r3 n5 i3 k! F, b
  35.                             break;4 B0 H$ A$ d: m3 s3 i7 p" ~
  36.                   case 3:. r: D/ d' y" _6 d/ f) @
  37.                           HAL_CRCEx_Input_Data_Reverse(&hcrc,CRC_INPUTDATA_INVERSION_HALFWORD);3 F5 j0 x# B& R: }7 W0 \
  38.                           printf("Input_Data_Reverse:0X%08lXU\r\n",CRC_INPUTDATA_INVERSION_HALFWORD);
    " w) d- q* H) A  ~# b( B2 U0 S1 l
  39.                           break;
    - A2 [6 d1 S! l2 n; \' N
  40.                   case 4:
    ( E' f. u: {( x" V3 c
  41.                           HAL_CRCEx_Input_Data_Reverse(&hcrc,CRC_INPUTDATA_INVERSION_WORD);
    5 C3 I, D, V5 i" h6 E1 N
  42.                           printf("Input_Data_Reverse:0X%08lXU\r\n",CRC_INPUTDATA_INVERSION_WORD);% T+ M# b0 F- R0 C# k$ }! b
  43.                             break;- K0 _! o# p5 v) L- T, l' n
  44.                   case 5:# n  d: r' `) \& N  O
  45.                           HAL_CRCEx_Polynomial_Set(&hcrc,DEFAULT_CRC32_POLY,CRC_POLYLENGTH_16B);
      B  I/ f7 i6 O# x- t# U
  46.                           printf("Polynomial_Set:0X%04XU\r\n",DEFAULT_CRC32_POLY);
    5 G  V9 u1 O9 v# ~) r
  47.                             break;' B2 n2 g% i- Q. [8 p3 D  S
  48.                   default:
    8 M* `1 }4 H- X, @; ]3 J
  49.                           break;
    $ G( h! l) N, l
  50.                   }" q+ M5 m/ I' Q2 K$ h
  51.                   crc_index++;* R7 p/ ?$ u8 n1 _
  52.             }
    # L- ?( J- _/ }# u4 e: z' B
  53.     /* USER CODE END WHILE */
复制代码
/ P+ g4 m% W9 m& n# u1 _: @$ c9 S
三、编译及测试
) J3 a2 ?0 Q! o, g2 z6 t- p5 \; x        3.1 编译下载
5 v/ @. \6 }! i3 R' n- G
9 M' o6 ~- d! X4 y
2f90fd2c88724e4fb13b8f1519dc258b.png
. m5 P/ F/ I" i% P% v8 p, H6 @7 v0 r
        3.2 测试
$ S& q1 D; e# v9 r/ i        程序开启时,默认多项式参数是0x04C11DB7U,无输入、输出反转。每按键一次KEY2改变输入反转模式或输出反转模式或多项式参数 ,然后各按键一次KEY0和KEY1, log输出如下:: A, S  p. H! @2 l3 L! v* o7 J6 @+ h) U
6 {. ^( w% r2 {2 F
11bedbc3fabc45af9a5b6994f93756d8.png
0 J( x) `/ R8 F7 _7 Z. r
$ v2 K3 {. N2 Z- G/ i6 |% w         案例只是抛砖引玉,更多CRC功能及应用拓展请自行上手代码实践。
! |' P" |+ n, C1 ^9 O& X) a  R$ _————————————————' h! d& J/ @$ H( a- ?
版权声明:py_free-物联智能
* F: `9 m# g% c6 i1 F4 f如有侵权请联系删除
) J0 T" B- K9 m, r9 n; F
! h. `4 k! o+ r6 Z1 y* a$ `+ _5 ]% @/ t3 l2 `
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管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版