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

MiniPro STM32H750 开发指南_V1.1-硬件随机数实验

[复制链接]
STMCU小助手 发布时间:2022-10-7 19:16
硬件随机数实验
2 R9 I2 h$ M0 C8 F% {# n3 Y本章,我们将介绍STM32H750的硬件随机数发生器。我们使用KEY0按键来获取硬件随机数,并且将获取到的随机数值显示在LCD上面。同时,使用LED0指示程序运行状态。
- S1 J# r  ]; M
2 n! |. V/ E! e, I: l2 Q& R28.1 随机数发生器简介
  w" ?& h0 o3 S, b, O# u& b9 f6 e
STM32H750自带了硬件随机数发生器(RNG),RNG处理器是一个以连续模拟噪声为基础的随机数发生器,在主机读数时提供一个32位的随机数。
; [# j/ i8 ?/ Q1 C& v, H' l28.1.1 RNG框图
1 m+ d9 r5 v# G1 f  ?+ h下面先来学习RNG框图,通过学习RNG框图会有一个很好的整体掌握,同时对之后的编程也会有一个清晰的思路。STM32H750的随机数发生器框图如图28.1.1.1所示:
7 K9 b# a, M% T
/ a9 l! X0 d" F& C, p. R 99d95b7257044648be07c5c92c60d4c1.png
1 d8 D3 U# ?9 y0 S5 [( t6 V
5 S8 E. t7 f0 Y- N6 p6 W图28.1.1.1 随机数发生器(RNG)框图
& r. j. ]' c' w7 s/ h随机数发生器有2个时钟域:AHB时钟域和RNG时钟域。AHB时钟域的时钟来自AHB2,用于访问相关寄存器等,通过AHB2ENR的RNGEN位(bit6)使能。
9 Y# U, V) {! x3 M( SRNG时钟域时钟为rng_clk,rng_clk由D2CCIP2R寄存器的RNGSEL[1:0]位选择具体的时钟源,具体选择关系为:0,hsi8_ck;1,pll1_q_ck;2,lse_ck;3,lsi_ck。我们一般选择pll1_q_ck作为rng_clk的时钟源(实验中调用sys_stm32_clock_init函数时设置了pll1_q_ck为240MHZ),因此设置RNGSEL[1:0]=1即可。AHB2ENR和D2CCIP2R这两个寄存器我们就不做介绍了,大家参考手册。
' ]+ I- C2 h3 d) W5 \从RNG框图整体上知道,RNG有两个输入和一个输出。具体如下表:
0 s$ `" a/ x, r! W* o- |3 C' @
% K3 J0 W) @1 o  o8 r) |$ z 7dbaf6ccad9e4a4d8290f414c4e1460c.png , {3 v1 G# m/ H
1 f8 Z1 r8 i" k3 z
表28.1.1.1 RNG内部输入/输出信号
) g. _8 J3 M  o- ~% bSTM32H750的随机数发生器(RNG)采用模拟电路实现,由内部两个模拟噪声源产生种子,经过采样和归一化处理,再经过线性移位寄存器和判断逻辑,最终输出到RNG_DR,生成32 位随机数。
! W, L) l% c0 ~每个模拟噪声源由3个环形振荡器组成,振荡器产生的输出经过异或运算产生种子,经过采样归一化处理后,输出到RNG内部的线性移位寄存器。采样频率由rng_clk时钟提供,因此,随机数质量与 HCLK 频率无关。当将大量种子引入线性移位寄存器后,经过判断逻辑,最终输出到数据寄存器 (RNG_DR)。
5 g- K$ h1 y9 M同时,系统会监视模拟种子和专用时钟 rng_clk,当种子上出现异常序列,或rng_clk时钟频率过低时,可以由RNG_SR寄存器的对应位读取到,如果设置了中断,则在检测到错误时,还可以产生中断。! w, f  Y! K7 P; A8 z4 b. q! m0 n. \* L

8 A1 }- V5 N4 {" P( P3 h/ p3 C) ?28.1.2 RNG寄存器
- ]$ T4 L* q3 T2 G$ k3 o3 R9 ?RNG控制寄存器(RNG_CR)& J, W2 ]$ U2 m9 b* v4 d9 g
RNG控制寄存器描述如图28.1.2.1所示:- E4 U  C( d2 t/ X/ ?
) D# k; S0 ^, P: }
50bbdb3d9278425db2d8c62d6fe70c2c.png
) K0 l) b1 K  g( E# C: ]1 \8 s0 H* t, i0 H1 A: i
图28.1.2.1 RNG_CR寄存器
9 u( D" M$ y6 Y4 w9 }5 v该寄存器我们只关心RNGEN位,该位用于使能随机数发生器,所以必须设置为1。
% R  W" P( n+ g! E3 `4 ?RNG状态寄存器(RNG_SR)+ R+ T8 g& ~# _4 i; Z' D1 B
RNG状态寄存器描述如图28.1.2.2所示:1 j/ ]/ h5 k& E% f5 Y1 x3 h
. [: }$ ?8 H/ H/ t/ b+ |4 l' f! X' `
fe3642fdf12844a38cc48c017f4e4c9f.png
# d; g: P; N; |' K/ g1 R$ A3 ^0 L; h' T9 i7 o# s
图28.1.2.2 RNG_SR寄存器
. E9 Z4 R3 M2 L. X- o4 @* _) w该寄存器我们仅关心最低位(DRDY位),该位用于表示RNG_DR寄存器包含的随机数数据是否有效,如果该位为1,则说明RNG_DR的数据是有效的,可以读取出来了。读RNG_DR后,该位自动清零。4 C$ T! \) S- q) q6 W
RNG数据寄存器(RNG_DR)
. s7 w  A5 ]& l. E# ]. o: Z* ^! tRNG数据寄存器描述如图28.1.2.3所示:
7 n* [/ L' i) D
- w# G- u* C9 [; M% U/ t 8db3b77bd38d4fb49643a113c1d7bc31.png
. V! A6 T. q; N% c; s: c. o/ P- o* R* B+ Z9 J4 k+ O* O% m$ l1 G
图28.1.2.3 RNG_DR寄存器4 @. @: t. I1 a1 a
RNG_DR寄存器是只读寄存器,我们可以读取该寄存器获得32位随机数值。此寄存器在最多216个AHB时钟周期后,又可以提供新的随机数值。
0 v; P# w; f: u& F6 l, E* Q7 q8 Z2 }28.2 硬件设计
& s* l, X1 a! Y) o! A0 E* t  d1.例程功能# U0 k* ?8 j& `1 q! D& q
本实验使用STM32H750自带的硬件随机数生成器(RNG),获取随机数,并显示在LCD屏幕上。按KEY0可以获取一次随机数。同时程序自动获取0~9范围内的随机数,显示在屏幕上。LED0闪烁用于提示程序正在运行。* Z' |1 m* H* u# g
2.硬件资源
3 ]/ e' j, w& P9 E8 ~% C' C% p1)RGB灯; U% t: o3 Z7 {$ V% Z
RED : LED0 - PB47 Q8 w6 H: h! Q- m
2)独立按键 KEY0 - PA1: ^: l  R; ?& D. d; p# U9 {  `
3)串口1(PA9/PA10连接在板载USB转串口芯片CH340上面)2 K7 j$ z2 x, s, ~
4)正点原子2.8/3.5/4.3/7/10寸TFTLCD模块(仅限MCU屏,16位8080并口驱动)& n" r, r# H" F4 E' _
5)RNG(硬件随机数生成器)" H% T+ e- m! o
3.原理图
/ h  X: k6 L# ~9 X( \% K- zRNG属于STM32H750内部资源,通过软件设置好就可以了。本实验通过配合按键获取随机数和通过LCD显示。8 N& Z: H/ X' d# e! b5 j: Z# R

7 A' o* s  R1 A. k" @1 P28.3 程序设计& Q. l  a  `1 ]1 E" r' a2 Z
28.3.1 RNG的HAL库驱动
+ T9 u, `  I: U( J& {
RNG在HAL库中的驱动代码在stm32h7xx_hal_rng.c文件(及其头文件)中。8 k' ?3 w. }3 S7 m* Z( M7 g
1.HAL_RNG_Init函数( Q4 y2 ^) S8 J- C9 A
RNG的初始化函数,其声明如下:5 P) K( \2 s2 d. [$ J+ T
HAL_StatusTypeDef HAL_RNG_Init(RNG_HandleTypeDef *hrng);& h1 ]7 c4 @6 ]' e
函数描述:
, J4 f8 e4 o& W  R  z8 I. N用于初始化RNG。$ B& Q8 e& t3 R1 k2 r6 K$ l
函数形参:% q+ b2 L& ?$ @% V
形参1是RNG_HandleTypeDef结构体类型指针变量,其定义如下:* {9 C# n5 P0 l; w; D  \. g
  1. typedef struct
    + s2 U8 j+ \2 D1 z' R
  2. {% C$ ?7 c8 T' Q  L, u3 |
  3.   RNG_TypeDef                                 *Instance;            /* RNG基地址 */4 u1 b1 B% Y6 r5 O: W8 `- g
  4.   RNG_InitTypeDef                       Init;                 /* RNG初始化配置结构体 */9 p+ [( P5 j; d, P5 c, R1 O
  5.   HAL_LockTypeDef                       Lock;                 /* RNG锁设置 */( E8 k- N: e2 |8 r( m
  6.   __IO HAL_RNG_StateTypeDef           State;                /* RNG设备访问状态 */
    % l" x9 Y; w  r
  7.   __IO  uint32_t                        ErrorCode;            /* RNG错误代码 */
    0 Y3 |$ ^  r% T: Z% T* Q# L, f* h8 @
  8.   uint32_t                              RandomNumber;         /* RNG最后生成的随机数 */
    ! `! m% I3 X; l" G
  9. } RNG_HandleTypeDef;
复制代码

% a! h' b5 E7 ^$ s9 k2 C; M# w1)Instance:指向RNG寄存器基地址。
# R2 [& s! b0 ?  o% u" F) O2 G4 D2)Init:是的RNG初始化结构体,其结构体类型RTC_InitTypeDef定义如下:/ R0 F$ Q# e2 e0 W) C. z/ n
typedef struct* @, t; h# U# e2 j/ h. j& m9 \% s
{
4 x8 T5 {6 o1 h& x: U4 xuint32_t ClockErrorDetection; /* CED时钟错误检测 */
  e8 L: P' }! t  R+ m} RNG_InitTypeDef;# Z: q4 N4 F6 x, ^! l
3)Lock:用于配置锁状态。. ~9 D! ?0 T: |. Z( C- I
4)State:RNG设备访问状态。) ?$ f" U& W' b3 g
5)ErrorCode :RNG错误代码
- l$ V1 v! u4 K) X6)RandomNumber :该变量存储RNG最后生成的随机数
3 ~* B* S6 G& E1 w- i( ~9 ~函数返回值:* b2 x* ]+ W3 A
HAL_StatusTypeDef枚举类型的值。
; Q( ^* d0 t+ a0 V7 a% o( E2. HAL_RNG_GenerateRandomNumber函数
' ]* Z& t9 b5 ]HAL_RNG_GenerateRandomNumber是RNG生成随机数函数。其声明如下:5 c0 J0 Y9 f, R3 x5 {/ m1 j
HAL_StatusTypeDef HAL_RNG_GenerateRandomNumber(RNG_HandleTypeDef *hrng,' d, M# w4 b: q3 O" v7 s
uint32_t *random32bit);  c$ B. j9 Y4 e: x. U2 ]5 J
函数描述:
* j/ _. k$ K$ _9 ?( e0 @  t该函数用于RNG生成随机数。2 ^  L% N6 I  Q
函数形参:
* r& m: C0 \+ m) G形参1是RNG_HandleTypeDef结构体类型指针变量,即RNG的句柄。3 V7 I: m+ F7 ~. j' F
形参2是uint32_t类型指针变量,随机32位指针,生成随机变量。1 G& R6 S8 X8 o1 z4 ?
函数返回值:
/ W/ b; ]4 T7 F- z' T( Z+ vHAL_StatusTypeDef枚举类型的值。
: W! H& a$ R) @( q) h, V- K+ zRNG配置步骤
2 h' }/ k7 B( ^% z, l0 _2 i1)使能随机数发生器时钟" a6 Q2 U$ p7 \5 u9 F% N3 z
调用__HAL_RCC_RNG_CLK_ENABLE函数使能随机数发生器时钟,实际是通过设置AHB2ENR寄存器的相关位。
9 m, U  G2 c5 F" k6 U: \* w2)初始化(使能)随机数发生器1 M2 G* g  G$ i3 u- |. `; ^
通过调用HAL_RNG_Init函数初始化随机数发生器,然后自行调用RNG的MSP回调函数,并使能随机数发生器。3 e$ y1 h" L# ]2 U: Y$ j4 ~
当我们使用HAL_RNG_Init之后,在该函数内部,会调用RNG的MSP回调函数。回调函数中一般编写与MCU相关的外设时钟初始化以及NVIC配置。
. g4 E$ c1 V, C+ d* `9 I3)判断DRDY位,读取随机数值! w% ^, Y9 P& a. K; l: f! D
经过前面两个步骤,我们就可以读取随机数值了,不过每次读取之前,必须先判断RNG_SR寄存器的DRDY位,如果该位为1,则可以读取RNG_DR得到随机数值,如果不为1,则需要等待。 在HAL库中,通过调用HAL_RNG_GenerateRandomNumber函数判断DRDY位并读取随机数值。3 V) O  D+ Q6 q3 J0 B4 e3 p; ]
通过以上3个步骤的设置,我们就可以使用STM32H7的随机数发生器(RNG)了。
9 D3 p: F0 F4 [2 _28.3.2 程序流程图
& R9 ]" O1 i. {# |
5 \0 R: D3 x3 r$ Y7 q" Y 24b52f5fb8f74c17be59bb8a9618d785.png 7 W8 A! \7 J! }4 M% C/ y6 C* O7 M

" S7 n1 q& T- [& q# p  G! F图28.3.2.1 硬件随机数实验程序流程图
: M  q- W  \( }2 I# X+ Q+ ]: f% Q) Q, C4 K) V! i" v" }
28.3.3 程序解析! |# T/ }6 `- @) Z- e7 ?
1.RNG驱动代码
/ s: Z4 `/ Y+ w9 A这里我们只讲解核心代码,详细的源码请大家参考光盘本实验对应源码。RNG驱动源码包括两个文件:rng.c和rng.h。: d) s8 R: x1 }" `  `. d
rng.h头文件只有函数的声明,下面我们直接介绍rng.c的程序,先看RNG的初始化函数,其定义如下:+ a; p- v. K' d# s+ q4 N2 y" g
  1. /**" Q. M; o& s8 P. Z6 E) L; |* U8 I
  2. * @brief              初始化RNG
    2 c9 ~# W" J4 m0 n3 v  M
  3. * @param               无% Q( u2 m. j6 V
  4. * @retval              0,成功;1,失败0 J" r$ ^  Q. m) I  d+ J
  5. */4 B+ ]* f+ _: `0 V$ I
  6. uint8_t rng_init(void)( T5 _& v( M8 Q$ y" k$ z
  7. {
    + c7 r( ]: m2 L5 {& I  A0 A
  8.     uint16_t retry = 0;9 n' m# D. A1 m

  9. ) I. I' t9 [! G, O( x
  10.     rng_handle.Instance = RNG;   ( z5 o0 ^( D$ b" w
  11.     HAL_RNG_DeInit(&rng_handle);% ^, C5 t3 Q0 i
  12.     HAL_RNG_Init(&rng_handle);        /* 初始化RNG */
    : g4 x1 v8 Z. y7 Y7 [! K2 P
  13. while (__HAL_RNG_GET_FLAG(&rng_handle, RNG_FLAG_DRDY) == RESET + t8 Z/ x$ `. b% q9 R) L8 r5 Z
  14. && retry < 10000)                         /* 等待RNG准备就绪 */& M' Z- \, o& p# C; R  j8 n
  15.     {- Y5 H1 P" i. _3 R
  16.         retry++;
    # o8 c- N+ l' i+ a% d3 s
  17.         delay_us(10);0 {* T5 x+ `9 J: I2 h7 \$ i, R
  18.     }8 A" C' u4 U% B6 ^
  19.     if (retry >= 10000)- j  [( h% Z9 P6 `' O0 v) I
  20.     {0 y) @7 b  g3 q6 z  p& B, j0 p6 f
  21.         return 1; /* 随机数产生器工作不正常 */) W- U/ ^; F% L- g/ \/ A
  22.     }, H& U3 E& U+ f7 a9 l1 S
  23.     return 0;
    6 ~7 a! E4 s& e8 Z. k4 ?) n
  24. }
复制代码

$ Y8 N- d# m4 C% N1 R" Vrng_init函数中调用HAL_RNG_Init函数初始化RNG,然后等待RNG初始化完成,同时判断初始化过程是否超时。% Y8 I2 S$ K' C$ p4 {
我们用HAL_RTC_MspInit回调函数来编写RNG时钟配置等代码,其定义如下:
0 F$ ~9 z& S/ m8 [- C$ i
" U& h) H& W* h* E1 L
  1. /**
    5 f% ]3 s- q) Z( b
  2. * @brief             RNG底层驱动,时钟源设置和使能2 C, `* C6 a/ E# E
  3. * @note                此函数会被HAL_RNG_Init()调用0 v& B. w# K  o. P4 R
  4. * @param               hrng:RNG句柄
      C+ B0 E* {  z" T
  5. * @retval              无
    1 L! H: @8 {8 }# ^- I( y4 b
  6. */
    ' q* l, p5 e/ V' r8 n( q  w: y
  7. void HAL_RNG_MspInit(RNG_HandleTypeDef *hrng)
    & o5 |/ u  S+ t. ~
  8. {) j7 a3 F8 L! e
  9.     RCC_PeriphCLKInitTypeDef RNGClkInitStruct;5 H5 H7 R3 N+ A0 R0 S
  10. 9 X9 q! l1 Y6 d) L* u) o: @* D
  11.     /* 设置RNG时钟源,选择PLL,时钟为480MHz */
    + k7 Q; |1 e' ~  p  }, h, B
  12.     RNGClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RNG;/* 设置RNG时钟源 */2 D3 x7 Z2 [* |/ ~/ E
  13.     RNGClkInitStruct.RngClockSelection =RCC_RNGCLKSOURCE_PLL;/*RNG时钟源选择PLL*/
    " u( c/ [8 m! I
  14.     HAL_RCCEx_PeriphCLKConfig(&RNGClkInitStruct);- j2 ^0 n' }; g1 b6 U0 S/ |
  15. : t% k. Y8 o5 q& V
  16.     __HAL_RCC_RNG_CLK_ENABLE();/* 使能RNG时钟 */9 l( z) ]. e9 H- r3 K9 A
  17. }
复制代码
8 K2 \/ P8 v6 p4 {8 |7 P1 Q' Q, U6 Z
最后两个是我们获取随机数函数,它们的定义如下:# _) u& V# s) q' r9 C1 I
6 w! v0 P$ b  r0 ~3 H
  1. /**
    $ ^0 D9 P9 k9 i: i( Q
  2. * @brief             得到随机数8 ?' F# b# e5 N( Q
  3. * @param              无
    5 K  H- k/ |5 @3 ^; G
  4. * @retval             获取 到的随机数(32bit)" ~  k4 `+ L: Z) ?
  5. */, @3 i, k% _0 ?& ^2 N
  6. uint32_t rng_get_random_num(void)
    + j6 N0 d( A/ q$ b; o4 M  ~* g% F
  7. {
    ) S0 T9 A; t2 j3 z. L. a
  8.     uint32_t randomnum;
    . r$ U, W3 h+ W
  9.     HAL_RNG_GenerateRandomNumber(&rng_handle, &randomnum);9 t" F6 B7 ^! T8 W
  10.     return randomnum;( N' O- Z" H) R1 A  U% m
  11. }5 Y* s/ k, x! h/ }
  12. ( i* a0 a' `: e  x! w1 g
  13. /**! H( |8 T& k, ?2 s
  14. * @brief       得到某个范围内的随机数
    2 Q# S, I/ p7 I4 z
  15. * @param       min,max: 最小,最大值.5 g( ?8 k6 {) i: P
  16. * @retval      得到的随机数(rval),满足:min<=rval<=max
    # g6 P* G0 p  m; q2 n2 ^$ ^
  17. */$ l+ ~8 c7 K. |; U% |
  18. int rng_get_random_range(int min, int max)5 z1 v" z, `; E5 ?) Z- N; t
  19. { $ I2 {/ U- [% H  Y
  20.     uint32_t randomnum;
    * M1 M. Q; P! U/ {
  21.     HAL_RNG_GenerateRandomNumber(&rng_handle, &randomnum);7 Z4 \3 J6 N$ @" Z& i
  22.     return randomnum%(max-min+1) + min;' S3 v) g+ M! r7 F4 m
  23. }
复制代码

+ ^1 G0 Y9 c- r/ v' k* ~$ \" |  l& d其中rng_get_random_num用于读取随机数值,而rng_get_random_range用于读取一个特定范围内的随机数,实际上它们都是通过调用的函数HAL_RNG_GenerateRandomNumber来实现的。1 {4 w1 z0 a4 R7 w  A) f- n; j( y
2. main.c代码
( ]+ Z7 Y6 `; D3 ^0 s% K  e9 @5 \在main.c里面编写如下代码:. b" A! ]! `7 G7 W4 t6 |$ S) I

2 h, k9 r  G, [& [  a! _1 D
  1. int main(void)
    % c/ s8 W& W  @* R1 z" }
  2. {% R& j* A5 i. ^* z( Y( u' }5 M
  3.     uint32_t random;- D6 D, }3 Q  J" [
  4. uint8_t t = 0, key;. u. ]  s* t* m) r- `1 K
  5. 2 \) W  {" {) f4 `; `6 I3 @
  6.     sys_cache_enable();                                  /* 打开L1-Cache */+ y) g/ U: ?! s0 N, D
  7.     HAL_Init();                                          /* 初始化HAL库 */, Y/ d) q; h# w! J- ~4 {
  8.     sys_stm32_clock_init(240, 2, 2, 4);         /* 设置时钟, 480Mhz */
    # ~0 p/ h1 e- v; h* x
  9.     delay_init(480);                                     /* 延时初始化 */
    - x6 H8 X% Q& w/ o
  10.     usart_init(115200);                                 /* 串口初始化为115200 */
    # B" w; Z6 W( }: F) R
  11.     usmart_dev.init(240);                               /* 初始化USMART */& q( K0 L5 {( D
  12.     mpu_memory_protection();                           /* 保护相关存储区域 */3 v  M9 n" w( ~  a; v8 h, M& a( O, ]
  13.     led_init();                                      /* 初始化LED */
    6 J- M1 \( a9 b6 I$ E
  14.     lcd_init();                                         /* 初始化LCD */! Y& G! {  ?3 N' C- W
  15.     key_init();                                         /* 初始化按键 */, v, ^2 K( p8 q6 D; p' [
  16.   z# d% F* [0 X( N: L
  17.     lcd_show_string(30, 50, 200, 16, 16, "STM32", RED);: K. j& q8 @. \+ K4 s% W6 e
  18.     lcd_show_string(30, 70, 200, 16, 16, "RNG TEST", RED);" Y' l3 F" y' N7 k; d. o7 s* t; ~
  19.     lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);' R% k% s1 o6 Y. q" R! j0 w

  20. , _+ k+ o  E" r, N0 y/ n
  21.     while (rng_init())  /* 初始化随机数发生器 */
    - w% @) F+ l( I. B1 \3 O
  22.     {" B7 j7 U. N) r  ]+ V0 Q4 O9 i# k: @
  23.         lcd_show_string(30, 130, 200, 16, 16, "  RNG Error! ", RED);. `* R7 z' j" Q# J$ J; Q) v
  24.         delay_ms(200);
    5 H8 |1 L1 q% ^' }# q, v
  25.         lcd_show_string(30, 130, 200, 16, 16, "RNG Trying...", RED);8 Q: m9 k3 b% Y7 ~3 Z6 G
  26.     }& K; Q# y8 q% E' J# q7 f& k3 x) t

  27. + ~- L" E  z) H/ v
  28.     lcd_show_string(30, 110, 200, 16, 16, "RNG Ready!   ", RED);
    # F" }( w0 X% D( N; W; m' w2 E' X' c
  29.     lcd_show_string(30, 130, 200, 16, 16, "KEY0:Get Random Num", RED);
    ' z* A0 X& `2 x( [
  30.     lcd_show_string(30, 150, 200, 16, 16, "Random Num:", RED);
    9 M# B8 T, @2 X, x) ?5 |9 ]
  31.     lcd_show_string(30, 180, 200, 16, 16, "Random Num[0-9]:", RED); / r) Y2 }% m5 G* j: J
  32. ) m: c5 H! p& m) F! W
  33.     while (1)
    7 Y! P; j! g, H) j* k6 t
  34.     {( N( A9 ?* D$ L2 |
  35.         key = key_scan(0);, `/ ]. S; A. ]* N
  36. & y7 ^0 x% C0 Z* J- G% T3 j
  37.         if (key == KEY0_PRES)9 f0 z' e* ]6 p1 K" e) T2 t
  38.         {
    3 C1 L9 d3 K0 A
  39.             random = rng_get_random_num();
    $ a$ f8 G$ J  y
  40.             lcd_show_num(30 + 8 * 11, 180, random, 10, 16, BLUE);8 @1 S% r& w5 r$ G. Q
  41.         }6 Q/ u9 h2 f2 V6 I4 |3 B* v3 W: C
  42. " ~0 a5 Y! V9 ^6 T; \. V' Q
  43.         if ((t % 20) == 0)
    - K' W; r+ D" U$ A$ X; W* `9 m
  44.         {3 D5 w! f. }' \, I, A2 D0 e% R! Z
  45.             LED0_TOGGLE();                                   /* 每200ms,翻转一次LED0 */* Z9 n. f' G& E; X; @- |7 U
  46.             random = rng_get_random_range(0, 9);        /* 取[0,9]区间的随机数 */; `  T/ u& V9 [# \
  47.             lcd_show_num(30 + 8 * 16, 210, random, 1, 16, BLUE);/* 显示随机数 */
    $ _0 f# J6 X  v9 \; b/ A
  48.         }7 D. ~- T% \* a  @! [% S1 S$ }

  49. + I  o# r5 u/ F; g$ K; u' k
  50.         delay_ms(10);7 b  w+ e0 {  d+ q
  51.         t++;
    3 Y! A9 O! s9 t' A
  52.     }
    : k# h- }0 A( d9 b8 j4 r
  53. }
复制代码

5 M3 J; g1 c3 b& h( S0 d) ~8 L/ a: h该部分代码也比较简单,在所有外设初始化成功后,进入死循环,等待按键按下,如果KEY0按下,则调用rng_get_random_num函数,读取随机数值,并将读到的随机数显示在LCD上面。每隔200ms获取一次区间[0,9]的随机数,并实时显示在液晶上。同时LED0,周期性闪烁,400ms闪烁一次。
% {* r; S. j- V最后,为了方便测试,我们将rng_get_random_num和rng_get_random_range加入USMART,修改usmart_nametab如下:
. R) {4 U  [4 W6 Q
. Z3 S9 D2 Q1 m3 F: B
  1. struct _m_usmart_nametab usmart_nametab[] =
    % W- j; P$ Q( u5 {
  2. {: z6 \5 X( w9 H+ U" K  c: C
  3. #if USMART_USE_WRFUNS == 1      /* 如果使能了读写操作 */# h1 v+ R# P0 ]. u# z
  4.     (void *)read_addr, "uint32_t read_addr(uint32_t addr)",/ e% v: ^1 N/ Q% d
  5.     (void *)write_addr, "void write_addr(uint32_t addr,uint32_t val)",, @& ~: p$ f8 g% C
  6. #endif
      k6 {5 g: U7 [1 b& J$ O
  7.     (void *)delay_ms, "void delay_ms(uint16_t nms)",
    3 L) D# d" i. j, R
  8.     (void *)delay_us, "void delay_us(uint32_t nus)",
    ( O6 D4 W. @9 F! t& b* E$ w

  9. # I( d; A2 |( I/ n  R
  10.     (void *)rng_get_random_num, "uint32_t rng_get_random_num(void)",
    % v" n4 s- Q5 h+ {
  11.     (void *)rng_get_random_range, "int rng_get_random_range(int min,int max)",9 x+ t. b! t4 `. D/ i4 u' p
  12. };
复制代码
' Y6 T( h0 H3 W
这样,我们便可以在串口输入我们想要调用的函数(rng_get_random_range或rng_get_random_num)进行测试。
, }6 i; f/ ?$ |% h. \7 [+ ~. r4 a6 N5 [" f
28.4 下载验证
- y* R: }6 O+ {% U0 s将程序下载到开发板后,可以看到LED0不停的闪烁,提示程序已经在运行了。然后我们按下KEY0,就可以在屏幕上看到获取到的随机数。同时,就算不按KEY0,程序也会自动的获取0~9区间的随机数显示在LCD上面。实验结果如图28.4.1所示:
3 B0 C$ S+ }4 v: N! P& U. a, v/ \. N5 O- N- }" q
bf64b55259274116b35751809ad0db1d.png
! G$ z6 B& b, d, @7 E4 H8 M/ B& ], }6 P% R' T9 z8 _) T& k
图28.4.1 获取随机数成功
- G- L! }. ]$ v% T0 X然后,我们还可以在串口调试助手里面,调用rng_get_random_num和rng_get_random_range函数,测试这两个函数的功能,大家可以自行测试。$ K6 y' q4 h3 p# s7 c
————————————————1 H3 ^3 K' ?' r
版权声明:正点原子
& D1 g! r# }) |3 O% D$ `, ]  f7 g0 J& c
7 k9 E. x" N  z4 E# h& {
赞 收藏 评论0 发布时间:2022-10-7 19:16

举报

0个回答

所属标签

相似技术帖

官网相关资源

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