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

STM32MP1 M4裸机CubeIDE开发指南-硬件随机数实验

[复制链接]
STMCU小助手 发布时间:2022-9-28 18:51
硬件随机数实验9 ]9 N% E2 t* M' ^  G+ j7 ~
本章,我们将介绍STM32MP157的硬件随机数发生器。我们使用KEY0按键来获取硬件随机数,并且将获取到的随机数值通过串口打印出来。同时,使用LED0指示程序运行状态。4 E" M* O$ J  U9 E& Z5 X4 \$ e6 t
' F7 o; I9 d1 e* c: p/ c
20.1 随机数发生器简介, g3 ^: I$ T0 ^7 @
STM32MP157自带了硬件随机数发生器(RNG),其中RNG1给A7内核使用,RNG2给M4内核使用。RNG处理器是一个以连续模拟噪声为基础的随机数发生器,在主机读数时提供一个32位的随机数。
; ^# p4 `# w& t! {+ d- X20.1.1 RNG框图
$ W+ Y; R2 n4 k' J/ _, C# l下面先来学习RNG框图,通过学习RNG框图会有一个很好的整体掌握,同时对之后的编程也会有一个清晰的思路。STM32MP157的随机数发生器框图如下图所示:6 ~$ @4 _2 @+ g* }1 Z& \; g- V- y: J
2 W3 q! P& u, O6 F3 [
948b166ef8df447eae44efcb1e13f983.png
5 w" O5 t: y- F
2 D& `; h* Y. {, N# k/ Z图20.1.1. 1随机数发生器(RNG)框图# n+ c  c. `5 H" B3 ?3 s
随机数发生器有2个时钟域:AHB时钟域和RNG时钟域。AHB 时钟用于为 AHB 存储寄存器和调节组件提供时钟信号,RNG 时钟用于噪声源采样。如果 RNG_CR 寄存器中的 CED 位设置为“0”了,即启用时钟错误检测,那么 RNG 时钟频率 必须大于 AHB 时钟频率的32 分之一,否则时钟检查器会指示时钟错误,RNG 将停止生成随机数。在配置时钟时,注意此范围。) Z+ S1 b' X, w
RNG时钟域时钟为rng_clk,rng_clk由RCC_RNG2CKSELR寄存器的RNG2SRC[1:0]位选择具体的时钟源,具体选择关系为:
" p  s; f: L" ?6 A# H$ p0 s3 g1 d0x0: csi_ker_ck5 ], E3 P/ a& `
0x1: pll4_r_ck- J. Z% }3 k( [4 {
0x2: lse_ck clock
$ A  b8 t- n' g; |' C1 x1 k1 |0 S0x3: lsi_ck
  \2 Z$ @; C) w. A/ S+ P默认情况下STM32CubeMX会选择0x0: csi_ker_ck(4 MHz)作为rng_clk的时钟源,最大可通过PLL4配置为48MHz:1 v6 d8 q" R7 Z, b
* o+ j- y- h0 C' P
698a8aa0268d4a76abfadcfbc0c54ff6.png
  M, [: g  ]5 d8 \1 T! I# v  i3 x/ l! V
图20.1.1. 2 RNG2默认采用CSI作为时钟源
. V3 ^+ L+ X# A: I. K' a1 N) hAHB时钟域的时钟来自AHB3(最大为209MHz),用于访问相关寄存器等,通过RCC_MC_AHB3ENSETR的RNG2EN位(bit6)使能。可见,4MHz小于209/32,如果开启时钟错误检测,注意配置RNG2的时钟范围。
. U2 s0 ]+ `+ Q- j' O
% r! _$ j2 N4 N# Y e7bcecb9be8d4075a8d6741c2be36332.png
" o, D7 Y. n( @9 ~
3 b5 [, M2 ]6 R$ V图20.1.1. 3 RNG时钟
! X2 T8 l7 O" k& B& C, E* z8 T6 y. {RCC_RNG2CKSELR和RCC_MC_AHB3ENSETR这两个寄存器我们就不做介绍了,大家参考手册。从RNG框图整体上知道,RNG有两个输入和一个输出。具体如下表:
" Q- X, Y" L9 X/ s0 U7 U  l4 _5 Z+ c7 S! ?/ |
96c86692b27941bebc458eee62773e42.png
' ?5 L9 A& F5 i/ B# }
& _0 W7 N+ m3 g表20.1.1. 1 RNG内部输入/输出信号
: Q3 f% D/ z( M2 sSTM32MP157的随机数发生器(RNG)采用模拟电路实现,由内部两个模拟噪声源产生种子,经过采样和归一化处理,再经过线性移位寄存器和判断逻辑,最终输出到RNG_DR,生成32 位随机数。2 {7 E; m. |5 X$ `. H2 t
每个模拟噪声源由3个环形振荡器组成,振荡器产生的输出经过异或运算产生种子,经过采样归一化处理后,输出到RNG内部的线性移位寄存器。采样频率由rng_clk时钟提供,因此,随机数质量与 HCLK 频率无关。当将大量种子引入线性移位寄存器后,经过判断逻辑,最终输出到数据寄存器 (RNG_DR)。
, g' }. m7 @5 R同时,系统会监视模拟种子和专用时钟 rng_clk,当种子上出现异常序列,或rng_clk时钟频率过低时,可以由RNG_SR寄存器的对应位读取到,如果设置了中断,则在检测到错误时,还可以产生中断。
9 ?! [" G/ F4 u, l: c$ A20.1.2 RNG寄存器
' e+ k$ p7 u, s6 s7 j1.RNG控制寄存器(RNG_CR)" g" b+ ~8 h" @
RNG控制寄存器描述如下图所示:, p3 I# [0 C' p1 t; x9 W

6 B- T2 ]# b# o6 k d730dffd53bf421caf8f752b159e98e4.png 7 ^7 X* [, O. D

+ d, n) v- b* r" r图20.1.2. 1 RNG_CR寄存器
9 \7 G. U" j8 I# p0 y3 v该寄存器我们只关心RNGEN位,该位用于使能随机数发生器,所以必须设置为1。
- }8 i& }1 z& N" o$ E1 D+ c2. RNG状态寄存器(RNG_SR)
2 o& U2 k! C8 y7 k( D4 |/ gRNG状态寄存器描述如下图所示:
8 h! x$ J3 g) Z# `0 W8 `' R. E: N& v; a3 U6 M7 s: `' R8 _
ce24f1c9f4954d3ab0b26abd65003e4b.png
1 u! n* S/ y, N4 h- S
) g; A5 H, H$ b& Y* ?6 W图20.1.2. 2 RNG_SR寄存器
6 M" i( v: U7 q5 V8 u/ b该寄存器我们仅关心最低位(DRDY位),该位用于表示RNG_DR寄存器包含的随机数数据是否有效,如果该位为1,则说明RNG_DR的数据是有效的,可以读取出来了。读RNG_DR后,该位自动清零。
! C7 I6 j9 H% w. d) u6 \8 y3. RNG数据寄存器(RNG_DR)7 ]/ }7 `1 l4 P5 z/ ]! X$ F
RNG数据寄存器描述如下图所示:/ \+ W& _9 W. c' E) W
. E/ _1 b. |% ^# \+ K9 @" |2 T
04dd465c96984062a7f83cc419e21de7.png 5 y/ Q& z: f2 x" z  f8 t

& g' q1 L- o) ~) k' C6 k. m图20.1.2. 3 RNG_DR寄存器4 v* ]' q) [5 J+ r( S) h
RNG_DR寄存器是只读寄存器,我们可以读取该寄存器获得32位随机数值。此寄存器在最多216个AHB时钟周期后,又可以提供新的随机数值。
- d$ C5 r1 \: ^- s4 G- I, a& [! b/ ~% G
20.1.3 RNG的HAL库驱动* v7 v& _8 O+ v8 m4 V( B: @8 V
RNG在HAL库中的驱动代码在stm32mp1xx_hal_rng.c文件(及其头文件)中。) F- K# L  f' Y! y: \
1.HAL_RNG_Init函数
  o" o' q! Q  R0 c4 y) `, U3 {6 PRNG的初始化函数,其声明如下:& F0 Z; i4 O, C# N$ Y
  1. HAL_StatusTypeDef HAL_RNG_Init(RNG_HandleTypeDef *hrng);1 n0 ?8 [" Y3 n' H- I8 Q2 P
  2. ●函数描述:3 I$ Q; r2 Z2 z+ `3 }) j0 e
  3.         用于初始化RNG。
    ; s, W# F3 ~9 Z( J5 G% @3 L# v% V, K
  4. ●函数形参:& B" U* a* m" n2 H
  5.         形参1是RNG_HandleTypeDef结构体类型指针变量,其定义如下:
    ) M8 g( D0 I# N7 G, z# U$ X
  6. typedef struct
    6 y# c! b0 m% q
  7. {
    9 ]9 u  c% Y+ ?- B4 G
  8.   RNG_TypeDef                   *Instance;    /* RNG基地址 */, e6 s% q0 h9 s
  9.   RNG_InitTypeDef               Init;         /* RNG初始化配置结构体 */  F( g4 F; {, g6 O/ b6 A0 b3 i  O
  10.   HAL_LockTypeDef               Lock;         /* RNG锁设置 */
    + m, f% j" n) z' c! q8 ?  r
  11.   __IO HAL_RNG_StateTypeDef   State;        /* RNG设备访问状态 */% x9 \/ v8 U* d+ l; C
  12.   __IO  uint32_t                ErrorCode;    /* RNG错误代码 */
    ) h4 L% k. K1 s6 ?
  13.   uint32_t                      RandomNumber; /* RNG最后生成的随机数 */0 U  i  l% T5 S1 @
  14. } RNG_HandleTypeDef;# h; j, A1 N/ |
  15.         1)Instance:指向RNG寄存器基地址。
    , u$ f* G9 d, U! a; t+ u
  16.         2)Init:是的RNG初始化结构体,其结构体类型RTC_InitTypeDef定义如下:5 S3 B# I/ E. p6 Q
  17. typedef struct
    / K; W  c7 @( ]$ S  J$ |5 n
  18. {
    " \3 L* c  O6 i+ f" ^
  19.   uint32_t            ClockErrorDetection; /* CED时钟错误检测 */
    9 P& e  f" \1 a9 l+ a. Y/ {4 w
  20. } RNG_InitTypeDef;
复制代码

# S( B) s+ a- f3)Lock:用于配置锁状态。6 L# s( R- t* a: J; B+ c% k9 G
4)State:RNG设备访问状态。+ h7 s/ [0 [' t( m4 P0 M. M
5)ErrorCode :RNG错误代码  d8 L; A! l' Y- D  u$ U( v) S9 q
6)RandomNumber :该变量存储RNG最后生成的随机数
, x- t  i5 c* v! ]. T/ w/ F6 x# Q; _  D1 D# Z
●函数返回值:
. N' K/ f  _% w6 b6 F7 UHAL_StatusTypeDef枚举类型的值。) @0 r4 N) z( {: g/ P
2. HAL_RNG_GenerateRandomNumber函数6 e+ P; M8 G+ h, m( q1 }
HAL_RNG_GenerateRandomNumber是RNG生成随机数函数。其声明如下:1 u* z- K& i# z! B' D, o* d1 R
HAL_StatusTypeDef HAL_RNG_GenerateRandomNumber(RNG_HandleTypeDef *hrng,
" ~) a  R2 I  X' p( Guint32_t *random32bit);. I( w/ E* a$ d: ~
●函数描述:
6 h9 X0 A9 T3 U$ B  G! j1 w+ g该函数用于RNG生成随机数。5 `4 ?9 O  F( t/ ?: J# T+ w! m; T
●函数形参:/ T& v/ P& P$ V* F2 }9 Q
形参1是RNG_HandleTypeDef结构体类型指针变量,即RNG的句柄。
* [% d  f- w" e  D形参2是uint32_t类型指针变量,随机32位指针,生成随机变量。
" v" G, p3 A+ R5 v2 Z, b: F" s8 D$ Y●函数返回值:
$ Z5 p  o" C) e9 U' X0 o3 |HAL_StatusTypeDef枚举类型的值。
% p: U- {' w/ r) g0 p$ }8 e7 e5 ^+ V. C+ j
20.2 硬件设计
3 I  E8 m/ }5 V1.例程功能
# ~. w% K$ x6 b: y: O  e4 D本实验使用STM32MP157自带的硬件随机数生成器(RNG),获取随机数,并通过串口打印出来。按KEY0可以获取一次随机数。同时程序自动获取0~9范围内的随机数,显示在屏幕上。LED0闪烁用于提示程序正在运行。
" j6 k5 ^' ~( b+ M2.硬件资源
9 V$ P' ]" K/ w8 L1)LED灯:LED0
/ [% M) Q, ], [2)独立按键 KEY0
% v" d3 R: F. |: B' E$ E8 _3)串口4
- r7 r1 d! ]4 {0 x; s3 a5 b& E4)RNG(硬件随机数生成器)
9 d: G. \$ _- J/ x7 zLED0 KEY0 UART4_TX UART4_RX* t+ X9 ?( v) E: l7 g# G
PI0 PG3 PG11 PB2
% e* {; F5 P, \0 Z表20.2. 1 硬件资源
5 l) J5 g% J( w3.原理图4 b' y9 d0 B7 U# d( @' L
RNG属于STM32MP157内部资源,通过软件设置好就可以了。* p9 k, a8 _1 L9 P& @

( W- v( ~7 Q( @9 c& H/ W% n; I20.3 软件设计" I6 Y; C! S$ ?7 f
本实验配置好的实验工程已经放到了开发板光盘中,路径为:开发板光盘A-基础资料\1、程序源码\11、M4 CubeIDE裸机驱动例程\CubeIDE_project\ 13 RNG。, f. j3 o3 a& W* K
20.3.1 程序流程图6 O! H4 e4 P; N% k( o3 B, D3 P; A8 Y
下面看看本实验的程序流程图:
' E; W; ]* B6 V0 R% `/ a# j; A
) l6 h9 g4 h* A0 f 3f99ad887c3b4ee6917cf73ad6f407d4.png
: Y' @8 k: y% R" u9 B
0 e1 @3 o$ F; G$ A5 Q$ f0 Y图20.3.1. 1硬件随机数实验程序流程图
3 R* `% o% U  u# V2 O4 L' j" ]. Q/ o  @/ R
20.3.2 软件配置! G2 C0 m. J5 z
1.新建和配置工程
  f' j; m5 [( X3 ]; v% i  h本节实验可以在前面的串口通信实验的基础上实现,因为用到串口UART4,也可以重新新建一个新的工程。这里新建工程RNG,然后配置串口UART4和按键KEY0以及LED0,具体的配置步骤我们前面的实验章节都有介绍过,如果不记得配置步骤,大家可以回顾前面相关的实验章节。本节实验中,LED和按键只用到LED0和KEY0,其它LED和按键没有用到,如果直接使用前面BSP文件夹里的led.c、led.h、ket.h和key.c文件的话,可以直接将其他LED和按键也一起配置了。
" z! [  V2 Z6 U$ _2 Z9 B(1)GPIO配置
" h2 C9 y) b# n1 QLED0和KEY0配置如下:) E: g! A+ A2 @
- ~( `1 E6 Z3 R9 B4 ]  W
6026e638dc554e4c91e2b8cbf73b5984.png # n6 C" H# f' _. h: v/ I- O

$ f: M- ?& F& }# q- o图20.3.2. 1 LE0和KEY0配置
! c; i1 V: p' hUART4配置如下:$ t% x# X! a- U! P: z: h0 z# M6 b
' u( G9 H1 v( t1 s; b6 H' k2 A7 m; ~
36ba603f8cb54816aca9fdbdf933934a.png
/ o+ }3 v+ [# h' y$ |7 o. ^+ ?9 F4 t2 w$ S3 j* W% {
图20.3.2. 2 UART4配置6 `+ ~/ m& L8 @: A$ M
(2)NVIC配置:
0 n+ q; r4 f8 X  @6 _3 Q  _UART4参数使用默认配置:
+ T/ O4 l8 B& _- W& l6 a. g3 q8 a4 D1 E9 A# w4 y$ Q
b45bbd9b64fe4fd7bc948b3f36a46d80.png * i0 r4 z2 @' Q, L
; R3 J7 Z% D, k- @$ T
图20.3.2. 3 UART4参数配置% q$ R1 D! h0 _% M( q- K
我们使用串口中断,先开启串口全局中断,+ B3 q/ `/ B, U
3 |# T5 G0 W7 s
aff30c544ad14d4c9f14cfed35b2ee6b.png 3 A! P- \2 U! a0 u% o8 P- t
; ]* ~& w' [% y1 H7 e
图20.3.2. 4 开启UART4全局中断5 B$ e2 c; S, Z# Z1 _+ X
串口中断优先级配置如下:8 w/ z8 z: p( m5 T) S0 t' X7 p* k8 W
! M8 n: Q5 e  L, ~
db52ac267c8f49ebb3e187bc94548cae.png # ^" F9 r# c7 q

, P: O: p6 ?( ~4 E图20.3.2. 5 配置UART4中断优先级
$ N( ]$ N/ L& H+ ~下面,我们直接配置RNG2:) h, ~! `" r: g3 r7 p' W- |
(3)配置RNG2
) k4 H7 y1 w! t2 s: w+ X如果不知道RNG在哪里,可以直接搜索RNG2:) K$ c* Z+ ], q8 ^
+ h$ n% w  T9 {  o
e05425cfce294f51905b95680b4fe1ba.png ; `$ Z$ s/ p0 ~6 p$ M& X/ g
* @3 r6 m# B2 \0 C
图20.3.2. 6 查找RNG2
; i: r* f2 ?7 j4 e5 {( d在SecurityRNG2下找到RNG2的配置,按照如下图配置,先勾选Cortex-M4,再选择Activated,即激活随机数发生器。其它配置保持默认,实际上RNG没有其它参数需要配置的。这里,我们不开启时钟错误检测:! A) ?* ]* C" ]0 p$ B3 B
, e/ x7 u5 {% s8 ]9 Y# E  Z' W
8dd3bd6af05e4d27a6937c253dc616d1.png
  f4 J5 Z0 m. r/ r# Y
/ {8 N& z' D$ X* H; b( m7 E图20.3.2. 7 配置RNG2
/ a6 {4 Y% w! K: h! W(4)配置时钟
; ~1 R; ?8 N' i- bRRNG2时钟默认采用CSI的时钟,其它时钟也可以保持默认配置。这里就保持和前面一样的配置,配置PCLK1最大为104.5MHz:
3 F9 @2 H1 \2 M( U. l" d( a' o4 d' {0 |5 S8 {3 y: ^  }
9f8297fe596f4fd78beb8d7e754ed18d.png ; f6 n( _# M2 s) K5 a, \  g4 K  X( @' i

0 @, t1 f, S" m; V/ D4 \图20.3.2. 8 配置时钟  ?7 ~7 m: z$ o- g% f; r
(5)配置生成独立的.c和.h文件+ o1 H1 y% V* R) V! [

. R! C/ u6 e) L8 ?" L5 z 55ab73bf94e04d18957f0d18b8bb892a.png - y: Q7 m3 M/ Q% b8 l  R) l6 H) }
4 N$ s% v1 s5 b. R
图20.3.2. 9配置生成独立的文件
# C  ]) i- _1 `0 L; \# k9 b* z2. 生成工程/ k. Z2 X% M; U# d3 |
以上的配置检查无误后,按下键盘的“Ctrl+S”组合键保存配置并生成工程。将前面按键实验用到的BSP文件夹拷贝到本工程的Src目录下,只留下按键和LED相关的代码:
  `2 r# H: w& h9 S; S" E) O9 r  A, q: f% b& z
88b0fa359fe243bd9466ab8773b12d19.png
1 r' M3 Y9 T: T; L% k
4 i/ s2 A3 b% G8 B# s( s: z* o图20.3.2. 10生成工程
3 c( O% |0 o3 K; I+ X3. 添加用户代码6 w1 U. i( W8 A" X
上一步操作中,我们已经将BSP文件夹拷贝到了工程中,因为本节实验只用到LED0和KEY0相关的代码,所以将其它LED1和按键的代码注释掉。当然,也可以在STM32CubeMX上将LED1和其它按键也一起配置了,这样就不需要注释这些代码了,或者也可以自己重新手动编写这部分代码。
( S- C9 s/ H8 ]6 k(1)key.h、key.c、led.c和led.h的代码比较简单,这里就不列出来了,大家可以直接参考本工程中的代码。& w8 y3 m5 w3 Z0 z$ @6 _* `' g
(2)串口相关的代码可直接参考前面串口通信实验章节部分,这里就不再列出来了。
3 n4 V3 _8 F' I: J(3)RNG2初始化代码已经在rng.c文件中生成了,代码比较简单,如下:, x! D( s+ L( h9 G! @$ u' F7 o
6 A+ t0 `& i. Y. D( ^( h* ?
  1. #include "rng.h": d' x- A. j, k8 ?
  2. 1 `  P! \5 R) u) v" Y  x0 P$ F
  3. RNG_HandleTypeDef hrng2; /* RNG2句柄 */
    & P# s0 K. k2 ~) {$ `9 p- B

  4. 2 f' k" \4 s' y7 o  r6 ?/ Y; e7 N' s
  5. /**
    ' ]" f1 C9 R( \; W
  6. * @brief       RNG底层驱动,初始化RNG2
    . K0 i' {( h2 H; K
  7. * @note        此函数会被HAL_RNG_Init()调用
    3 U. ?# `8 c; ~6 x" t3 ]% g( R  h
  8. * @param       hrng:RNG句柄( e# Y* ~! q5 O9 u3 Q7 V
  9. * @retval      无' }4 |- s' w1 J" {' k
  10. */
    * X, i* x) z0 @7 C1 R1 ~3 W1 `
  11. void MX_RNG2_Init(void)
    6 M, U! H5 N. A- C0 ]- I; g% f
  12. {
    , F7 E6 w# W. q/ [: I  y. Y
  13.   hrng2.Instance = RNG2; /* RNG2 */
    " c& u- ?+ P2 a4 z0 e- i
  14.   hrng2.Init.ClockErrorDetection = RNG_CED_DISABLE; /* 关闭时钟错误检查 */
    : e2 D; }3 L2 G8 {1 J- c3 S$ a1 z9 N
  15.   if (HAL_RNG_Init(&hrng2) != HAL_OK) /* 初始化RNG2 */# a2 ~1 e( }, O* F' Z2 u( d
  16.   {
      P' p# H" |& Q0 m' n/ K2 F
  17.     Error_Handler();
    - E$ ]! L' \1 r6 O- m
  18.   }
    1 o" K7 w  ^. X' j. P

  19. 6 u& _& S5 a3 A& D9 {" D, u- t) D
  20. }9 L/ G+ l4 u% q6 Z, w' ?  |
  21. /**1 w+ x( g$ v- Y
  22. * @brief       RNG底层驱动,时钟源设置和使能
    / q' D  Q& n  {. _. `7 u
  23. * @note        此函数会被HAL_RNG_Init()调用. g- V" i& U0 }6 J5 H
  24. * @param       hrng:RNG2句柄- ]# ?( Y4 @! z, i3 d, @
  25. * @retval      无
    $ b" Y' [9 q  I
  26. */5 r2 I* e2 }7 y0 K/ @- V1 R5 d
  27. void HAL_RNG_MspInit(RNG_HandleTypeDef* rngHandle)/ L+ t5 E9 V& A, b. j! `
  28. {
    ! W9 e/ I* F, c
  29.   RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};. o( w) F$ e9 E8 g
  30.   if(rngHandle->Instance==RNG2)$ v& \. b$ Q% w+ z/ n; |
  31.   {, e( y/ U+ Y: {8 ?1 C  S, a! W8 s8 v
  32.   if(IS_ENGINEERING_BOOT_MODE())
    # B9 U& z& O$ @
  33.   {
    ) p( M8 o* s- X6 ~  R, E8 F$ r
  34.       /* 外设外RNG2 */
    ( K# Z. H; H& l, s! [
  35.     PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RNG2;
    : Z# g* Z( z5 S, W1 o
  36.     /* 时钟源设置为CSI */) o5 e& u! g* g: E2 @* S% }2 c
  37.     PeriphClkInit.Rng2ClockSelection = RCC_RNG2CLKSOURCE_CSI;- F5 Y% r5 _7 [
  38.     /* 初始化RCC扩展外设时钟,也就是RNG2时钟 */
    6 r3 C6 [1 B3 X% p! ?* B/ {9 c; m$ I3 e
  39.     if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
    / H; E$ @1 h) V9 r  M
  40.     {# g( \5 B  p& F3 {" V* G$ E
  41.       Error_Handler();. ~5 x: a! M" Q+ o# q' `
  42.     }
    " T8 @& W0 w* D
  43.   }' P, x7 j. d9 `
  44.     __HAL_RCC_RNG2_CLK_ENABLE(); /* 使能RNG2时钟 */
    0 y! j' Z: O$ J
  45.   }9 Q: k( E3 x/ Y* Z0 f! ?! V( F2 V
  46. }
    9 [7 Y" Y% U) a4 z
  47. /**+ }( Q& A0 L1 s& c
  48. * @brief       RNG底层驱动反初始化函数/ y1 v2 d( s6 J3 w4 G+ P
  49. * @note        如果需要,可以调用此函数" c+ Y$ i# h% N" P( k6 O
  50. * @param       hrng:RNG句柄9 V& @* u8 ]8 o8 s1 X# U
  51. * @retval      无
    2 u8 T# e1 a9 Y: N' O
  52. */6 x7 Y- C& _& g  O$ D8 f
  53. void HAL_RNG_MspDeInit(RNG_HandleTypeDef* rngHandle)& i  R' f* ]4 u+ v$ K6 _% F& p
  54. {1 d6 @* t8 \- `5 d3 r1 |
  55.   if(rngHandle->Instance==RNG2)
    7 x+ Y# I  ]6 O- S6 `8 B) Y$ b
  56.   {; [3 m0 o; `9 S; Y
  57.     __HAL_RCC_RNG2_CLK_DISABLE();/* 关闭RNG2时钟,即关闭RNG2 */
    + a# C0 Z3 b. @5 ?8 K: y, l; v
  58.   }& b& s4 C+ D0 P0 ]- h4 A+ _! ?; L/ Z% t
  59. }% G2 @2 k, i" O9 U9 P* ~+ G
  60.         (4)手动添加获取随机数的代码7 H6 u4 S" j0 k6 c: {1 R: q/ S
  61.         在rng.c文件中添加如下代码:
    ! s: ]' D0 ^" c* p- q6 K
  62. /* USER CODE BEGIN 1 */
    1 O3 E$ [/ g' t+ E) y. F9 x$ Z
  63. /**
    1 [& ~1 _$ \* ]; f& ?7 O
  64. * @brief       得到随机数
    * o9 X7 l) d8 ^- j5 S. u: k
  65. * @param       无  l, A; [5 F+ g' |, T. j- B! b7 |5 R
  66. * @retval      获取到的随机数(32bit)# ], U# H, j0 l; @8 W2 O
  67. */- @9 |9 R7 h: Q1 L8 B
  68. uint32_t rng_get_random_num(void)
    3 A9 e* m2 a3 V7 h# J
  69. {
    . B% L# O( A- a- X
  70.     uint32_t randomnum;
    , v5 V* t* s8 ]( O
  71.     HAL_RNG_GenerateRandomNumber(&hrng2, &randomnum);6 Y9 Q: u0 f9 m- D/ F; {2 F2 C( V1 e
  72.     return randomnum;' x) F  ]5 `' v/ [( b2 @* A
  73. }
    3 b! l4 w7 ^# M9 M2 ]! e) ~

  74. 6 @: b7 _: {7 x  v4 t: g6 M9 Z
  75. /*** S4 R5 a6 _( w% X1 X
  76. * @brief       得到某个范围内的随机数7 A7 K5 k1 F% ]2 i# f. E. V
  77. * @param       min,max: 最小,最大值.
    + O, ^3 a6 O2 Y* V1 V
  78. * @retval      得到的随机数(rval),满足:min<=rval<=max6 V# c* z3 W( N' W
  79. */
    1 [6 F) o5 G9 p8 Z, R- L% L1 k: E  t
  80. int rng_get_random_range(int min, int max)
    # [- v* m7 G+ v" m# J# G' i% I
  81. {
    ! z& B# P! e: ~
  82.     uint32_t randomnum;& {4 A5 x9 g& v  T0 c* `% y
  83.     HAL_RNG_GenerateRandomNumber(&hrng2, &randomnum);
    0 }, u+ a/ a9 I/ S% z! c# I2 R
  84.     return randomnum%(max-min+1) + min;
    ! X' K# S! F7 K! K, h, b
  85. }
    ; ^2 J5 I2 x% X
  86. /* USER CODE END 1 */
复制代码
9 ?9 F. r. S* r
以上代码比较简单,主要是通过HAL库中的HAL_RNG_GenerateRandomNumber函数获取随机数。rng_get_random_num函数主要是获取随机数,rng_get_random_range主要是返回某个范围内的随机数。& @" ~8 V8 r) @
(5)修改main.c文件  w( V2 B9 b- L) j9 ^$ v" R
; \; k% O+ m/ U) R3 d/ f" f* ~. e
  1. #include "main.h": m- m0 e2 i/ C$ S
  2. #include "rng.h"
    ( ]8 h: X1 J8 b
  3. #include "usart.h": o8 Q$ b5 e6 H, ~9 d! Q& s! p8 }+ J
  4. #include "gpio.h"
    , I) {1 g8 |8 o) X

  5. & R6 J. z) o; U/ ~
  6. /* USER CODE BEGIN Includes */
    ) X5 v  m: f6 m: O& ?
  7. #include "./BSP/Include/led.h"
    5 w  C( b6 `! c+ O4 h5 V
  8. #include "./BSP/Include/key.h"
      K/ k/ e9 N! B6 J8 J6 s
  9. /* USER CODE END Includes */- [$ a( A3 y  B- a6 v7 b

  10. ) F0 m- q# |& U4 |4 d6 q2 Q
  11. void SystemClock_Config(void);
    7 \. d/ j5 ], n  K' H; F$ ?
  12. / m5 {' M* @  b
  13. int main(void)
    1 i: T' J$ U" h8 m/ d) N6 |* _
  14. {2 u1 y8 ^1 @* |$ L8 i! J
  15.   HAL_Init();. N( s0 V- {5 }" x2 A5 [
  16.   if(IS_ENGINEERING_BOOT_MODE())
    ( L( l) f% C: f! ^0 O! P! o. L
  17.   {/ [" `2 Y; o  S6 e8 |1 a( n
  18.     SystemClock_Config();
    3 Y) I3 ^) j2 [2 K' o  F) m2 K
  19.   }
      t9 W" d' `, E! ~! S
  20.   MX_GPIO_Init();
    - X. R1 q7 L, m7 R# n! b7 f) F
  21.   MX_RNG2_Init();$ h0 H1 d; [1 |
  22.   MX_UART4_Init();
    " C9 n0 F0 e1 w4 V: q
  23.   /* USER CODE BEGIN 2 */
    * M' g" ?  g9 m8 S
  24.   /* printf("请输入字符,并按下回车键结束\r\n"); */
    ! q! T. l7 x( V) I+ j7 B, b& L3 i
  25.       HAL_UART_Receive_IT(&huart4,&RxBuffer,1);/* 以中断方式接收函数 */
    0 J: f  i7 s4 w6 e% e, A: E  ~( n
  26.   /* USER CODE END 2 */# e$ I$ q: b% m5 f. N
  27.   while (1)
    + X3 |# w% h* I
  28.   {
    . b0 x2 K. r* d) w5 g$ L/ _. U" W
  29.     /* USER CODE BEGIN 3 */
    : U, M' K% T" D( w6 u/ ^
  30.       uint32_t random;" Y6 G7 V& U7 w- @$ J/ Y$ D
  31.       uint8_t t = 0, key;
    0 y7 M& c0 H6 s0 _. n9 M
  32.       key = key_scan(0);
    - ]$ @( _; t  j3 O' r
  33.       if (key == KEY0_PRES)
    6 d2 M& D- s  x& o" }$ B
  34.           {0 N( P% P, q1 S9 S5 F3 X
  35.              random = rng_get_random_num();
    4 W1 X6 G7 ?& f$ U. j
  36.              printf("Random Num:%lu\r\n", random);
    - L+ \/ v0 @% g( T; g
  37.            }
    9 A# r. p8 Q4 a; M( O+ Y
  38.        if ((t % 20) == 0)
    3 G- w& D1 T2 w' `8 n
  39.            {* R/ S; c% K1 M9 z: l
  40.              t = 0;7 I8 F- Y. ?% F- x, A/ A3 p
  41.              LED0_TOGGLE();                    /* 每200ms,翻转一次LED0 */( v5 f  N3 P- W3 p0 a
  42.              random = rng_get_random_range(0, 9);/* 取[0,9]区间的随机数 */, L: ^( p( W; ]: g$ j7 K- B* [0 f" Y$ |
  43.              printf("Random Num[0-9]:%lu\r\n", random);8 e: S; V) C$ t9 I& g0 v
  44.             }/ w' c( A- V5 V
  45.               HAL_Delay(10);0 `! \: n7 L3 O! c0 `3 D$ t  b
  46.               t++;
    ' ~" o% X( E+ S6 S; ^+ d- k; }
  47.   }: K6 K) A# W7 r& Z( X' S
  48.   /* USER CODE END 3 */
    - Z; h! M# O4 G- s" Z
  49. }
复制代码
* D9 {$ r5 q! e" D
以上代码中,每隔200ms会自动打印一次[0,9]区间的随机数,同时LED0会翻转一次。如果有按键按下,那么串口就会打印获取到的随机数。( M& g: R0 W5 ]5 `# s9 M7 @8 }' ~" f( M
7 d  b# H; q2 Q/ D5 R  W8 N) i
20.4 编译和测试% v/ K- h( P: ?9 o% U- |$ T
编译无报错,测试结果如下:) I6 G- ?/ E" s5 s& Y# i5 R! B' f
) q, R  D- g& {8 l3 T+ k& Z9 J
96b8c0d3c0f34914bc71d09b3936bfb2.png
  n$ N, \7 e3 h+ c: n, d) Y4 F
, b2 @  J/ ^) `- z7 w图20.4. 1测试结果
& _  v# l4 s3 g8 L————————————————" |8 _2 I- f0 [) }) {3 L+ _
版权声明:正点原子8 J4 H; G& M# V5 y& f; Z* v* g
; a. b8 ~, F, c( J- U

3 B8 }$ ~1 O1 M7 X! K$ ]0 _8 W; R, I% n
收藏 评论0 发布时间:2022-9-28 18:51

举报

0个回答

所属标签

相似分享

官网相关资源

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