《DNESP32P4开发指南_V1.0》第二十六章 RNG实验
第二十六章 RNG实验
本章将介绍ESP32-P4的硬件随机数发生器。我们使用BOOT按键来获取硬件随机数,并且将获取到的随机数值显示在LCD上。同时,LED0用来指示程序运行状态。
本章分为如下几个小节:
26.1 RNG介绍
26.2 硬件设计
26.3 程序设计
26.4 下载验证
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相关功能函数,必须先导入以下头文件:
#include "esp_random.h"
接下来,作者将介绍一些常用的函数,这些函数的描述及其作用如下:
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,他们的功能是不一样的,代码如下:
/**
* @brief 得到随机数
* @param 无
* @retval 获取到的随机数(32bit)
*/
uint32_t rng_get_random_num(void)
{
return esp_random();
}
/**
* @brief 得到某个范围内的随机数
* @param min,max: 最小,最大值.
* @retval 得到的随机数(rval),满足:min<=rval<=max
*/
int rng_get_random_range(int min, int max)
{
return esp_random() % (max - min + 1) + min;
}
上述两个函数都是调用esp_random函数实现功能的。rng_get_random_num函数用于读取一个32位随机数,而rng_get_random_range函数用于读取一个特定范围内的随机数。
2. CMakeLists.txt文件
本例程的功能实现主要依靠RNG驱动。要在main函数中,成功调用RNG文件中的内容,就得需要修改BSP文件夹下的CMakeLists.txt文件,修改如下:
set(src_dirs
LED
KEY
LCD
RNG)
set(include_dirs
LED
KEY
LCD
RNG)
set(requires
driver
esp_lcd
esp_common)
idf_component_register( SRC_DIRS ${src_dirs} INCLUDE_DIRS ${include_dirs} REQUIRES ${requires})
component_compile_options(-ffast-math -O3 -Wno-error=format=-Wno-format)
3. main.c驱动代码
在main.c里面编写如下代码。
void app_main(void)
{
esp_err_t ret;
uint8_t key = 0;
uint32_t random = 0;
uint8_t t = 0;
ret = nvs_flash_init(); /* 初始化NVS */
if(ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
{
ESP_ERROR_CHECK(nvs_flash_erase());
ESP_ERROR_CHECK(nvs_flash_init());
}
led_init(); /* LED初始化 */
key_init(); /* KEY初始化 */
lcd_init(); /* LCD屏初始化 */
lcd_show_string(30, 50, 200, 16, 16, "ESP32-P4", RED);
lcd_show_string(30, 70, 200, 16, 16, "RNG TEST", RED);
lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);
lcd_show_string(30, 110, 200, 16, 16, "BOOT:Get Random Num", RED);
lcd_show_string(30, 130, 200, 16, 16, "Random Num:", RED);
lcd_show_string(30, 150, 200, 16, 16, "Random Num[0-9]:", RED);
while(1)
{
key = key_scan(0);
if (key == BOOT_PRES)
{
random = rng_get_random_num(); /* 获取随机数 */
lcd_show_num(118, 130, random, 10, 16, BLUE);
ESP_LOGI("test", "data:%ld ", random);
}
if ((t % 20) == 0)
{
random = rng_get_random_range(0, 9); /* 取[0,9]区间的随机数 */
lcd_show_num(158, 150, random, 1, 16, BLUE);
LED0_TOGGLE();
}
vTaskDelay(pdMS_TO_TICKS(10));
t++;
}
}
在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实验程序运行效果图

浙公网安备 33010602011771号