1)实验平台:正点原子MiniPro H750开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=677017430560 3)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-336836-1-1.html 4)对正点原子STM32感兴趣的同学可以加群讨论:879133275
第二十八章 硬件随机数实验本章,我们将介绍STM32H750的硬件随机数发生器。我们使用KEY0按键来获取硬件随机数,并且将获取到的随机数值显示在LCD上面。同时,使用LED0指示程序运行状态。 本章分为如下几个小节: 28.1 随机数发生器简介 28.2 硬件设计 28.3 程序设计 28.4 下载验证
28.1 随机数发生器简介STM32H750自带了硬件随机数发生器(RNG),RNG处理器是一个以连续模拟噪声为基础的随机数发生器,在主机读数时提供一个32位的随机数。 28.1.1 RNG框图 下面先来学习RNG框图,通过学习RNG框图会有一个很好的整体掌握,同时对之后的编程也会有一个清晰的思路。STM32H750的随机数发生器框图如图28.1.1.1所示:
图28.1.1.1 随机数发生器(RNG)框图 随机数发生器有2个时钟域:AHB时钟域和RNG时钟域。AHB时钟域的时钟来自AHB2,用于访问相关寄存器等,通过AHB2ENR的RNGEN位(bit6)使能。 RNG时钟域时钟为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这两个寄存器我们就不做介绍了,大家参考手册。 从RNG框图整体上知道,RNG有两个输入和一个输出。具体如下表:
表28.1.1.1 RNG内部输入/输出信号 STM32H750的随机数发生器(RNG)采用模拟电路实现,由内部两个模拟噪声源产生种子,经过采样和归一化处理,再经过线性移位寄存器和判断逻辑,最终输出到RNG_DR,生成32 位随机数。 每个模拟噪声源由3个环形振荡器组成,振荡器产生的输出经过异或运算产生种子,经过采样归一化处理后,输出到RNG内部的线性移位寄存器。采样频率由rng_clk时钟提供,因此,随机数质量与 HCLK 频率无关。当将大量种子引入线性移位寄存器后,经过判断逻辑,最终输出到数据寄存器 (RNG_DR)。 同时,系统会监视模拟种子和专用时钟 rng_clk,当种子上出现异常序列,或rng_clk时钟频率过低时,可以由RNG_SR寄存器的对应位读取到,如果设置了中断,则在检测到错误时,还可以产生中断。
28.1.2 RNG寄存器RNG控制寄存器(RNG_CR) RNG控制寄存器描述如图28.1.2.1所示:
图28.1.2.1 RNG_CR寄存器 该寄存器我们只关心RNGEN位,该位用于使能随机数发生器,所以必须设置为1。 RNG状态寄存器(RNG_SR) RNG状态寄存器描述如图28.1.2.2所示:
图28.1.2.2 RNG_SR寄存器 该寄存器我们仅关心最低位(DRDY位),该位用于表示RNG_DR寄存器包含的随机数数据是否有效,如果该位为1,则说明RNG_DR的数据是有效的,可以读取出来了。读RNG_DR后,该位自动清零。 RNG数据寄存器(RNG_DR) RNG数据寄存器描述如图28.1.2.3所示:
图28.1.2.3 RNG_DR寄存器 RNG_DR寄存器是只读寄存器,我们可以读取该寄存器获得32位随机数值。此寄存器在最多216个AHB时钟周期后,又可以提供新的随机数值。 28.2 硬件设计
- 例程功能 本实验使用STM32H750自带的硬件随机数生成器(RNG),获取随机数,并显示在LCD屏幕上。按KEY0可以获取一次随机数。同时程序自动获取0~9范围内的随机数,显示在屏幕上。LED0闪烁用于提示程序正在运行。
- 硬件资源 1)RGB灯 RED : LED0 - PB4 2)独立按键 KEY0 - PA1 3)串口1(PA9/PA10连接在板载USB转串口芯片CH340上面) 4)正点原子2.8/3.5/4.3/7/10寸TFTLCD模块(仅限MCU屏,16位8080并口驱动) 5)RNG(硬件随机数生成器)
- 原理图 RNG属于STM32H750内部资源,通过软件设置好就可以了。本实验通过配合按键获取随机数和通过LCD显示。
28.3.1 RNG的HAL库驱动 RNG在HAL库中的驱动代码在stm32h7xx_hal_rng.c文件(及其头文件)中。
- HAL_RNG_Init函数 RNG的初始化函数,其声明如下: HAL_StatusTypeDef HAL_RNG_Init(RNG_HandleTypeDef *hrng); 函数描述: 用于初始化RNG。 函数形参: 形参1是RNG_HandleTypeDef结构体类型指针变量,其定义如下:
typedef struct
{
RNG_TypeDef *Instance; /* RNG基地址 */
RNG_InitTypeDef Init; /* RNG初始化配置结构体 */
HAL_LockTypeDef Lock; /* RNG锁设置 */
__IO HAL_RNG_StateTypeDef State; /* RNG设备访问状态 */
__IO uint32_t ErrorCode; /* RNG错误代码 */
uint32_t RandomNumber; /* RNG最后生成的随机数 */
} RNG_HandleTypeDef;
1)Instance:指向RNG寄存器基地址。 2)Init:是的RNG初始化结构体,其结构体类型RTC_InitTypeDef定义如下: typedef struct { uint32_t ClockErrorDetection; /* CED时钟错误检测 */ } RNG_InitTypeDef; 3)Lock:用于配置锁状态。 4)State:RNG设备访问状态。 5)ErrorCode :RNG错误代码 6)RandomNumber :该变量存储RNG最后生成的随机数 函数返回值: HAL_StatusTypeDef枚举类型的值。 2. HAL_RNG_GenerateRandomNumber函数 HAL_RNG_GenerateRandomNumber是RNG生成随机数函数。其声明如下: HAL_StatusTypeDef HAL_RNG_GenerateRandomNumber(RNG_HandleTypeDef *hrng, uint32_t *random32bit); 函数描述: 该函数用于RNG生成随机数。 函数形参: 形参1是RNG_HandleTypeDef结构体类型指针变量,即RNG的句柄。 形参2是uint32_t类型指针变量,随机32位指针,生成随机变量。 函数返回值: HAL_StatusTypeDef枚举类型的值。 RNG配置步骤 1)使能随机数发生器时钟 调用__HAL_RCC_RNG_CLK_ENABLE函数使能随机数发生器时钟,实际是通过设置AHB2ENR寄存器的相关位。 2)初始化(使能)随机数发生器 通过调用HAL_RNG_Init函数初始化随机数发生器,然后自行调用RNG的MSP回调函数,并使能随机数发生器。 当我们使用HAL_RNG_Init之后,在该函数内部,会调用RNG的MSP回调函数。回调函数中一般编写与MCU相关的外设时钟初始化以及NVIC配置。 3)判断DRDY位,读取随机数值 经过前面两个步骤,我们就可以读取随机数值了,不过每次读取之前,必须先判断RNG_SR寄存器的DRDY位,如果该位为1,则可以读取RNG_DR得到随机数值,如果不为1,则需要等待。 在HAL库中,通过调用HAL_RNG_GenerateRandomNumber函数判断DRDY位并读取随机数值。 通过以上3个步骤的设置,我们就可以使用STM32H7的随机数发生器(RNG)了。 28.3.2 程序流程图
图28.3.2.1 硬件随机数实验程序流程图 28.3.3 程序解析
- RNG驱动代码 这里我们只讲解核心代码,详细的源码请大家参考光盘本实验对应源码。RNG驱动源码包括两个文件:rng.c和rng.h。 rng.h头文件只有函数的声明,下面我们直接介绍rng.c的程序,先看RNG的初始化函数,其定义如下:
/**
* @brief 初始化RNG
* @param 无
* @retval 0,成功;1,失败
*/
uint8_t rng_init(void)
{
uint16_t retry = 0;
rng_handle.Instance = RNG;
HAL_RNG_DeInit(&rng_handle);
HAL_RNG_Init(&rng_handle); /* 初始化RNG */
while (__HAL_RNG_GET_FLAG(&rng_handle, RNG_FLAG_DRDY) == RESET
&& retry = 10000)
{
return 1; /* 随机数产生器工作不正常 */
}
return 0;
}
rng_init函数中调用HAL_RNG_Init函数初始化RNG,然后等待RNG初始化完成,同时判断初始化过程是否超时。 我们用HAL_RTC_MspInit回调函数来编写RNG时钟配置等代码,其定义如下:
/**
* @brief RNG底层驱动,时钟源设置和使能
* @note 此函数会被HAL_RNG_Init()调用
* @param hrng:RNG句柄
* @retval 无
*/
void HAL_RNG_MspInit(RNG_HandleTypeDef *hrng)
{
RCC_PeriphCLKInitTypeDef RNGClkInitStruct;
/* 设置RNG时钟源,选择PLL,时钟为480MHz */
RNGClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RNG;/* 设置RNG时钟源 */
RNGClkInitStruct.RngClockSelection =RCC_RNGCLKSOURCE_PLL;/*RNG时钟源选择PLL*/
HAL_RCCEx_PeriphCLKConfig(&RNGClkInitStruct);
__HAL_RCC_RNG_CLK_ENABLE();/* 使能RNG时钟 */
}
最后两个是我们获取随机数函数,它们的定义如下:
/**
* @brief 得到随机数
* @param 无
* @retval 获取 到的随机数(32bit)
*/
uint32_t rng_get_random_num(void)
{
uint32_t randomnum;
HAL_RNG_GenerateRandomNumber(&rng_handle, &randomnum);
return randomnum;
}
/**
* @brief 得到某个范围内的随机数
* @param min,max: 最小,最大值.
* @retval 得到的随机数(rval),满足:min
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?