完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
2)摘自《STM32F7 开发指南(HAL 库版)》关注官方微信号公众号,获取更多资料:正点原子
第二十四章 硬件随机数实验 本章我们将向大家介绍 STM32F767 的硬件随机数发生器。在本章中,我们将使用 KEY0 按键来获取硬件随机数,并且将获取到的随机数值显示在 LCD 上面,同时,使用 DS0 指示程 序运行状态。本章将分为如下几个部分: 24.1 STM32F767 随机数发生器简介 24.2 硬件设计 24.3 软件设计 24.4 下载验证 24.1 STM32F767 随机数发生器简介 STM32F767 自带了硬件随机数发生器(RNG),RNG 处理器是一个以连续模拟噪声为基础 的随机数发生器,在主机读数时提供一个 32 位的随机数。STM32F767 的随机数发生器框图如 图 24.1.1 所示: 图 24.1.1 随机数发生器(RNG)框图 STM32F767 的随机数发生器(RNG)采用模拟电路实现。此电路产生馈入线性反馈移位寄 存器 (RNG_LFSR) 的种子,用于生成 32 位随机数。 该模拟电路由几个环形振荡器组成,振荡器的输出进行异或运算以产生种子。RNG_LFSR 由专用时钟 (PLL48CLK,即 RNG_CLK) 按恒定频率提供时钟信息,因此随机数质量与 HCLK 频率无关。当将大量种子引入 RNG_LFSR 后,RNG_LFSR 的内容会传入数据寄存器 (RNG_DR)。 同时,系统会监视模拟种子和专用时钟 PLL48CLK,当种子上出现异常序列,或 PLL48CLK 时钟频率过低时,可以由 RNG_SR 寄存器的对应位读取到,如果设置了中断,则在检测到错误 时,还可以产生中断。 接下来,我们介绍下 STM32F767 随机数发生器(RNG)的几个寄存器。 首先是 RNG 控制寄存器:RNG_CR,该寄存器各位描述如图 24.1.2 所示: 图 24.1.2 RNG_CR 寄存器各位描述 该寄存器只有 bit2 和 bit3 有效,用于使能随机数发生器和中断。我们一般不用中断,所以 只需要设置 bit2 为 1,使能随机数发生器即可。 然后,我们看看 RNG 状态寄存器:RNG_SR,该寄存器各位描述如图 23.1.3 所示: 图 24.1.3 RNG_SR 寄存器各位描述 该寄存器我们仅关心最低位(DRDY 位),该位用于表示 RNG_DR 寄存器包含的随机数数 据是否有效,如果该位为 1,则说明 RNG_DR 的数据是有效的,可以读取出来了。读 RNG_DR 后,该位自动清零。 最后,我们看看 RNG 数据寄存器:RNG_DR,该寄存器各位描述如图 24.4.3 所示: 图 24.1.3 RNG_SR 寄存器各位描述 在 RNG_SR 的 DRDY 位置位后,我们就可以读取该寄存器获得 32 位随机数值。此寄存器 在最多 40 个 PLL48CK 时钟周期后,又可以提供新的随机数值。 至此,随机数发生器的寄存器,我们就介绍完了。接下来,我们看看要使用 HAL 库操作 随机数发生器,应该如何设置。 首先,我们要说明的是,库函数中随机数发生器相关的操作在文件 stm32f7xx_hal_rng.c 和 对应的头文件 stm32f7xx_hal_rng.h 中。所以我们实验工程必须引入这两个文件。 随机数发生器操作步骤如下: 1)使能随机数发生器时钟。 要使用随机数发生器,必须先使能其时钟。随机数发生器时钟来自 PLL48CK,通过 2)初始化(使能)随机数发生器。 AHB2ENR 寄存器使能。 HAL 库使能随机数发生器时钟方法为: __HAL_RCC_RNG_CLK_ENABLE();//使能 RNG 时钟HAL 库提供了 HAL_RNG_Init 函数,该函数非常简单,主要作用是引导调用 RNG 的 MSP 回调函数,然后使能随机数发生器。该函数声明如下: HAL_StatusTypeDef HAL_RNG_Init(RNG_HandleTypeDef *hrng);该函数非常简单,这里我们就不做过多讲解。使用方法如下:RNG_HandleTypeDef RNG_Handler; //RNG 句柄RNG_Handler.Instance=RNG;HAL_RNG_Init(&RNG_Handler);//初始化 RNG当我们使用 HAL_RNG_Init 之后,在该函数内部,会调用 RNG 的 MSP 回调函数,回调函 数声明如下: void HAL_RNG_MspInit(RNG_HandleTypeDef *hrng);回调函数中一般编写与 MCU 相关的外设时钟初始化以及 NVIC 配置。 同时,HAL 库也提供了单独使能随机数发生器的方法为: __HAL_RNG_ENABLE(hrng); //使能 RNG3)判断 DRDY 位,读取随机数值。 经过前面两个步骤,我们就可以读取随机数值了,不过每次读取之前,必须先判断 RNG_SR 寄存器的 DRDY 位,如果该位为 1,则可以读取 RNG_DR 得到随机数值,如果不为 1,则需要 等待。 在 HAL 库中,判断 DRDY 位并读取随机数值的函数为: uint32_t HAL_RNG_GetRandomNumber(RNG_HandleTypeDef *hrng);通过以上几个步骤的设置,我们就可以使用 STM32F7 的随机数发生器(RNG)了。本章, 我们将实现如下功能:通过 KEY0 获取随机数,并将获取到的随机数显示在 LCD 上面,通过 DS0 指示程序运行状态。 24.2 硬件设计 本实验用到的硬件资源有: 1) 指示灯 DS0 2) 串口 3) KEY0 按键 4) 随机数发生器(RNG) 5) LCD 模块 这些资源,我们都已经介绍了,硬件连接上面也不需要任何变动,插上 LCD 模块即可。 24.3 软件设计 打开本章的实验工程可以看到,我们在 HALLIB 下面添加了随机数发生器支持库函数 stm32f7xx_hal_rng.c 和对应的头文件 stm32f7xx_hal_rng.h。同时我们编写的随机数发生器相关 的函数在新增的文件 rng.c 中。 接下来我们看看 rng.c 源文件内容: RNG_HandleTypeDef RNG_Handler; //RNG 句柄//初始化 RNGu8 RNG_Init(void){ u16 retry=0; RNG_Handler.Instance=RNG; HAL_RNG_Init(&RNG_Handler);//初始化 RNG while(__HAL_RNG_GET_FLAG(&RNG_Handler,RNG_FLAG_DRDY)==RESET&&retry<10000)//等待 RNG 准备就绪 { retry++; delay_us(10); } if(retry>=10000) return 1;//随机数产生器工作不正常 return 0;}void HAL_RNG_MspInit(RNG_HandleTypeDef *hrng){ __HAL_RCC_RNG_CLK_ENABLE();//使能 RNG 时钟}//得到随机数//返回值:获取到的随机数u32 RNG_Get_RandomNum(void){ return HAL_RNG_GetRandomNumber(&RNG_Handler);}//生成[min,max]范围的随机数int RNG_Get_RandomRange(int min,int max){ return HAL_RNG_GetRandomNumber(&RNG_Handler)%(max-min+1) +min;}该部分总共 4 个函数,其中:RNG_Init 用于初始化随机数发生器;HAL_RNG_MspInit 函 数是随机数发生器 MSP 回调函数,该函数下面只有一行代码就是使能 RNG 时钟。 RNG_Get_RandomNum 用于读取随机数值;RNG_Get_RandomRange 用于读取一个特定范围内 的随机数,实际上也是调用的函数 HAL_RNG_GetRandomNumber 来实现的。这些函数的实现 方法都比较好理解。 最后我们看看 main.c 文件内容: int main(void){ u32 random; u8 t=0,key; Cache_Enable(); //打开 L1-Cache‘ HAL_Init(); //初始化 HAL 库 Stm32_Clock_Init(432,25,2,9); //设置时钟,216Mhzdelay_init(216); //延时初始化uart_init(115200); //串口初始化 LED_Init(); //初始化 LED KEY_Init(); //初始化按键 SDRAM_Init();//初始化 SDRAM LCD_Init(); //LCD 初始化POINT_COLOR=RED;LCD_ShowString(30,50,200,16,16,"Apollo STM32F4/F7");LCD_ShowString(30,70,200,16,16,"RNG TEST");LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");LCD_ShowString(30,110,200,16,16,"2016/7/12"); while(RNG_Init()) //初始化随机数发生器{LCD_ShowString(30,130,200,16,16," RNG Error! ");delay_ms(200);LCD_ShowString(30,130,200,16,16,"RNG Trying...");}……//此处省略部分液晶显示代码 while(1) { delay_ms(10);key=KEY_Scan(0);if(key==KEY0_PRES){random=RNG_Get_RandomNum(); //获得随机数LCD_ShowNum(30+8*11,180,random,10,16); //显示随机数}if((t%20)==0){LED0_Toggle; //每 200ms,翻转一次 LED0random=RNG_Get_RandomRange(0,9);//获取[0,9]区间的随机数LCD_ShowNum(30+8*16,210,random,1,16); //显示随机数}delay_ms(10);t++;}}该部分代码也比较简单,在所有外设初始化成功后,进入死循环,等待按键按下,如果 KEY0 按下,则调用 RNG_Get_RandomNum 函数,读取随机数值,并将读到的随机数显示在 LCD 上 面。每隔 200ms 获取一次区间[0,9]的随机数,并实时显示在液晶上。同时 DS0,周期性闪烁, 400ms 闪烁一次。这就实现了前面我们所说的功能。 至此,本实验的软件设计就完成了,接下来就让我们来检验一下,我们的程序是否正确了。 24.4 下载验证 将程序下载到水星 STM32F767 后,可以看到 DS0 不停的闪烁,提示程序已经在运行了。 然后我们按下 KEY0,就可以在屏幕上看到获取到的随机数。同时,就算不按 KEY0,程序也 会自动的获取 0~9 区间的随机数显示在 LCD 上面。实验结果如图 24.4.1 所示: 图 24.4.1 获取随机数成功 |
|
相关推荐
|
|
hal库中i2c卡死在HAL_I2C_Master_Transmit
981 浏览 1 评论
LL库F030进行3个串口收发,2个串口为232,一个为485,长时间后,会出现串口1停止运行,另外两个正常,只有重启复原
1464 浏览 1 评论
524 浏览 0 评论
1057 浏览 0 评论
1199 浏览 1 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-5 05:33 , Processed in 0.491983 second(s), Total 38, Slave 31 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号