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

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

[复制链接]
攻城狮Melo 发布时间:2023-4-6 13:44
一、STM32的随机数发生器
" g2 ~7 a* z. m! J9 _/ `% l        1.1 RGN 简介

+ W$ i, m$ \. K9 u0 U        STM32的RGN(Random Number Generator,随机数发生器),是一个以连续模拟噪声为基础的随机数发生器,在主机读数时提供一个由模拟量发生器产生的 32 位随机数。- E- q- ], g; p) p7 Z% s+ ?

! ^0 H1 M3 [1 f& l        RGN由实时熵源(模拟)和内部调节组件组成,它将全熵输出作为32位样本提供给应用程序。通常MCU中去读取两个连续随机数的间隔为 40 个 PLL48CLK时钟信号周期。产生随机数的模拟量发生器,由几个环形振荡器组成,振荡器的输出进行异或运算以产生馈入线性反馈移位寄存器(RNG_LFSR)种子,这些种子用于生成 32 位随机数。RGN支持中断功能,通过检测状态位(RNG_SR 寄存器),检测种子异常(RNG_FLAG_SECS)、时钟异常(RNG_SR_CECS)等现象,检测到错误时生成中断。) L" u; a6 ?0 V; W5 S1 n6 n
9 i  f* Z  \9 |1 g' I
        1.2 RNG配置说明
, \' b( s( y: K" R7 Y) M        在CubeMX上开启RNG功能非常简单,只需要激活即可,在其参数栏设置无任何参数需要设置,在NVIC栏可以开启中断功能。( `7 E. X0 ~: c
) u$ I' |! X9 l0 f
6c5500271ea54551b6dfb2258f57b6b1.png
! }  d- k7 i* x( O/ L. R6 v+ v

! N+ h" p; t% {' r0 Z         RNG依赖时钟源可有在时钟树选择器设置,时钟频率大小可以通过倍频器、分频器设置,例如本文采用STM32L496VGTx芯片时,设置其PLL48CLK时钟依赖源PLLSAl1Q,输出时钟频率是48MHz,如下图所示。( w: P( a% X/ ]

' R% u7 ~+ }5 ]! R% Q' j. e
bfd00a447e8b40a2ada3feff5a9db078.png " O; g/ P4 @5 @4 d* h

9 P9 [$ D) O/ _! z) [
         STM32的RGN内部通信通常是通过AHB总线实现,例如STM32L496VGTx芯片通过AHB2总线。% c% z: c8 T8 R3 c2 ^6 |
  k  j2 K1 g# s/ F* `6 C+ ~
d07264915c5c436ab6a33677e4c23e7e.png ( Z/ ?1 m9 K4 D8 R% v6 ?& A
( A3 R0 E# j6 D6 K7 f: X5 j8 ~9 \
         RNG在STM32芯片正常、睡眠的工模式下有效。
3 Y, h" ^4 q& i7 H# V, Y' G/ W2 C4 l& ^
774abc141f7e400684de60aa97a0b5e4.png - J! @" B) i6 n5 N5 d9 D/ {' _

8 S* `0 \9 r% ~! t2 o         在STM32L496VGTx芯片中,RNG的寄存器空间大小为0X3FF(1024),用于存储RNG的数据寄存器、状态寄存器、控制寄存器以及缓存参数、组件信息等。
  d. T( x  ?" _- _6 b5 h9 p
- B' x9 r- h7 u( L0 z- o) U6 ]
529c47a4c0b04f7ea77a8740cc6293c4.png 7 o4 Q8 B% m6 W5 ~" \+ E
; O/ k% w  p; A8 F
二、创建RNG测试工程及HLA源码分析
& O' ]! ?) l2 q3 C7 q. ?5 y( E1 C: h         2.1 工程创建

7 u) l. h0 n) s) V7 m) v$ L        本文为采用的是stm32L496VGTx-ali开发板来建立测试工程,并按本专栏前面的博文移植好了lpuart1串口调试及按键功能,请自行参考。" Z# Z& Z) f4 k+ Q- U

! q+ C: G0 J. b* T1 p现双击.ioc文件,打开CubeMX配置界面,开启RNG功能,并开启中断,时钟树上设置最终输出频率48MHz。; s5 O5 R7 U' p/ z( ]

/ y1 q& F* K5 R5 }8 T
6afc948c88ba476ead37ed7ea9ab24b0.png
' C! P- w$ A" @/ ?% x, k8 J
9 r/ u# w% Q: W. n
6e455e8c7f2641bab92415594e07705c.png 0 z+ W2 ~* ?2 z2 _1 S  g
( M/ g1 J3 o" T' a: u+ k
         保成生成输出代码
8 r1 z' @% P5 x1 ^& C
( [0 i( L. [- `# K5 V( \7 e* B$ k0 r+ ^
        2.3 RNG的HLA库源码分析5 f5 U0 R  n; D( B" ^
        cubeMX生成代码时,会在Core源码目录下的Inc及Src目录,分别生成rng.h和rng.c驱动文件。
8 r' L2 \- \3 O4 [
5 _- `' y9 t0 ?9 m1 x3 X- H        在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函数。4 a6 [& _4 _( o, x& g% w/ F

( c6 A# t& [* b! B1 a0 D- Z1 y
c1aa904de5fb4cc0bdbc3d0ae144e8c5.png
% l, W" p. j' r% e
/ T5 c) `4 R1 y/ i  n         在stm32l4xx_hal_rng.c源文件中定义了HAL_RNG_Init函数,它做以下事情:诊断配置参数是否合规;
, v9 V, b& y, i5 k( z9 `+ `# b+ t0 T( P6 S( A' W6 [4 _/ ]1 H8 J" o
a14b55c38d564dfd8549ce2e8261ccab.png 9 w) }4 L( M. U

) [+ B' H+ \0 L( `+ H: n         以及调用HAL_RNG_MspInit函数完成CRC时钟开启及中断设置与开启(如果cubeMX配置开启中断功能的话);
5 l; c3 ?3 i0 C, n
, b! }: ?& e, y5 Y1 V
86a0aa84e2cb442e92ff09e879d6e13a.png - u* [1 F5 ?" u3 k
9 X' N% i9 P/ m6 X% X, @
        最后开启RNG,检测种子、数据寄存器的有效性。5 K: ^3 ]0 M* \6 ^/ e

- I, _3 a$ k0 t3 W a7f7ea93c5124a0498a4db383d8e579f.png ) U+ m" ^, Y  z, w& ^1 p
( A% F, }# {' c
         再回到rng.c内,HAL_RNG_MspInit函数实现了RNG外设时钟设置(如果配置依赖外设的话)与开启,以及中断设置与开启(如果cubeMX配置开启中断功能的话)。- O- h% T  A0 [# t+ g6 M- y* a

, z2 ^# T2 w; F& ]
bd11d809b4614cf4b3c50e6427bcc79b.png ( `+ U" R- G; B+ Y( C( R! K- E- P2 T9 c

& l& w1 Q" E8 ^4 R% X, h* ?% U         在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。0 t' A1 @/ d! x0 N, t

) W0 h; U& E, d# N  g9 b! Z! ~+ l
ef6be0c76ac74bc58979a372f8488d21.png - h/ n  z" ~1 j6 [

& A1 s9 c. y% p# U' z2 F" C0 Y+ a         2.3 RNG使用设计
- ^( _  Z# b2 z5 f7 \# I+ \* d        由于本文开启了RNG中断功能,在rng.c源码中,重新编码HAL_RNG_ReadyDataCallback函数如下:
1 ~: h/ U/ K" I
  1. /* USER CODE BEGIN 1 */& p3 G5 U0 w& G# f3 G% D7 c( Z7 G
  2. void HAL_RNG_ReadyDataCallback(RNG_HandleTypeDef *hrng, uint32_t random32bit)
    # z$ a' R- h3 [$ c8 h. D! X
  3. {
    4 s+ I  M: E# |
  4.         printf("RNG_ReadyDataCallback:%lu\r\n",random32bit);
    + Y% @- y8 w- X; X
  5. }' C( M6 O0 y" b& Z
  6. /* USER CODE END 1 */
复制代码
- L0 m4 x0 s2 s# B; k/ m
         在main.c源码文件中,添加各个外设及功能模块的头文件依赖。9 Z7 m$ R0 G# t7 C3 U
  1. /* Private includes ----------------------------------------------------------*/
    " C% q+ W9 Q( y
  2. /* USER CODE BEGIN Includes */( S; N) D/ ?& \8 e; h% h
  3. #include "../../ICore/key/key.h"
    9 \& a/ H% ~# M1 M+ Q
  4. #include "../../ICore/led/led.h"
    * ~: m7 B& |% l, W0 {5 N
  5. #include "../../ICore/print/print.h"
    ) s" h$ `9 b. u
  6. #include "../../ICore/usart/usart.h"
    ( [' P, s( n* X( [
  7. #include "../../ICore/delay/delay.h"
      }/ W- x4 |7 {8 `: p( d* \3 \
  8. /* USER CODE END Includes */
复制代码

5 v5 W) |: y1 e% D; C         在main.c源码文件中,添加RNG句柄声明,用于读取随机数时使用。3 L8 o# O3 d6 l* _9 B3 c# u
  1. /* Private user code ---------------------------------------------------------*/
    2 n- l' x, P% l* Y. O; x
  2. /* USER CODE BEGIN 0 */
    , ~1 ?8 N" h+ U+ M
  3. extern RNG_HandleTypeDef hrng;
    & O8 o3 `; o: j% ^$ }
  4. /* USER CODE END 0 */
复制代码

. p, _7 G( A+ f- t! {         在main函数内,启动串口中断功能及初始化其他辅助参数。
/ j1 R0 A8 O. N; C+ I6 x. D
  1.   /* Initialize all configured peripherals */
    4 h( p! X- U, U
  2.   MX_GPIO_Init();
    ! b+ I2 p# ?/ S" v6 y9 L, A
  3.   MX_LPUART1_UART_Init();4 N' c7 U% y: _) h$ ]: X
  4.   MX_RNG_Init();& c/ q# @/ \2 p! x' C" ]
  5.   /* USER CODE BEGIN 2 */5 w3 H- s/ R2 E  I  Z/ ]- d
  6.   ResetPrintInit(&hlpuart1);
    : |3 k3 {. g" N( S  V/ B  Q
  7.   HAL_UART_Receive_IT(&hlpuart1,(uint8_t *)&HLPUSART_NewData, 1); //再开启接收中断
    ) `: H& `; T6 {( Z4 r
  8.   HLPUSART_RX_STA = 0;3 N2 _5 h% E1 O) L
  9.   //+ s/ G6 Z& n4 [, e& R$ P3 d& d
  10.   printf("app restart now!\r\n");
    . K* N% ^" s1 a: [% \! d, ?
  11.   uint32_t rng_val = 0;2 Z  @$ Y1 l5 A# t3 I. s( }. z1 {
  12.   /* USER CODE END 2 */
复制代码

# R# ?+ d( Z4 E4 _1 Y% Z, s) k        在main函数循环体内,通过按键触发调用不同的随机数获取函数,并打印输出到lpuart1上。3 v7 Y' H5 `( [% [( a* S8 f  f
  1.   /* Infinite loop *// s/ I7 J; b' {
  2.   /* USER CODE BEGIN WHILE */7 M1 K" j: R/ k/ N
  3.   while (1)! h6 K4 c9 h5 b) _
  4.   {# b! p, X" A& y5 v( ?6 `
  5.             if(HLPUSART_RX_STA&0xC000){//溢出或换行,重新开始6 K. b, w9 ?6 e, w' s
  6.                     //printf("%.*s\r\n",HLPUSART_RX_STA&0X0FFF, HLPUSART_RX_BUF);: e% T% m5 P7 L, H4 v
  7.                     HLPUSART_RX_STA=0;//接收错误,重新开始
    % J3 ^; m7 G$ d$ m
  8.                     HAL_Delay(100);//等待- P8 Z6 x2 y: C5 d, R  O3 C
  9.             }
    . ]& u- e$ o+ F  z
  10.           if(KEY_0())
      W- L" Q! O; a" ?
  11.           {
    : D, |% z4 O; ?1 n/ L; c
  12.                   rng_val = HAL_RNG_GetRandomNumber(&hrng);
    ! Q8 J/ e; S4 W: a  A% P& E7 [
  13.                   printf("KEY_0->RNG_GetRandomNumber:%lu\r\n",rng_val);$ V7 f, E! O0 F8 g$ ~6 G
  14.           }
    ) e! E% F# }6 i7 E) i$ d, Q7 t
  15.           if(KEY_1())
    " e0 _# a# x5 j6 _4 t$ T" k
  16.             {+ e' m. H! e5 g# T2 n* i
  17.                   rng_val = HAL_RNG_GetRandomNumber_IT(&hrng);
    + x( ~( {" w) s% X( r* C
  18.                   printf("KEY_1->RNG_GetRandomNumber_IT:%lu\r\n",rng_val);* U1 `/ o- t& c; ^5 [; m
  19.             }' t3 F3 }# E3 i3 O" I2 m2 O
  20.           if(KEY_2())
    $ w4 J  ^+ K0 F" a: M, V
  21.             {
    ) c: S7 Y# v+ v0 S5 v* M
  22.                   rng_val = HAL_RNG_ReadLastRandomNumber(&hrng);
    # I4 b0 m! H- c6 W: k& u0 O
  23.                   printf("KEY_2->RNG_ReadLastRandomNumber:%lu\r\n",rng_val);
    $ y# l2 T4 o! W% d9 k
  24.             }' O: x7 o! i# i! Y9 S/ Z' ~
  25.     /* USER CODE END WHILE */
复制代码
6 O% D; w7 C( v" u
三、编译及测试/ l# u5 n- D- k+ X5 c/ Q
        3.1 编译及下载
" C) V% E. p4 f4 `1 E7 q1 @8 P  ]
        点击编译按钮确保编译正确输出,并配置运行配置后,点击运行完成下载9 g; g6 v( |2 a/ k* d

$ V, S% a. M" O( u
5259cc9e59ce4d57b99d0423e030f230.png $ J/ O1 I' G5 y& u, Q3 i  g

% U1 U+ n3 b9 ]0 R4 `9 R# D  E* [         3.2 测试0 \1 G, t% k% m! ^& _' r2 I- q
        串口助手链接到开发板上,分别按键KEY0、KEY1、KEY2输出log如下图:
% w1 _& u, A" u( n4 N  i
$ ^; e& G0 h& w. I+ `8 C$ [& T, N
9d0b9e5066b9489388d7a9d0d44be04c.png & D- `5 H( S8 w8 g. r0 _
. K" M' Y. K, E3 O8 `, _
         由于KEY1是中断方式读取随机数,因此我们前面重写的回调函数也会生效,但需要注意的是HAL_RNG_GetRandomNumber_IT先于HAL_RNG_ReadyDataCallback,读取了数据寄存器,连个函数是分别读取数据寄存器,因此得到的随机数是不一致的,实际项目中按需选择来应用。- O! k. Z2 ]+ {3 M; [7 H

4 Y* ~8 N6 T4 @- [% h
952a2c1763a0432fa35a4e1fc750eddc.png ) N2 R, t& P& c+ {$ c
1 j( ]4 r* _) w% x3 h+ a
————————————————
  u1 r; J' p: }$ `! v版权声明:py_free-物联智能
) W  g& o: Q& e4 `如有侵权请联系删除- A4 U. f' |; \9 j7 u/ s

' z7 \7 G3 D" _8 F( k. Q" F* `
收藏 评论0 发布时间:2023-4-6 13:44

举报

0个回答

所属标签

相似分享

官网相关资源

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