超级版主
 
- 积分
- 5292
- 金钱
- 5292
- 注册时间
- 2019-5-8
- 在线时间
- 1353 小时
|
|
第二十六章 RNG实验
1)实验平台:正点原子DNESP32P4开发板
2)章节摘自【正点原子】ESP32-P4开发指南— V1.0
3)购买链接:https://detail.tmall.com/item.htm?id=873309579825
4)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/esp32/ATK-DNESP32P4.html
5)正点原子官方B站:https://space.bilibili.com/394620890
6)正点原子DNESP32S3开发板技术交流群:132780729
26.1 RNG介绍
随机数发生器(Random Number Generators),用于生成随机数的程序或软件。
随机数的特性:产生的后面那个数与前面那个数毫无关系。
随机数又分为真随机数和伪随机数。真随机数:完全随机,毫无规律;伪随机数:用确定性算法计算出的随机数序列,并非真随机。
ESP32-P4内置一个真随机数发生器,其生成的32位随机数可作为加密等操作的基础。
ESP32-P4的随机数发生器可通过物理过程而非算法生成真随机数,所有生成的随机数在特定范围内出现的概率完全一致。
接下来,介绍一下随机数生成的过程,如下图所示。
图26.1.1 随机数生成过程
随机数的源,在这里称为噪声源。噪声源为系统中的热噪声和异步时钟。使用随机数生成器时,至少启用其一,否则,生成的是伪随机数。热噪声可以来自SAR ADC。当芯片SAR ADC工作时,就会产生比特流,并通过异或(XOR)逻辑运算作为随机数种子进入随机数生成器。RC_FAST_CLK是一种异步时钟源,它通过引入电路亚稳态来增加RNG熵。
当有噪声来自SAR ADC时,随机数发生器在一个RC_FAST_CLK时钟周期中被输入1位熵,这是由内部RC振荡器产生的。读取LPSYSREG_RNG_DATA_REG寄存器时可用最大速率1MHz异或以获得最大熵。
26.2 硬件设计
26.2.1 例程功能
使用ESP32-P4的硬件随机数发生器来生成随机数,并显示在LCD屏幕上。按下BOOT可以获取一次随机数。同时程序会自动获取0~9范围内的随机数,显示在LCD屏上。LED0闪烁用于提示程序正在运行。
26.2.2 硬件资源
1)LED灯
LED 0 - IO51
2)KEY按键
BOOT - IO35
3)RGBLCD / MIPILCD(引脚太多,不罗列出来)
26.2.3 原理图
RNG属于ESP32-P4的片上资源,因此没有对应的连接原理图。
26.3 程序设计
26.3.1 RNG的IDF驱动
使用RNG相关功能函数,必须先导入以下头文件:
接下来,作者将介绍一些常用的函数,这些函数的描述及其作用如下:
1,得到随机数函数esp_random
该函数用于从系统中获取时间,其函数原型如下:
- uint32_t esp_random(void);
复制代码 无函数形参
函数返回值:
返回的是0~uint32_max之间的随机数。
26.3.2 程序流程图
图26.3.2.1 RNG实验程序流程图
26.3.3 程序解析
在17_rng例程中,作者在17_rng\components\BSP路径下新增了1个文件夹RNG,并且需要更改CMakeLists.txt内容,以便在其他文件上调用。
1. RNG驱动代码
这里我们只讲解核心代码,详细的源码请大家参考光盘本实验对应源码。RNG驱动源码包括两个文件:rng.c和rng.h。
rng.h用于声明rng_get_random_num等函数,以便在其他文件中调用,具体内容不再赘述。
下面我们再解析rng.c的程序,主要就是两个获取随机数的函数rng_get_random_num和rng_get_random_range,他们的功能是不一样的,代码如下:
- <font size="3">/**</font>
- <font size="3"> * @brief 得到随机数</font>
- <font size="3"> * [url=home.php?mod=space&uid=271674]@param[/url] 无</font>
- <font size="3"> * @retval 获取到的随机数(32bit)</font>
- <font size="3"> */</font>
- <font size="3">uint32_t rng_get_random_num(void)</font>
- <font size="3">{</font>
- <font size="3"> return esp_random();</font>
- <font size="3">}</font>
- <font size="3">/**</font>
- <font size="3"> * @brief 得到某个范围内的随机数</font>
- <font size="3"> * @param min,max: 最小,最大值.</font>
- <font size="3"> * @retval 得到的随机数(rval),满足:min<=rval<=max</font>
- <font size="3"> */</font>
- <font size="3">int rng_get_random_range(int min, int max)</font>
- <font size="3">{ </font>
- <font size="3"> return esp_random() % (max - min + 1) + min;</font>
- <font size="3">}</font>
复制代码 上述两个函数都是调用esp_random函数实现功能的。rng_get_random_num函数用于读取一个32位随机数,而rng_get_random_range函数用于读取一个特定范围内的随机数。
2. CMakeLists.txt文件
本例程的功能实现主要依靠RNG驱动。要在main函数中,成功调用RNG文件中的内容,就得需要修改BSP文件夹下的CMakeLists.txt文件,修改如下:
- <font size="3">set(src_dirs</font>
- <font size="3"> LED</font>
- <font size="3"> KEY</font>
- <font size="3"> LCD</font>
- <font size="3"> RNG)</font>
- <font size="3">set(include_dirs</font>
- <font size="3"> LED</font>
- <font size="3"> KEY</font>
- <font size="3"> LCD</font>
- <font size="3"> RNG)</font>
- <font size="3">set(requires</font>
- <font size="3"> driver</font>
- <font size="3"> esp_lcd</font>
- <font size="3"> esp_common)</font>
- <font size="3">idf_component_register( SRC_DIRS ${src_dirs} INCLUDE_DIRS ${include_dirs} REQUIRES ${requires})</font>
- <font size="3">component_compile_options(-ffast-math -O3 -Wno-error=format=-Wno-format)</font>
复制代码 3. main.c驱动代码
在main.c里面编写如下代码。
- <font size="3">void app_main(void)</font>
- <font size="3">{</font>
- <font size="3"> esp_err_t ret;</font>
- <font size="3"> uint8_t key = 0;</font>
- <font size="3"> uint32_t random = 0;</font>
- <font size="3"> uint8_t t = 0;</font>
- <font size="3"> ret = nvs_flash_init(); /* 初始化NVS */</font>
- <font size="3"> if(ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND)</font>
- <font size="3"> {</font>
- <font size="3"> ESP_ERROR_CHECK(nvs_flash_erase());</font>
- <font size="3"> ESP_ERROR_CHECK(nvs_flash_init());</font>
- <font size="3"> }</font>
- <font size="3"> led_init(); /* LED初始化 */</font>
- <font size="3"> key_init(); /* KEY初始化 */</font>
- <font size="3"> lcd_init(); /* LCD屏初始化 */</font>
- <font size="3"> lcd_show_string(30, 50, 200, 16, 16, "ESP32-P4", RED);</font>
- <font size="3"> lcd_show_string(30, 70, 200, 16, 16, "RNG TEST", RED);</font>
- <font size="3"> lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);</font>
- <font size="3"> lcd_show_string(30, 110, 200, 16, 16, "BOOT:Get Random Num", RED);</font>
- <font size="3"> lcd_show_string(30, 130, 200, 16, 16, "Random Num:", RED);</font>
- <font size="3"> lcd_show_string(30, 150, 200, 16, 16, "Random Num[0-9]:", RED);</font>
- <font size="3"> while(1)</font>
- <font size="3"> {</font>
- <font size="3"> key = key_scan(0);</font>
- <font size="3"> if (key == BOOT_PRES) </font>
- <font size="3"> {</font>
- <font size="3"> random = rng_get_random_num(); /* 获取随机数 */</font>
- <font size="3"> lcd_show_num(118, 130, random, 10, 16, BLUE);</font>
- <font size="3"> ESP_LOGI("test", "data:%ld ", random);</font>
- <font size="3"> }</font>
- <font size="3"> if ((t % 20) == 0) </font>
- <font size="3"> { </font>
- <font size="3"> random = rng_get_random_range(0, 9); /* 取[0,9]区间的随机数 */</font>
- <font size="3"> lcd_show_num(158, 150, random, 1, 16, BLUE);</font>
- <font size="3"> LED0_TOGGLE(); </font>
- <font size="3"> }</font>
- <font size="3"> vTaskDelay(pdMS_TO_TICKS(10));</font>
- <font size="3"> t++;</font>
- <font size="3"> }</font>
- <font size="3">}</font>
复制代码 在app_main函数中,完成所需外设初始化以后,进入到死循环,等待按键按下,如果BOOT按键按下,则调用rng_get_random_num函数,读取随机数值,并将读到的随机数显示在LCD上面。每隔200ms调用rng_get_random_range函数获取一次区间[0,9]的随机数,并实时显示在LCD上。LED0闪烁,以提示程序正在运行。
26.4 下载验证
将程序下载到开发板后,可以看到LED0不停闪烁,提示程序已经在运行了。然后我们按下BOOT按键,就可以在LCD上看到获取到的随机数。同时,就算不按BOOT按键,程序也会自动的获取0~9区间的随机数显示在LCD上。实验效果如图26.4.1所示。
图26.4.1 RNG实验程序运行效果图 |
|