如何有效地在微控制器中生成随机数?

时间:2009-10-13 05:21:21

标签: random microcontroller

如何有效地在微控制器中生成随机数?是否有任何一般指导方针或特定的快速方法?

8 个答案:

答案 0 :(得分:11)

一个通常生成伪随机数而不是实际随机数,尽管两者都可能以不同的速率生成。

有两种常规类别,具体取决于序列是否用于加密目的。主要区别在于序列中一个数字的知识是否允许预测下一个数字。通用RNG不担心算法的知识是否允许观察者复制序列,并且它们运行得更快。

典型的通用RNG算法是Mersenne Twister。各种算法有许多公共实现。 See here一个人。

如果MT需要太多内存,那么linear congruential generator就会产生一半中等回退。 (MT直到1997年才被发明。)这个生成器有一些问题,但它几乎不需要内存,几乎没有代码,而且速度非常快。实现无处不在,Knuth的 Seminumerical Algorithms 中详细介绍了它。

要为任何RNG播种,您需要一个熵源,请参阅http://en.wikipedia.org/wiki/Entropy_(computing)(注意:SO对该链接中的()的内容感到困惑。)这通常是由CPU可以定时事件派生的。观察,例如击键,(我猜这对你不起作用)中断和数据包到达。实时时钟通常是可接受的来源,如果它保持自己的状态,因为重新启动很少以任何顺序计时。

答案 1 :(得分:10)

您可以将种子存储到EEPROM中,当设备启动时,您可以递增种子并再次存储它。因此,每次重启都会有不同的随机数。

答案 2 :(得分:7)

您可以通过模拟线性反馈移位寄存器来操作位来生成伪随机数字

然后问题变成'你要模拟多少位?'

Wikipedia有一些信息。

答案 3 :(得分:4)

如果您可以访问ADC,那么您可以从中读取最低有效位,并将其用作伪随机数生成器的种子,就像其他人发布的那样。显然,您需要从ADC读取多个位,因此需要多次读取,这可能需要一段时间。但是,您只需要在启动时执行此操作一次,然后使用更快的PRNG生成新的随机数。

许多嵌入式设备都内置了无线ADC,例如Atmel的ATMega系列。

答案 4 :(得分:2)

如果硬件有一个用户按钮,一个简单的技巧就是计算按下按钮的时间。使用足够快的短计数器,您可以获得“随机”数字。

答案 5 :(得分:1)

伪随机数生成器是最快且要求最低的w.r.t.指令集(只有移位和xor,没有乘法或除法)是Mersenne twister想法的较小变体(称为广义线性反馈移位寄存器)。 Mersenne Twister本身对微控制器需要太多内存。

这些发生器的问题在于,如果你运气不好,它们可能会产生接近零的长序列。有了合理的状态空间大小和来自另一个PNRG的初始化,这是不可能的。

他们对加密或赌博也不安全,智能对手可以在观察输出后预测未来状态。这是因为它们是线性的。

我曾经为一个小型非标准处理器设计了这样一个发生器,其状态空间大约为50个24位字。我用Diehard测试套件测试了变体,直到找到一个好的变体。该应用程序为硬件测试生成随机变量。

答案 6 :(得分:0)

读取定时器和xoring / nanding / etc它会带一系列位给用户半随机,因为事件之间的时间间隔可能足以让用户真的无法告诉与计时器的相关性。

答案 7 :(得分:0)

如果您可以将引脚悬空,则可以使用线性反馈移位寄存器生成随机数。我不确定这是怎么回事,但请看看我的代码:

// This code was written for 8051 (AT89S52)
unsigned char lfsr = 231; //8 bit shift register, with the seed of 231 or '11100111b'
unsigned char input_bit, i;

void main (void) 
{
    //Setup
    P0_0 = 0; // Leave Pin 0 Port 0 floating
    uart_init(); //Initializing uart/serial communication with pc


    while (1) 
    {
        for (i = 0; i < 255; i++) 
        {
            if (P0_0 == 1) // If Pin 0.0 is HIGH
            {
                input_bit = ((lfsr >> 0) ^ (lfsr >> 2) ^ (lfsr >> 3) ^ (lfsr >> 4)) & 1;
                lfsr = (lfsr >> 1) | (input_bit << 7);
            }
        }
        printf_tiny("%u\n", lfsr); //Send the random number to PC
        soft_delay(65535); //Simple delay function
    } //end while (1) loop

}

编辑:我发现我的答案可能不好。有关为何不使用浮动数字引脚的更多细节:https://electronics.stackexchange.com/questions/50476/random-number-generators-using-a-gpio-pin

相关问题