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

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

[复制链接]
攻城狮Melo 发布时间:2023-4-6 13:44
一、STM32的随机数发生器, R5 x$ c8 n* K7 H$ h* u. |( H, A
        1.1 RGN 简介

1 p( K) o$ Y5 _( q4 m        STM32的RGN(Random Number Generator,随机数发生器),是一个以连续模拟噪声为基础的随机数发生器,在主机读数时提供一个由模拟量发生器产生的 32 位随机数。
" \+ j: ^# R3 c$ P8 C
7 q) H& D7 a/ m4 f
        RGN由实时熵源(模拟)和内部调节组件组成,它将全熵输出作为32位样本提供给应用程序。通常MCU中去读取两个连续随机数的间隔为 40 个 PLL48CLK时钟信号周期。产生随机数的模拟量发生器,由几个环形振荡器组成,振荡器的输出进行异或运算以产生馈入线性反馈移位寄存器(RNG_LFSR)种子,这些种子用于生成 32 位随机数。RGN支持中断功能,通过检测状态位(RNG_SR 寄存器),检测种子异常(RNG_FLAG_SECS)、时钟异常(RNG_SR_CECS)等现象,检测到错误时生成中断。% ]; p2 @' [) [0 o3 }" ?3 a* k

9 X/ r; |; B, B7 E& `        1.2 RNG配置说明
! ^5 h' K& M  [- Z# `        在CubeMX上开启RNG功能非常简单,只需要激活即可,在其参数栏设置无任何参数需要设置,在NVIC栏可以开启中断功能。
3 p) K$ p* N$ S. K$ U2 E. _7 @) ~  k& c; A- F) ^, a# ?
6c5500271ea54551b6dfb2258f57b6b1.png
1 E9 C, f7 \  m8 I$ B

$ F0 r) S) y+ M% t/ P         RNG依赖时钟源可有在时钟树选择器设置,时钟频率大小可以通过倍频器、分频器设置,例如本文采用STM32L496VGTx芯片时,设置其PLL48CLK时钟依赖源PLLSAl1Q,输出时钟频率是48MHz,如下图所示。$ b5 \, B! U( k+ S6 i! V

" r+ o$ [' T- }) n  f4 T6 m
bfd00a447e8b40a2ada3feff5a9db078.png
+ z2 a8 r' T# A" j
* |: V% L# w0 F8 s! T7 @
         STM32的RGN内部通信通常是通过AHB总线实现,例如STM32L496VGTx芯片通过AHB2总线。
  D" g  M# p& N; n$ S  d1 w& _) E: }2 k6 J; G* s
d07264915c5c436ab6a33677e4c23e7e.png * `* c: y! u! ?
: D, m" B0 j) r( }( G& j
         RNG在STM32芯片正常、睡眠的工模式下有效。
( ?* n! u8 [$ L7 K
( W) E2 [( b! ^( g! s
774abc141f7e400684de60aa97a0b5e4.png ( W: u1 s/ c0 g8 @! N2 D, `

  }4 ^$ R" x; a% ]' ~$ t9 O2 Z         在STM32L496VGTx芯片中,RNG的寄存器空间大小为0X3FF(1024),用于存储RNG的数据寄存器、状态寄存器、控制寄存器以及缓存参数、组件信息等。
* Q2 L5 b3 O0 `! j2 N2 _4 r# B$ H0 o4 l5 D1 T
529c47a4c0b04f7ea77a8740cc6293c4.png
2 `4 V2 z$ S+ \% R; F( {
" `" R0 y9 [% K 二、创建RNG测试工程及HLA源码分析
& X" N0 b5 _1 v' D( f         2.1 工程创建
3 W, f: c! c* k9 X) e0 u# N
        本文为采用的是stm32L496VGTx-ali开发板来建立测试工程,并按本专栏前面的博文移植好了lpuart1串口调试及按键功能,请自行参考。0 d6 h! V5 s: X( D

6 w7 ?0 i; O; Y# K6 x6 R* x% \现双击.ioc文件,打开CubeMX配置界面,开启RNG功能,并开启中断,时钟树上设置最终输出频率48MHz。
5 T+ g! Y+ U6 |$ b! @7 H5 l( O$ v8 {% d* o% _. m* w9 R
6afc948c88ba476ead37ed7ea9ab24b0.png $ ?# |% q+ y+ P; D/ `5 i

$ Y  A- x+ U: g/ [1 R
6e455e8c7f2641bab92415594e07705c.png 2 A* T( k3 ^, E* ]+ \
# L  h( ~: z& W; }
         保成生成输出代码* Y4 U; z, g, p& N

7 ~, G# t5 Q- L! E# m! U        2.3 RNG的HLA库源码分析7 O: g" E8 U9 i! v, L' z- H
        cubeMX生成代码时,会在Core源码目录下的Inc及Src目录,分别生成rng.h和rng.c驱动文件。
+ o  x1 Z$ a6 ]* P
$ m* O1 v* T/ _( k* W* e# \        在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函数。1 a( R/ L# [) D$ ~
8 W; ^$ x2 `( n1 H
c1aa904de5fb4cc0bdbc3d0ae144e8c5.png
$ h- K) s3 {' q2 ?9 e6 O; A: e3 _" l% L; |3 y; a
         在stm32l4xx_hal_rng.c源文件中定义了HAL_RNG_Init函数,它做以下事情:诊断配置参数是否合规;
) @( ^0 `5 v$ n: h$ w5 C* g- \! s8 a
a14b55c38d564dfd8549ce2e8261ccab.png " A( e+ A, G3 I
. J% v6 k4 w' H8 c
         以及调用HAL_RNG_MspInit函数完成CRC时钟开启及中断设置与开启(如果cubeMX配置开启中断功能的话);7 h8 i+ r5 I- j0 Z. N3 N% n' G

1 J% `& B: d% M/ e
86a0aa84e2cb442e92ff09e879d6e13a.png 9 t) U8 U& A: P: ~( ?2 K3 F- F
. Y, D) G! i4 {6 S
        最后开启RNG,检测种子、数据寄存器的有效性。
/ }- Y9 d+ @8 i  w3 x5 K

2 P4 w: Z' `% N% ?/ S# o* z: ^ a7f7ea93c5124a0498a4db383d8e579f.png ) U. v2 r, @5 P" j" P

9 r; R- |' N7 c! r, h% I
         再回到rng.c内,HAL_RNG_MspInit函数实现了RNG外设时钟设置(如果配置依赖外设的话)与开启,以及中断设置与开启(如果cubeMX配置开启中断功能的话)。9 U. I, n( t& ~" A7 [

+ w: z, h8 H5 G' J- z* n+ t
bd11d809b4614cf4b3c50e6427bcc79b.png " J- T% P! t6 z7 [
* e7 H; E' K5 s6 ]
         在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。; H' z( E6 g6 v5 L

  S* l, i' H6 H9 O- Z7 W0 T2 {
ef6be0c76ac74bc58979a372f8488d21.png % ?4 z  v+ v2 p, m, M, s2 s4 H
, \  i# t3 P9 u$ ]2 E: P
         2.3 RNG使用设计
7 T2 i. X+ O( b7 H        由于本文开启了RNG中断功能,在rng.c源码中,重新编码HAL_RNG_ReadyDataCallback函数如下:' V" a" Z. r. K9 a4 O
  1. /* USER CODE BEGIN 1 */& m' v8 t0 Z; ^, o  @! s; X6 M5 z
  2. void HAL_RNG_ReadyDataCallback(RNG_HandleTypeDef *hrng, uint32_t random32bit)
    ( D  a. a6 q3 n  ^
  3. {% ^5 c: O+ U! O( l! A$ c  f8 H. A( ~
  4.         printf("RNG_ReadyDataCallback:%lu\r\n",random32bit);
    ! B2 }, R1 i( |5 b& Y
  5. }
    ' \6 |( B2 f0 e6 E
  6. /* USER CODE END 1 */
复制代码

  n* B' i4 l" w         在main.c源码文件中,添加各个外设及功能模块的头文件依赖。
; Z( j2 m: p2 A9 r- \  F6 k
  1. /* Private includes ----------------------------------------------------------*/
    5 C/ m! C3 @: ~( l3 B$ C1 H# y( B0 |: s5 X
  2. /* USER CODE BEGIN Includes */
    - D) `0 P  G0 c" b
  3. #include "../../ICore/key/key.h"0 L& |- ]9 c; ^2 ]
  4. #include "../../ICore/led/led.h"1 i5 R- v5 C; g; C
  5. #include "../../ICore/print/print.h"
    ( l0 U" P: j! `0 b
  6. #include "../../ICore/usart/usart.h"
    - h! C5 m1 h5 j0 c0 Y4 \
  7. #include "../../ICore/delay/delay.h"
    , K* X, E0 k' g. S
  8. /* USER CODE END Includes */
复制代码

/ X5 a  Z  a1 @  T; H/ }8 O' e         在main.c源码文件中,添加RNG句柄声明,用于读取随机数时使用。' E- W- V# e9 \9 f- C  ?
  1. /* Private user code ---------------------------------------------------------*/8 L5 f: k# U8 N7 c
  2. /* USER CODE BEGIN 0 */
    8 x0 p+ V/ F% T/ U! f
  3. extern RNG_HandleTypeDef hrng;
    * M( ^2 T6 `& G3 L9 C
  4. /* USER CODE END 0 */
复制代码

3 E1 \# t. @. I4 j2 C0 U6 |         在main函数内,启动串口中断功能及初始化其他辅助参数。# X8 [' x3 e6 K
  1.   /* Initialize all configured peripherals */
    ; B" m1 c' E- Z* O( d
  2.   MX_GPIO_Init();5 f5 w9 S! d; j9 C% f5 h
  3.   MX_LPUART1_UART_Init();/ U, q# Z8 P7 S# \" S' v/ H
  4.   MX_RNG_Init();
    2 O2 W  i# _; \
  5.   /* USER CODE BEGIN 2 */' P9 h# _9 C1 n6 I. k
  6.   ResetPrintInit(&hlpuart1);" c" F- y. @' X; Z+ w  {5 ~$ C
  7.   HAL_UART_Receive_IT(&hlpuart1,(uint8_t *)&HLPUSART_NewData, 1); //再开启接收中断% ?% l/ D2 K1 Z2 O1 X2 N* P- M& z
  8.   HLPUSART_RX_STA = 0;) A4 s/ _) t3 K+ ]/ y" K' U) f
  9.   //
    & f0 O" B% Y8 P
  10.   printf("app restart now!\r\n");+ y/ [; I& j6 L  F. u" [) R4 Q+ D
  11.   uint32_t rng_val = 0;# x8 J8 H4 E& ?. X4 X
  12.   /* USER CODE END 2 */
复制代码
, y0 l5 J/ T% X; j, `
        在main函数循环体内,通过按键触发调用不同的随机数获取函数,并打印输出到lpuart1上。
. x( {" `& @6 _
  1.   /* Infinite loop */
    . [- a% h9 D" l9 C
  2.   /* USER CODE BEGIN WHILE */  u! Q) L& v: K! ?
  3.   while (1)5 f' R: a+ i0 E2 S) j+ o2 Z- v
  4.   {
    1 G! E' K7 i7 W! u
  5.             if(HLPUSART_RX_STA&0xC000){//溢出或换行,重新开始: r2 r. `" \5 d
  6.                     //printf("%.*s\r\n",HLPUSART_RX_STA&0X0FFF, HLPUSART_RX_BUF);
    ( ^) p% ?8 \' d
  7.                     HLPUSART_RX_STA=0;//接收错误,重新开始
    " j2 k* \# C; R, b) K7 q4 E- J% l, {
  8.                     HAL_Delay(100);//等待( f. c1 }8 _0 v  Q
  9.             }4 i: m) M) ?- s
  10.           if(KEY_0())
    ' I- s) ~, l2 c% t3 I
  11.           {' P, W% D$ W* m) k
  12.                   rng_val = HAL_RNG_GetRandomNumber(&hrng);
    7 o( t1 [! q: t* D5 I) I& [; k
  13.                   printf("KEY_0->RNG_GetRandomNumber:%lu\r\n",rng_val);/ \) K' y, a: H6 v( A' R
  14.           }# ?3 U( Q+ K% r( \/ v3 f' H
  15.           if(KEY_1())/ {3 x; j8 ?! b+ B  m
  16.             {
    4 Q/ b/ o* B6 a+ |
  17.                   rng_val = HAL_RNG_GetRandomNumber_IT(&hrng);+ {" B0 y8 A+ k0 b$ {
  18.                   printf("KEY_1->RNG_GetRandomNumber_IT:%lu\r\n",rng_val);* ]7 h/ B7 Q8 p6 T2 L* N4 F* c
  19.             }9 Z6 ?1 U& k0 r1 Q6 Z
  20.           if(KEY_2())
    * F- Q2 k, ]9 u4 K
  21.             {
    ( f0 O8 E1 T7 A/ f
  22.                   rng_val = HAL_RNG_ReadLastRandomNumber(&hrng);
    7 o0 r, f" }0 J0 x: ]+ u" F, ]  H
  23.                   printf("KEY_2->RNG_ReadLastRandomNumber:%lu\r\n",rng_val);
      N4 G. R# A) k; D: T
  24.             }
    # ?/ T; T4 r! h9 ~  |/ J8 g- S  U+ O+ z
  25.     /* USER CODE END WHILE */
复制代码
- S  z0 M$ M& E3 K' k- V5 z0 L
三、编译及测试
4 }; q. t' W. F3 s        3.1 编译及下载
& T2 H5 ?# a* T1 s
        点击编译按钮确保编译正确输出,并配置运行配置后,点击运行完成下载7 h$ A0 b2 a7 C  F
% R: _6 W+ [2 N( r' n$ W. r; O  t
5259cc9e59ce4d57b99d0423e030f230.png ( b4 d- p, o  n+ [
/ |- F5 o; r9 Q& ]; y5 Z9 Q- t
         3.2 测试* q5 O6 @$ B/ w1 b4 M" a
        串口助手链接到开发板上,分别按键KEY0、KEY1、KEY2输出log如下图:" l9 I. ^; H. H2 P+ I2 q( H! A

" g) V5 k$ Y$ D8 j
9d0b9e5066b9489388d7a9d0d44be04c.png * D8 P: V: m6 d9 |0 C) k1 ^- }
; ^8 D$ X1 x& Y; J& S8 ]
         由于KEY1是中断方式读取随机数,因此我们前面重写的回调函数也会生效,但需要注意的是HAL_RNG_GetRandomNumber_IT先于HAL_RNG_ReadyDataCallback,读取了数据寄存器,连个函数是分别读取数据寄存器,因此得到的随机数是不一致的,实际项目中按需选择来应用。
1 m" `/ q* \! Y- M7 E( ?: q9 ]" ]( A; C0 X
952a2c1763a0432fa35a4e1fc750eddc.png
( f5 q& X& ?! O4 k7 O& }& V4 w& b' x  K, T
————————————————
* A  s1 Q' v3 P6 D# |版权声明:py_free-物联智能
' |' _& J1 T" n& M. N2 j7 q1 F( K如有侵权请联系删除, m0 x8 }( k( s. J& ]- [& c0 `! d7 u: I: c

8 X6 _$ i+ F2 O" u+ `3 t+ f. ~
赞 收藏 评论0 发布时间:2023-4-6 13:44

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版