14. 硬件随机数

一、随机数发生器简介

  ESP32 S3 内置一个真随机数发生器(RNG),其生成的 32 位随机数可作为加密等操作的基础。ESP32-S3 的随机数发生器可通过物理过程而非算法生成真随机数,所有生成的随机数在特定范围内出现的概率完全一致。

  系统可以从随机数发生器的寄存器 RNG_DATA_REG 中读取随机数,每个读到的 32 位随机数都是真随机数,噪声源为系统中的热噪声和异步时钟。具体来说,这些热噪声可以来自 SARADC 或高速 ADC 或两者兼有。当芯片的 SARADC 或高速 ADC 工作时,就会产生比特流,并通过异或(XOR)逻辑运算作为随机数种子进入随机数生成器。

  当为数字内核使能 RC_FAST_CLK 时钟时,随机数发生器也会对 RC_FAST_CLK(20MHz)进行采样,作为随机数种子。RC_FAST_CLK 是一种异步时钟源,由于存在电路亚稳态,因此可以提高随机数发生器的墒值。然而,为了保证随机数发生器可以获得最大熵值,仍建议在使用随机数发生器时至少使能一路 ADC 作为随机数种子。

随机数发生器噪声源

二、硬件随机数常用函数

  ESP-IDF 提供了一套 API 来配置高精度定时器。要使用此功能,需要导入必要的头文件:

#include "esp_timer.h"

  我们可以使用 esp_random() 函数 获取随机数,它的函数原型如下:

/**
 * @brief 获取0到UINT32_MAX之间的随机值
 * 
 * @return uint32_t 获取的随机数
 */
uint32_t esp_random(void);

三、实验例程

  这里,我们在【components】文件夹下的【peripheral】文件夹下的【inc】文件夹(用来存放头文件)新建一个 bsp_rng.h 文件,在【components】文件夹下的【peripheral】文件夹下的【src】文件夹(用来存放源文件)新建一个 bsp_rng.c 文件。

#ifndef __BSP_RNG_H__
#define __BSP_RNG_H__

#include "esp_random.h"

uint32_t bsp_rng_get_random_number(void);
uint32_t bsp_rng_get_random_number_in_range(uint32_t min, uint32_t max);

#endif // !__BSP_RNG_H__
#include "bsp_rng.h"

/**
 * @brief 获取0到UINT32_MAX之间的随机值
 * 
 * @return uint32_t 获取的随机数
 */
uint32_t bsp_rng_get_random_number(void)
{
    uint32_t random_number = esp_random();
    return random_number;
}

/**
 * @brief 获取min到max之间的随机值
 * 
 * @param min 最小值
 * @param max 最大值
 * @return uint32_t 获取的随机数
 */
uint32_t bsp_rng_get_random_number_in_range(uint32_t min, uint32_t max)
{
    uint32_t random_number = bsp_rng_get_random_number();
    random_number = random_number % (max - min + 1) + min;
    return random_number;
}

  修改【main】文件夹下的 main.c 文件。

#include <stdio.h>

#include "freertos/FreeRTOS.h"

#include "bsp_rng.h"

// app_main()函数是ESP32的入口函数,它是FreRTOS的一个任务,任务优先级是1
// main()函数是C语言入口函数,它会在编译过程中插入到二进制文件中的
void app_main(void)
{
    while (1)
    {
        uint32_t random_number = bsp_rng_get_random_number_in_range(0, 30);
        printf("random_number = %ld\n", random_number);

        // 将一个任务延迟给定的滴答数,IDF中提供pdMS_TO_TICKS可以将指定的ms转换为对应的tick数
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}
posted @ 2025-03-24 22:26  星光映梦  阅读(58)  评论(0)    收藏  举报