硬件随机数发生器实验

STM32F4随机数发生器
①STM32F4自带了硬件随机数发生器(RNG),RNG处理器是一个以连续模拟噪声为基础的随机数发生器,在主机读数时提供一个32位的随机数。
②两个连续的随机数的间隔为40个PLL48CLK时钟信号周期。
③通过监控RNG熵来标识异常行为。
④可以禁止来降低功耗。
随机数发生器框图
①STM32F4的随机数发生器(RNG)采用模拟电路实现。此电路产生馈入线性反馈移位寄存器 (RNG_LFSR) 的种子,用于生成 32 位随机数。
②该模拟电路由几个环形振荡器组成,振荡器的输出进行异或运算以产生种子。RNG_LFSR 由专用时钟 (PLL48CLK) 按恒定频率提供时钟信息,因此随机数质量与 HCLK 频率无关。当将大量种子引入RNG_LFSR后,RNG_LFSR 的内容会传入数据寄存器 (RNG_DR)。
③同时,系统会监视模拟种子和专用时钟 PLL48CLK,当种子上出现异常序列,或PLL48CLK时钟频率过低时,可以由RNG_SR寄存器的对应位读取到,如果设置了中断,则在检测到错误时,还可以产生中断。

STM32F4 随机数发生器(RNG)的几个寄存器 

RNG 控制寄存器:RNG_CR

 该寄存器只有 bit2 和 bit3 有效,用于使能随机数发生器和中断。我们一般不用中断,所以 只需要设置 bit2 为 1,使能随机数发生器即可。

RNG 状态寄存器:RNG_SR

该寄存器我们仅关心最低位(DRDY 位),该位用于表示 RNG_DR 寄存器包含的随机数数 据是否有效,如果该位为 1,则说明 RNG_DR 的数据是有效的,可以读取出来了。读 RNG_DR 后,该位自动清零。 

RNG 数据寄存器:RNG_DR

在 RNG_SR 的 DRDY 位置位后,我们就可以读取该寄存器获得 32 位随机数值。此寄存器 在最多 40 个 PLL48CK 时钟周期后,又可以提供新的随机数值。

随机数发生器操作步骤:

1)使能随机数发生器时钟。

要使用随机数发生器,必须先使能其时钟。随机数发生器时钟来自 PLL48CK,通过 AHB2ENR 寄存器使能。 所以我们调用使能 AHB2 总线外设时钟的函数使能 RNG 时钟即可:

RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_RNG, ENABLE);//开启 RNG 时钟

2)使能随机数发生器。

这个就是通过 RNG_CR 寄存器的最低位设置为 1,使能随机数发生器。如果需要用 到中断,可以使能 RNG 中断。库函数中使能随机数发生器的方法为:

RNG_Cmd(ENABLE); //使能 RNG

3)判断 DRDY 位,读取随机数值。

每次读取之前,必须先判断 RNG_SR 寄存器的 DRDY 位,如果该位为 1,则可以读取 RNG_DR 得到随机数值,如果不为 1,则需要等待。 在库函数中,获取随机数发生器状态的函数为:

FlagStatus RNG_GetFlagStatus(uint8_t RNG_FLAG);

库函数中,判断数据是否有效的入口参数为 RNG_FLAG_DRDY,所以等待就绪的方法为:

while(RNG_GetFlagStatus(RNG_FLAG_DRDY)==RESET);

判断数据有效后,然后我们读取随机数发生器产生的随机数即可,调用函数为:

uint32_t RNG_GetRandomNumber(void);

RNG库函数

void RNG_DeInit(void);//复位

void RNG_Cmd(FunctionalState NewState);//使能RNG

uint32_t RNG_GetRandomNumber(void);//获取随机数

void RNG_ITConfig(FunctionalState NewState);

FlagStatus RNG_GetFlagStatus(uint8_t RNG_FLAG);

void RNG_ClearFlag(uint8_t RNG_FLAG);

ITStatus RNG_GetITStatus(uint8_t RNG_IT);

void RNG_ClearITPendingBit(uint8_t RNG_IT);

RNG初始化以及获得随机数函数

//初始化RNG
u8 RNG_Init(void)
{
	u16 retry=0; 
	
  RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_RNG, ENABLE);//开启RNG时钟,来自PLL48CLK
	
	RNG_Cmd(ENABLE);	//使能RNG
	
	while(RNG_GetFlagStatus(RNG_FLAG_DRDY)==RESET&&retry<10000)	//等待随机数就绪
	{
		retry++;
		delay_us(100);
	}
	if(retry>=10000)return 1;//随机数产生器工作不正常
	return 0;
}
//得到随机数
//返回值:获取到的随机数
u32 RNG_Get_RandomNum(void)
{	 
	while(RNG_GetFlagStatus(RNG_FLAG_DRDY)==RESET);	//等待随机数就绪  
	return RNG_GetRandomNumber();	
}

//生成[min,max]范围的随机数
int RNG_Get_RandomRange(int min,int max)
{ 
   return RNG_Get_RandomNum()%(max-min+1) +min;
}

main函数

int main(void)
{ 
	u32 random;
	u8 key;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
	delay_init(168);  //初始化延时函数
	uart_init(115200);		//初始化串口波特率为115200
	LED_Init();					//初始化LED
	KEY_Init();					//按键初始化
	delay_ms(10000);
	LED0=!LED0;
	while(RNG_Init())	 		//初始化随机数发生器
	{
		printf("RNG Error!\r\n ");	 
		delay_ms(200);
		printf("RNG Trying...\r\n");	 
	}                                 
	printf("RNG Ready!\r\n   ");	 
	printf("KEY0:Get Random Num\r\n");	 	 	
  printf("KEY1:Get Random Num[0,9]\r\n");
	while(1) 
	{		
		delay_ms(10);
		key=KEY_Scan(0);
		if(key==KEY0_PRES)
		{
			random=RNG_Get_RandomNum(); //获得随机数
			printf("Random Num:%d\r\n",random); //显示随机数

		}
		delay_ms(10);
		key=KEY_Scan(0);
		if(key== KEY1_PRES)
		{
			random=RNG_Get_RandomRange(0,9);//获取[0,9]区间的随机数
			printf("Random Num[0,9]:%d\r\n",random); //显示随机数
		}			
		//if((t%20)==0)
			//LED0=!LED0;	//每200ms,翻转一次LED0 
		//t++;
	}	
}

运行视频

随机数发生器实验

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值