第三十一章 ESP32S3 RNG 实验
本章将学习 ESP32-S3 的硬件随机数发生器。使用 BOOT 按键来获取硬件随机数,并且将获取到的随机数值显示在 LCD 上面。同时,使用 LED 指示程序运行状态。
本章分为如下几个小节:
31.1 随机数发生器简介
31.2 硬件设计
31.3 程序设计
31.4 下载验证
31.1 随机数发生器简介
ESP32-S3 内置的硬件随机数发生器(RNG)是一个基于物理过程生成真随机数的模块,它利用芯片内部固有的噪声源(如热噪声和时钟抖动)来产生不可预测的随机数,非常适合用于加密、安全认证和各类需要高随机性的应用场景。
RNG 工作原理与特性:
- 噪声源:主要依赖两种物理熵源:
模数转换器 (ADC) 热噪声:当 SARADC 或高速 ADC 工作时,其内部晶体管的热噪声会产生微小的电压波动,经采样后形成随机比特流。
RC_FAST_CLK 时钟抖动:对内部 20MHz RC 快速时钟进行采样,利用其固有的频率漂移和抖动(电路亚稳态)作为随机性来源。
这些熵源产生的比特流通过异或 (XOR) 等逻辑混合后,存入 RNG_DATA_REG寄存器供读取。
- 输出数据:每次读取会返回一个 32 位的无符号随机数 (uint32_t)。
- 性能与质量:生成的随机数在其范围内分布均匀。为确保熵值最大,建议在使用 RNG 时至少使能一路 ADC 作为种子源。
真随机数发生器(TRNG) VS 伪随机数发生器 (PRNG):
|
特性维度 |
真随机数发生器 (TRNG) |
伪随机数发生器 (PRNG) |
|---|---|---|
|
随机性来源 |
物理现象(热噪声、量子效应等) |
确定性算法(数学公式) |
|
可预测性 |
完全不可预测,即使知道所有生成细节也无法推测结果 |
可预测,知道算法和种子即可重现整个序列 |
|
周期性 |
无周期,理论上永不重复 |
有周期,序列长度取决于算法和种子长度 |
|
速度 |
相对较慢,受物理过程限制 |
非常快,依赖算法计算速度 |
|
主要应用 |
高安全场景:加密密钥生成、数字签名、安全令牌 |
一般随机需求:模拟仿真、游戏、随机抽样 |
|
硬件依赖 |
通常需要专用硬件或利用物理熵源 |
纯软件即可实现 |
表31.1.1 真随机数发生器(TRNG) 和 伪随机数发生器 (PRNG)比较
31.1.1 RNG 功能描述
下面先来了解噪声源,EDP32- S3 的随机数发生器噪声源如图 31.1.1.1 所示:

图 31.1.1.1 ESP32-S3 随机数发生器噪声源
系统可以从随机数发生器的寄存器 RNG_DATA_REG 中读取随机数,每个读到的 32 位随机数都是真随机数,噪声源为系统中的热噪声和异步时钟。具体来说,这些热噪声可以来自SARADC或高速 ADC或两者兼有。当芯片的 SARADC 或高速 ADC工作时,就会产生比特流,并 通 过 异 或(XOR)逻辑运算作为随机数种子进入随机数生成器 。当为数字内核使能RC_FAST_CLK 时钟时,随机数发生器也会对 RC_FAST_CLK(20MHz)进行采样,作为随机数种子。RC_FAST_CLK 是一种异步时钟源,由于存在电路亚稳态,因此可以提高随机数发生器的墒值。然而,为了保证随机数发生器可以获得最大熵值,仍建议在使用随机数发生器时至少使能一路 ADC 作为随机数种子。
31.1.2 RNG 随机数寄存器
RND 随机数寄存器描述如下所示:
| 名称 | 描述 | 地址 | 访问 |
|---|---|---|---|
| RNG_DATA_REG | 随机数数据 | 0x0110 | 只读 |
表 31.1.2.1 RNG 寄存器列表

图 31.1.2.1 RNG_CR 寄存器
需要注意:这里的地址都是相对于随机数发生器基地址的地址偏移量。
31.2 硬件设计
31.2.1 例程功能
本实验使用 ESP32-S3 自带的硬件随机数生成器(RNG),获取随机数,并显示在 LCD 屏幕上。按 BOOT 按键可以获取一次随机数。同时程序自动获取 0~9 范围内的随机数,显示在屏幕上。 LED 闪烁用于提示程序正在运行。
31.2.2 硬件资源
1. LED
LED - IO1
2.独立按键
BOOT - IO0
3. XL9555
IIC_SDA-IO41
IIC_SCL-IO42
4. SPILCD
CS-IO21
SCK-IO12
SDA-IO11
DC-IO40(在 P5 端口,使用跳线帽将 IO_SET 和 LCD_DC 相连)
PWR- IO1_3(XL9555)
RST- IO1_2(XL9555)
5. RNG(硬件随机数生成器)
31.2.3 原理图
RNG 属于 ESP32-S3 内部资源,通过软件设置。本实验通过配合按键获取随机数和通过 LCD 显示。
31.3 程序设计
31.3.1 程序流程图
本实验的程序流程图:

图 31.3.1.1 随机数实验程序流程图
31.3.2 RNG 函数解析
ESP-IDF 提供了一套 API 来配置 RNG。要使用此功能,需要导入必要的头文件:
#include "esp_random.h"
接下来介绍一些常用的 ESP32-S3 中的 RNG 函数,这些函数的描述及其作用如下:
(1)得到随机数
该函数用于获取一个 32 位的硬件随机数,其函数原型如下:
uint32_t esp_random(void);
该函数的无形参。
该函数的返回值描述,如下表所示:
| 返回值 | 描述 |
|---|---|
| result ^ REG_READ(WDEV_RND_REG) | 0 和 UINT32_MAX 之间的随机值 |
表 31.3.2.1 函数 esp_random ()返回值描述
31.3.3 RNG 驱动解析
在 IDF 版 21_rng 例程中,在 21_rng\components\BSP 路径下新增了一个 RNG 文件夹,分别用于存放 rng.c、 rng.h 这两个文件。其中, rng.h 文件负责声明 RNG 相关的函数和变量,而rng.c 文件则实现了 RNG 的驱动代码。
(1)rng.h 文件
uint32_t rng_get_random_num(void); /* 得到随机数 */
int rng_get_random_range(int min, int max); /* 得到某个范围内的随机数 */
(2)rng.c 文件
/**
* @brief 得到随机数
* @param 无
* @retval 获取到的随机数(32bit)
*/
uint32_t rng_get_random_num(void)
{
uint32_t randomnum;
randomnum = esp_random();
return randomnum;
}
/**
* @brief 得到某个范围内的随机数
* @param min,max: 最小,最大值.
* @retval 得到的随机数(rval),满足:min<=rval<=max
*/
int rng_get_random_range(int min, int max)
{
uint32_t randomnum;
randomnum = esp_random();
return randomnum % (max - min + 1) + min;
}
31.3.4 CMakeLists.txt 文件
打开本实验 BSP 下的 CMakeLists.txt 文件,其内容如下所示:
set(src_dirs
IIC
KEY
LCD
LED
RNG
SPI
XL9555)
set(include_dirs
IIC
KEY
LCD
LED
RNG
SPI
XL9555)
set(requires
driver)
idf_component_register(SRC_DIRS ${src_dirs} INCLUDE_DIRS ${include_dirs} REQUIRES ${requires})
component_compile_options(-ffast-math -O3 -Wno-error=format=-Wno-format)
31.3.5 实验应用代码
打开 main/main.c 文件,该文件定义了工程入口函数,名为 app_main。该函数代码如下。
i2c_obj_t i2c0_master;
/**
* @brief 程序入口
* @param 无
* @retval 无
*/
void app_main(void)
{
uint8_t key;
uint32_t random;
uint8_t t = 0;
esp_err_t ret;
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());
ret = nvs_flash_init();
}
led_init(); /* 初始化LED */
i2c0_master = iic_init(I2C_NUM_0); /* 初始化IIC0 */
spi2_init(); /* 初始化SPI2 */
xl9555_init(i2c0_master); /* 初始化XL9555 */
lcd_init(); /* 初始化LCD */
key_init(); /* 初始化按键 */
lcd_show_string(30, 50, 200, 16, 16, "ESP32", 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, "RNG Ready! ", RED);
lcd_show_string(30, 130, 200, 16, 16, "BOOT:Get Random Num", RED);
lcd_show_string(30, 150, 200, 16, 16, "Random Num:", RED);
lcd_show_string(30, 180, 200, 16, 16, "Random Num[0-9]:", RED);
while(1)
{
key = key_scan(0);
if (key == BOOT) /* 获取随机数并显示至LCD */
{
random = rng_get_random_num();
lcd_show_num(30 + 8 * 11, 150, random, 10, 16, BLUE);
}
if ((t % 20) == 0) /* 获取0~9间的随机数并显示至LCD */
{
LED_TOGGLE(); /* 每200ms,翻转一次LED */
random = rng_get_random_range(0, 9); /* 取[0,9]区间的随机数 */
lcd_show_num(30 + 8 * 16, 180, random, 1, 16, BLUE); /* 显示随机数 */
}
vTaskDelay(10);
t++;
}
}
31.4 下载验证
将程序下载到开发板后,可以看到 LED 不停的闪烁,提示程序已经在运行了。然后按下 BOOT,就可以在屏幕上看到获取到的随机数。同时,就算不按 BOOT,程序也会自动的获取 0~9 区间的随机数显示在 LCD 上面。实验结果如图 31.4.1 所示:

图 31.4.1 获取随机数成功
更多推荐


所有评论(0)