GD32L233C TRNG 处理和PWM配置
[复制链接]
题主原来用ESP32-C3 开发了一款IOT智能LED灯,这这次为了用GD32L233C替换ESP32 需要把ESP32 的代码移植到GD32L233C上,需要用到随机数用来产生真随机数
根据随机数生成绚丽多变的灯光,PWM则用负责用来控制RGBW四个LED灯的亮度和实现灯光渐变灯灯效。下面就开始来用GD32L233C的TRNG产生随机数。
看一下SPEC上是这样描述TRNG的
3.9. True Random number generator (TRNG)
About 40 periods of TRNG_CLK are needed between two consecutive random numbers.
两个连续的随机数需要大约40个 TRNG_CLK 时钟
Disable TRNG module will reduce the chip power consumption.
禁止TRNG 模块可以减低芯片功耗,(看来鱼和熊掌不可兼得)
32-bit random value seed is generated from analog noise, so the random number is a true random number.
The true random number generator (TRNG) module can generate a 32-bit random value by using continuous analog noise.
32位的随机数值种子产生来之模拟噪音,所以这个随机数是真随机数,这个TRNG 模块可以产生32为随机值依靠连续不断的模拟噪音
下面就是如何初始化TRNG模块:兆易创新很贴心,直接在下载包里面提供了实例程序,我们需要的只是在巨人的肩膀上修改一下就可以了。
这也是这几年嵌入式系统发张的大方向,厂家提供SDK和demo示例,大大减低了arm的开发难度,妈妈再也不用担心我天天在家看规格书了。
/*!
\brief configure TRNG module
\param[in] none
\param[out] none
\retval ErrStatus: SUCCESS or ERROR
*/
ErrStatus trng_configuration(void)
{
ErrStatus reval = SUCCESS;
/* TRNG module clock enable */
rcu_periph_clock_enable(RCU_TRNG);//shineng TRNG 时钟
/* TRNG registers reset */
trng_disable();//复位TRNG
trng_enable();//使能 TRNG
/* check TRNG work status */
reval = trng_ready_check();//检查trng准备状态
return reval;
}
/*!
\brief check whether the TRNG module is ready
\param[in] none
\param[out] none
\retval ErrStatus: SUCCESS or ERROR
*/
ErrStatus trng_ready_check(void)
{
uint32_t timeout = 0;
FlagStatus trng_flag = RESET;
ErrStatus reval = SUCCESS;
/* check wherther the random data is valid */
do {
timeout++;
trng_flag = trng_flag_get(TRNG_FLAG_DRDY);
} while((RESET == trng_flag) && (0xFFFF > timeout));
if(RESET == trng_flag) {
/* ready check timeout */
// printf("Error: TRNG can't ready \r\n");
trng_flag = trng_flag_get(TRNG_FLAG_CECS);
// printf("Clock error current status: %d \r\n", trng_flag);
trng_flag = trng_flag_get(TRNG_FLAG_SECS);
// printf("Seed error current status: %d \r\n", trng_flag);
reval = ERROR;
}
/* return check status */
return reval;
}
void rand_setup(void)
{
uint8_t retry = 0;
/* configure TRNG module */
while((ERROR == trng_configuration()) && retry < 3) {
//printf("TRNG init fail \r\n");
//printf("TRNG init retry \r\n");
retry++;
}
//printf("TRNG init ok \r\n");
}
以上就是trng初始化过程
uint32_t randoms(void)
{
uint32_t random_data = 0, random_lastdata = 0;
/* get the first random data */
random_lastdata = trng_get_true_random_data();
if(SUCCESS == trng_ready_check()) {
random_data = trng_get_true_random_data();
if(random_data != random_lastdata) {
random_lastdata = random_data;
// printf("Get random data: 0x%08x \r\n", random_data);
} else {
/* the random data is invalid */
// printf("Error: Get the random data is same \r\n");
}
}
return random_data;
}
获取随机数函数
在封装一个根据自己需要的随机函数,可以指定生成的随机数范围
/*!
\brief 生成指定随机数范围
\param[in] uint32_t min 最小随机数 uint32_t max 最大随机数
\param[out] none
\retval 返回随机数
*/
uint32_t Xrandom(uint32_t min, uint32_t max)
{
uint32_t rand_data =0;
rand_data =randoms();
rand_data =rand_data % (max - min + 1);
return rand_data+min;
}
改造好后编译然后固件烧写到芯片上发现随机随生成失败,重新找到GD 提供的demo代码发现demo代码上面选择的时钟是内部晶振48M ,我最初配置的晶振是64M的,
尝试把晶振改为48M
/* turn on the oscillator */
rcu_osci_on(RCU_IRC48M);
if(ERROR == rcu_osci_stab_wait(RCU_IRC48M)) {
while(1) {
}
}
重新编译下载,发现随机数已经可以正常生成,其中有一个要注意的是每次生成的随机数是否和上次一样如果一样要重新生成,加上延时
随机数在IOT LED灯里面主要三个应用一个是密钥认证的、二是灯光变幻随机步骤,三是随机生成不同颜色的灯光
如下所示
step =Xrandom(0, 5);
rand_rgb=Xrandom(0, 16777215) ;
未完待续
|