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

基于STM32CubeIDE的CubeMX配置及HAL库实现经验分享

[复制链接]
攻城狮Melo 发布时间:2023-4-6 13:44
一、STM32的随机数发生器
% e) G, s# Q( B, N2 c        1.1 RGN 简介

) M* c' [* m0 ]6 X+ j; {9 Z        STM32的RGN(Random Number Generator,随机数发生器),是一个以连续模拟噪声为基础的随机数发生器,在主机读数时提供一个由模拟量发生器产生的 32 位随机数。* P: P0 G- I3 b( j

& l3 @# g1 U. A& a2 b) u        RGN由实时熵源(模拟)和内部调节组件组成,它将全熵输出作为32位样本提供给应用程序。通常MCU中去读取两个连续随机数的间隔为 40 个 PLL48CLK时钟信号周期。产生随机数的模拟量发生器,由几个环形振荡器组成,振荡器的输出进行异或运算以产生馈入线性反馈移位寄存器(RNG_LFSR)种子,这些种子用于生成 32 位随机数。RGN支持中断功能,通过检测状态位(RNG_SR 寄存器),检测种子异常(RNG_FLAG_SECS)、时钟异常(RNG_SR_CECS)等现象,检测到错误时生成中断。# e; M* j) T$ `3 P

! C; s  B) R- Z7 q. w        1.2 RNG配置说明' U; p/ d; m0 }- F+ G( J& h
        在CubeMX上开启RNG功能非常简单,只需要激活即可,在其参数栏设置无任何参数需要设置,在NVIC栏可以开启中断功能。: @; N1 c7 v5 a* X1 m
4 \$ h2 P3 B! H/ f7 x
6c5500271ea54551b6dfb2258f57b6b1.png
& |* z8 J. m% a9 z/ n

/ d7 Q; h- L' i* L' x& }         RNG依赖时钟源可有在时钟树选择器设置,时钟频率大小可以通过倍频器、分频器设置,例如本文采用STM32L496VGTx芯片时,设置其PLL48CLK时钟依赖源PLLSAl1Q,输出时钟频率是48MHz,如下图所示。
& w$ e+ E1 [% K1 ]$ R+ j* J7 M# q" [& y1 p& M7 h/ `
bfd00a447e8b40a2ada3feff5a9db078.png
4 v# Z- U4 C0 v8 Q! H/ g4 _
: j  b" C9 g* K2 F
         STM32的RGN内部通信通常是通过AHB总线实现,例如STM32L496VGTx芯片通过AHB2总线。
& T$ A4 Z$ p% \% o2 {  ?
1 H  R5 p- o- U6 ~9 R
d07264915c5c436ab6a33677e4c23e7e.png
' r# L) d3 C/ f, o
8 y0 ^$ L8 q/ N6 V0 l. J/ ~- o1 r" P         RNG在STM32芯片正常、睡眠的工模式下有效。
/ v: `; n" X  _3 [' V! i* @7 ~6 _9 {2 V/ Z: U  V& G$ M
774abc141f7e400684de60aa97a0b5e4.png $ A4 C. p" g. c* d$ _

* H4 _! z7 j5 Y+ I6 E' Z* x         在STM32L496VGTx芯片中,RNG的寄存器空间大小为0X3FF(1024),用于存储RNG的数据寄存器、状态寄存器、控制寄存器以及缓存参数、组件信息等。2 Q' R' I  f- A3 D8 y4 _) S% s3 q( M

; x; H  c$ q! P$ ?" r
529c47a4c0b04f7ea77a8740cc6293c4.png
2 \7 ^+ P) ^/ t9 o7 B: p, N3 Z: f* i
二、创建RNG测试工程及HLA源码分析+ U1 V8 [( Z; l+ ^2 v4 o$ V: R
         2.1 工程创建
4 ]+ D& _( t* _: ^
        本文为采用的是stm32L496VGTx-ali开发板来建立测试工程,并按本专栏前面的博文移植好了lpuart1串口调试及按键功能,请自行参考。6 `1 }2 K5 D3 C% I4 U5 p9 I

9 \' i( ^$ S/ p& h7 @' f; Z1 a; W现双击.ioc文件,打开CubeMX配置界面,开启RNG功能,并开启中断,时钟树上设置最终输出频率48MHz。) A5 k2 D9 v( L& z/ X! Z
5 h5 G+ |  Z3 m2 O) V6 G9 H
6afc948c88ba476ead37ed7ea9ab24b0.png
0 `" C9 }0 P7 W8 `% L6 t# Y1 T
" B# l6 D4 t7 u# T* [4 [
6e455e8c7f2641bab92415594e07705c.png ( D" `4 h) e: z: ~6 Q
6 w9 a! M( Q/ S: h
         保成生成输出代码
1 r3 B3 E# o3 C. H9 D$ W( y9 ?: a

& V) M, U1 U: R! R  K5 h; p5 M        2.3 RNG的HLA库源码分析. Y; X( X1 [+ T2 ?1 `$ Y8 T& L. `- o
        cubeMX生成代码时,会在Core源码目录下的Inc及Src目录,分别生成rng.h和rng.c驱动文件。
# o% w! n& M# b6 m2 ~5 p% ]; s$ \
* q7 M0 p* A8 X. y9 O) K# ]' _  M0 j8 `        在rng.c文件中,主要定义了MX_RNG_Init函数和HAL_RNG_MspInit函数。MX_RNG_Init主要做两件事情,一是生成RNG句柄Instance(寄存器),二是调用HLA库的HAL_RNG_Init来实现真正的初始化设定。HAL_RNG_MspInit是HLA内的弱函数,根据实际配置CubeMX会生成新的函数,完成真正的MCU底层设置任务(MspInit,MCU Specific Package init,即指和MCU相关的初始化),覆盖原来的弱函数,而在HAL_RNG_Init函数中会调用到HAL_RNG_MspInit函数。- [' a/ h; j: Z5 E% k! h, ^

0 P% B) Y6 D* ^! E
c1aa904de5fb4cc0bdbc3d0ae144e8c5.png % u. M+ Z- Z0 k9 w3 M: L3 ~

. I% z0 [. a8 z4 U( H         在stm32l4xx_hal_rng.c源文件中定义了HAL_RNG_Init函数,它做以下事情:诊断配置参数是否合规;
7 m1 ?. G9 ^- R. S  R! P3 ~
6 i8 \, A  ?9 {1 S7 R
a14b55c38d564dfd8549ce2e8261ccab.png
' _# z+ S5 @# S* l1 C4 M9 `0 P5 ]4 b: g" r9 \. G; A3 W6 T
         以及调用HAL_RNG_MspInit函数完成CRC时钟开启及中断设置与开启(如果cubeMX配置开启中断功能的话);- t- u5 R) z- D4 ~  u( Y( f# s0 x3 `

8 r4 b/ w7 R% G. L+ S
86a0aa84e2cb442e92ff09e879d6e13a.png
' \8 A- @6 W. S! g! \+ t
5 t, F" m9 F) j# m6 A! i% ~        最后开启RNG,检测种子、数据寄存器的有效性。
) m7 s5 Q/ H  G$ g: j/ ^( I. t

# B# B* j0 i4 k; O, X6 t a7f7ea93c5124a0498a4db383d8e579f.png 0 D  i( X( Y/ z

9 E, w: J' _  F- L! U: L; l
         再回到rng.c内,HAL_RNG_MspInit函数实现了RNG外设时钟设置(如果配置依赖外设的话)与开启,以及中断设置与开启(如果cubeMX配置开启中断功能的话)。
' E8 D( S2 ]3 v/ b) D8 R& i6 n1 U9 h, j- o5 q4 p4 e2 f8 l# J, g
bd11d809b4614cf4b3c50e6427bcc79b.png
" ]' D& n3 I' a  F6 g8 [/ x* Z4 R8 P4 z& e: V
         在stm32l4xx_hal_rng.c源文件除了定义初始化功外,还定义了RNG的MSP初始化及删除函数,各种方式读取随机数函数,状态读取函数,中断请求及中断回调函数等。较常用的是:读取随机数函数如HAL_RNG_GetRandomNumber、HAL_RNG_GetRandomNumber_IT、HAL_RNG_ReadLastRandomNumber,状态读取函数HAL_RNG_GetState,以及回调函数HAL_RNG_ReadyDataCallback和HAL_RNG_ErrorCallback。' i% |" \$ ~6 a

1 V5 q. z. f( H, v$ M' Z" a" g- o0 D
ef6be0c76ac74bc58979a372f8488d21.png
/ u8 L7 b7 Y, b* [& [! |  F$ x: O
. k- o- I; F& b, y( l# _. c         2.3 RNG使用设计
7 B0 {4 z4 }: y% k, E! G$ h        由于本文开启了RNG中断功能,在rng.c源码中,重新编码HAL_RNG_ReadyDataCallback函数如下:
- M. z0 F0 j/ _5 D0 |
  1. /* USER CODE BEGIN 1 */
    - B) S. g) E2 K4 C% \
  2. void HAL_RNG_ReadyDataCallback(RNG_HandleTypeDef *hrng, uint32_t random32bit)
    3 H7 c& m% G  ~7 `9 o6 p3 p
  3. {
    5 A' U' m4 c) Z  `! h  A& N
  4.         printf("RNG_ReadyDataCallback:%lu\r\n",random32bit);
    % V6 F: P0 b1 u- \0 G
  5. }
    5 M& w- W# ?4 f  [
  6. /* USER CODE END 1 */
复制代码

2 c2 a/ ?, V( e! m; m% q  j; P5 y         在main.c源码文件中,添加各个外设及功能模块的头文件依赖。. g' F+ p( L/ F" G5 V
  1. /* Private includes ----------------------------------------------------------*/8 m* Z/ {$ \7 @, G- }; V
  2. /* USER CODE BEGIN Includes */
    4 h/ ]# G4 F: y7 A9 U
  3. #include "../../ICore/key/key.h"
    & _! K8 l0 {+ E. n! K
  4. #include "../../ICore/led/led.h"
    , x- x# I( W/ ~+ l, N7 X/ R
  5. #include "../../ICore/print/print.h"
    ' e' Q* ^- z2 G. }% W! A- [: H
  6. #include "../../ICore/usart/usart.h"
    2 V2 p6 G0 k7 ~* e' i( c. ^1 K  ^
  7. #include "../../ICore/delay/delay.h"
    & x& o* M; ?' u& k- A5 `! }
  8. /* USER CODE END Includes */
复制代码

  ~% ?6 y% ?3 S; L- q# V6 y         在main.c源码文件中,添加RNG句柄声明,用于读取随机数时使用。  h: M! g1 Z+ V9 {: ]: B, Q
  1. /* Private user code ---------------------------------------------------------*/
    6 n1 v1 a) _! B7 N! S( s; y; A
  2. /* USER CODE BEGIN 0 */
    , m  m7 F2 @" b$ ?
  3. extern RNG_HandleTypeDef hrng;' U& I+ W( b8 ~' ~+ d9 z
  4. /* USER CODE END 0 */
复制代码

- e. T$ {5 h  x6 I7 `  d& @# m         在main函数内,启动串口中断功能及初始化其他辅助参数。2 @* ]' {! I' q3 R8 q# v2 c( T2 E5 b
  1.   /* Initialize all configured peripherals */
    . ^$ K1 o$ Z, D' x' E+ C7 @) Y6 j
  2.   MX_GPIO_Init();; J1 G6 k5 u! D: z: u; y/ K
  3.   MX_LPUART1_UART_Init();+ H% M; d% M( {& P' B+ P  \8 J
  4.   MX_RNG_Init();
    $ J3 P6 o; U) @; [
  5.   /* USER CODE BEGIN 2 */
    5 ^" E5 @" c  p4 f; q3 h0 M
  6.   ResetPrintInit(&hlpuart1);4 I, w: b# S2 c" S2 {; ~
  7.   HAL_UART_Receive_IT(&hlpuart1,(uint8_t *)&HLPUSART_NewData, 1); //再开启接收中断
    5 A/ c9 y# y) Z
  8.   HLPUSART_RX_STA = 0;
    ! B% i: c& l* S
  9.   //
    % v0 L& d; q7 g% {2 Y- h6 U/ d5 G
  10.   printf("app restart now!\r\n");
    $ P) E9 t, \+ z* h. w
  11.   uint32_t rng_val = 0;2 {. o: e8 N1 a* s- a2 @+ ]1 o: B8 ]
  12.   /* USER CODE END 2 */
复制代码
. T- F9 q' D$ X& ^) G6 D6 c' b. I; v/ L
        在main函数循环体内,通过按键触发调用不同的随机数获取函数,并打印输出到lpuart1上。
9 b! U3 }+ ]8 l
  1.   /* Infinite loop */7 S& L8 s9 c2 H
  2.   /* USER CODE BEGIN WHILE */
    9 D0 @' }, R( G
  3.   while (1)5 y) @0 x4 r! U+ _4 T
  4.   {
    . K+ b6 {1 f2 n
  5.             if(HLPUSART_RX_STA&0xC000){//溢出或换行,重新开始6 h" h3 }2 H. V- ^
  6.                     //printf("%.*s\r\n",HLPUSART_RX_STA&0X0FFF, HLPUSART_RX_BUF);
    4 H) Z  n# l/ I7 o6 f9 [
  7.                     HLPUSART_RX_STA=0;//接收错误,重新开始
    3 }4 }4 Q/ m/ |& ^3 X) C& q
  8.                     HAL_Delay(100);//等待- z( K- Z: L) J+ \
  9.             }; K, n# V3 a) c  Y
  10.           if(KEY_0())
    , V5 m4 l* P0 e2 b* p) q
  11.           {
    1 ^; _. u4 u, k) }8 H2 j: f
  12.                   rng_val = HAL_RNG_GetRandomNumber(&hrng);3 M5 k# K$ ^2 X$ }$ L; ?+ O
  13.                   printf("KEY_0->RNG_GetRandomNumber:%lu\r\n",rng_val);
    7 @. Z! I$ @* i
  14.           }
    0 Z" z% I2 L& z5 f
  15.           if(KEY_1())
    3 W% f( P+ q% a" \4 c7 I% q* _; p1 g
  16.             {9 @1 d3 ~% _  B
  17.                   rng_val = HAL_RNG_GetRandomNumber_IT(&hrng);  ]( ?3 _9 x0 H9 e8 O; s
  18.                   printf("KEY_1->RNG_GetRandomNumber_IT:%lu\r\n",rng_val);; x# J$ o0 K& I/ u% x8 ]- @
  19.             }
    3 f$ U, ^3 U  e2 l* W
  20.           if(KEY_2())
    * Y# D+ m" I/ w0 D) c% B% @: P
  21.             {! X$ A" c7 Z% Z1 e% c1 b; G7 i
  22.                   rng_val = HAL_RNG_ReadLastRandomNumber(&hrng);2 y. G' P$ F& f
  23.                   printf("KEY_2->RNG_ReadLastRandomNumber:%lu\r\n",rng_val);
    0 j# ^0 f" g5 j
  24.             }5 g6 J) y# o# d1 e
  25.     /* USER CODE END WHILE */
复制代码

6 r3 y# H, n* a9 m/ R3 M0 c三、编译及测试0 t- r+ ?* l6 k  m1 Y1 E2 g8 q
        3.1 编译及下载

6 u! p6 f) X" k/ `: V        点击编译按钮确保编译正确输出,并配置运行配置后,点击运行完成下载
2 l, X: R( U2 ~7 x  q) D7 P3 K7 _# b" f7 ^& k: W. ?
5259cc9e59ce4d57b99d0423e030f230.png
( I. }: `% m4 K2 s# c* ^0 I( f. W% o
         3.2 测试7 T9 E9 V  @1 K1 r! B
        串口助手链接到开发板上,分别按键KEY0、KEY1、KEY2输出log如下图:! w& R, U0 k0 V/ b5 C, D
+ Q+ L8 G' W1 |/ x- A4 N- y! {9 x
9d0b9e5066b9489388d7a9d0d44be04c.png
2 d0 o+ X  {8 F  N. r5 k6 C; z  m' D
         由于KEY1是中断方式读取随机数,因此我们前面重写的回调函数也会生效,但需要注意的是HAL_RNG_GetRandomNumber_IT先于HAL_RNG_ReadyDataCallback,读取了数据寄存器,连个函数是分别读取数据寄存器,因此得到的随机数是不一致的,实际项目中按需选择来应用。
8 V/ i+ \& Z1 F8 l: @; E2 k* m$ Q  c
952a2c1763a0432fa35a4e1fc750eddc.png
# r6 K7 N5 c* `3 Z; g) n- z
+ ^( h4 m/ }; {# }- X# w————————————————& p- Z2 N8 w) h" g5 B) V
版权声明:py_free-物联智能5 D% h, W7 E/ C" l- B0 `
如有侵权请联系删除' `7 j) e, W& `0 Q
7 D: ~: g( ?) H$ n6 J
收藏 评论0 发布时间:2023-4-6 13:44

举报

0个回答

所属标签

相似技术帖

官网相关资源

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