在一些防碰撞系统中,比如加密系统、无线通讯中的碰撞,我们都需要用到随机数。但是C语言标准库中的随机数函数rand(),生成是伪随机数。
一、rand()函数原理
a1 = f(seed), an = f(an-1), 其中: seed 为种子,f为产生随机序列的映射方法。
由以上可以产生随机数的方法可知,当seed种子一样时,产生的随机序列就是一样的。要产生真正的随机数,最核心的就是要产生真正随机的种子。
二、产生随机种子的方法
在一个系统中,如果没有硬件随机数生成器,就需要我们根据系统的特点,自己设计方法,产生随机数的种子。嵌入式系统中常用到的随机数生成方法有:
1,利用定时器,包括系统时钟、RTC等
通过在系统初始化时,读取定时器的ticks,来产生随机数,是无法产生真正的随机数的,国为指令周期是固定的,初始化相同位置的代码,也具有相同的时钟周期,这时获取到的tick值,也是固定的,所以这种方法是不可行的。但是如果RTC时钟已经校正过,这个时候获取的tcks值每次均是不一样的,这可以获取随机数。
2,利用外部交互的不确定性
对于一个与外部有交互的系统中,由于外部的触发是随机的,通过这种外部交互触发时,读取时钟值,产生的随机数是真随机数。常用到的交互包括: 外部DI第一次触发时、有按键接下时、第一次通讯某指令时等。
3,利用上电后,RAM区域中,未初始化的部分数据的随机性,获取随机数
这个需要认真阅读MCU的datasheet,看未初始化的RAM中随机的,还是为0或者1。同时当代码功能变化较大时,RAM的分配产生变化时,还需要重新定位指针,以保证指针指向的是随机区域。
4,利用AD
在我们使用AD时,我们会发现,获取到的AD值,并不是固定的,总会有几个数字的飘移,我们一般需要滤波才能获取比较稳定的AD值。当我们的AD是接入悬空引脚时,AD的漂移会更大,这种漂移就是随机的。我们可以用如下办法获取到随机数,比如我们想获取一个2字节的随机数:
for(i = 0; i < 16; i ++){ ad_val = ADC_GetVal(ch); rand_bit |= (ad_val & 0x01) << i; Delay_Ms(10); }
我们每次读取AD值,只用它最低位的1bit,因为这个bit,一般都是漂移的。通过多次获取这个bit,从而获取我们需要的随机数。
5,组合的办法
在一个多机的联合系统中,产生随机数,可能对于这个设备来说,产生的随机数是真随机数,但如果这个系统中,其它相同的设备,因为也采用一样的随机数生成方法(比如定时器、外部触发),这就会造成一个系统中,两个相同设备,可能产生相同的随机数的可能性。这就需要利每个设备的唯一性,来产生随机数,比如芯片ID(每个芯片有唯一的ID),将芯片ID、随机数生成方法组合起来,这样产生的随机数,就是系统级的随机数。
我们在生成随机数时,还是要根据设备、多机系统、应用场景、目的的不同,设计不同的产生随机数的方法,以保障它真正的随机性。
还没有评论,来说两句吧...