目录
一、实验介绍
简单来说,随机数就是一个数列,这个数列可能满足一定的概率分布,也许其满足的分布并不为我们所知。
随机数发生器有如下功能:
- 产生伪随机字节,可以被 CPU 读取,或由命令选通处理器直接使用。
- 计算写入到 RNDH 的 CRC16 字节。
- 由写入到 RNDL 的值播种。
二、实验目的
- 通过本实验了解CC2530 的随机数发生器配置;
- 通过本实验了解CC2530的随机数发生器功能的运用。
三、实验设备
3.1、硬件设备
- ZIGBEE开发板
- SmartRF04EB仿真器
- Micro-USB线
3.2、软件环境
- IAR Embedded Workbench for 8051集成开发环境
- 串口调试助手
四、实验原理
4.1、随机发生器
随机发生器是一个16位的LFSR(线性反馈移位寄存器),带有多项式(即CRC16)。根据执行的操作,它使用不同级别的展开值。

当ADCCON1.RCTRL位置11时,关闭随机发生器。
4.2、随机发生器的运行
随机发生器的运行由ADCCON1.RCTRL控制,LFSR的16位移位寄存器的当前值可以从RNDH和RNDL寄存器中读取。
4.2.1、伪随机序列的生成
ADCCON1.RCTRL置00为默认操作,是命令选通处理器每次读取随机值就会通知一次LFSR。将ADCCON1.RCTRL置01也可以更新LFSR,将每次通知LFSR,当操作完成时该位自动清除。
4.2.2、种子值的产生
计算机使用随机算法计算前需要给算法一个初始值,即种子值,算法通过对该值的运算获取随机数。
LFSR可以通过两次写入RNDL寄存器产生种子值,每次写入,LFSR的低8位复制到高8位,低8位替换为新写入的数据。
当需要一个真正的随机值,LFSR 应通过写入 RNDL 产生种子,随机值来自在 RF 接收路径的 IF_ADC。要使用这种产生种子的方法,无线电必须首先上电。无线电应处于无限 TX 状态,以避免 RX 状态可能的同步检测。来自 IF_ADC 的随机值从 RF 寄存器 RFRND 中读出。读出的值作为种子值写入 RNDL 寄存器,如上所述,注意这可以在为正常任务使用无线电时完成。
种子值为0x0000或0x8003将会导致LFSR中的值通知之后不会改变,因此不能产生随机数。
4.2.3、CRC16
计算一个字节序列的CRC(循环冗余校验)值可以用LFSR,写入RNDH寄存器将触发一个CRC计算。
在计算CRC计算前,LFSR必须通过写入RNDL产生一个随机数,产生用于CRC计算的种子数通常为0x0000或0xFFFF。
4.3、相关寄存器
RNDL和RNDH寄存器存放的是随机值或CRC值的结果,读取随机数时,RNDH的低8位为随机数的高8位,RNDL的低8位为随机数的低8位。

五、实验演示
现在演示的是,给定一个种子值,生成随机数并在串口显示。
首先创建rnd.c和rnd.h文件,在rnd.c文件内初始化也就是给定一个种子值,对应存入RNDH和RNDL寄存器,生成对应的随机数:
#include "headfile.h"
void rnd_init(uint16_t seed)
{
RNDH = seed >>8; //将种子值的高8位写入RNDH
RNDL = seed; //将种子值写入RNDL
}
uint16_t getrandomnum(void)
{
ADCCON1 |= 0x04; //0000 0100 使能随机发生器
uint16_t rand;
rand = RNDH; //将RNDH的数据写入rand的高8位
rand <<= 8;
rand |= RNDL; //将RNDL的数据写入rand的低8位
return rand;
}
在main.c内调用这两个函数生成随机数,取这个数的低3位,并在串口显示该值,记得要切换时钟源为32MHz:
#include "iocc2530.h"
#include "headfile.h"
char buf[20];
void main(void)
{
clk32m_init();
uart0_init();
rnd_init(0x2000); //给定种子值为0x2000
//注意种子值不可为0x0000和0x8003
uint16_t rand = getrandomnum(); //获取随机数
buf[2] = (rand)%10 + '0'; //获取个位数
buf[1] = (rand/10)%10 + '0'; //获取十位数
buf[0] = (rand/100)%10 + '0'; //获取百位数
//将整数转换为对应的字符型,只需加上'0'
uartsendstring(buf,3);
uartsendstring("\r\n",2);
while(1);
}
打开串口助手,观察现象:

接下来利用无线电随机生成种子数:
void rnd_init(void)
{
RFRND = 0x04; //无线电上电
while(RFRND & 0x10); //等待上电完毕
RFST = 0xE2; //让无线电处于无限TX状态
ADCCON1 &= ~0x0C; //正常运行发生器
RNDH = ADCTEST2;
ADCCON1 |= 0x04; //使能随机发生器
}
每次按下按键1使能外部中断,生成一个随机数,对随机数的个位数进行对3取余并实现以下功能:
余数为0时LED1亮,LED2灭,LED3灭;
余数为1时LED1灭,LED2亮,LED3灭;
余数为2时LED1灭,LED2灭,LED3亮。
外部中断配置参考实验“4-CC2530 外部中断配置”。
通过以下程序实现:
#include "iocc2530.h"
#include "headfile.h"
char buf[20];
uint16_t rand;
void main(void)
{
clk32m_init();
uart0_init();
rnd_init();
key_init();
led_init();
while(1)
{
switch((rand%10)%3) //对随机数的个位数进行3取余
{
case 0:led_proc(1,1);led_proc(2,0);led_proc(3,0);break;
case 1:led_proc(1,0);led_proc(2,1);led_proc(3,0);break;
case 2:led_proc(1,0);led_proc(2,0);led_proc(3,1);break;
default:break;
}
}
}
#pragma vector = P0INT_VECTOR
__interrupt void P0_int(void)
{
if(P0IFG & 0x01)
{
uint8_t state=0;
delayms(10);
rand = getrandomnum(); //获取随机数
state++;
while(KEY1 == 0);
delayms(10);
if(state)
{
buf[2] = (rand)%10 + '0'; //获取个位数
buf[1] = (rand/10)%10 + '0'; //获取十位数
buf[0] = (rand/100)%10 + '0'; //获取百位数
uartsendstring(buf,3);
uartsendstring("\r\n",2);
}
}
P0IFG = 0;
P0IF = 0;
}
有疑问可以加入QQ群交流:324611467
4923

被折叠的 条评论
为什么被折叠?



