Как эффективно генерировать случайные числа в микроконтроллере?

Как эффективно генерировать случайные числа в микроконтроллере? Есть ли общие рекомендации или конкретный быстрый метод?

8 ответов


вы можете создать псевдослучайных числа путем манипуляции битами путем имитации ЛИНЕЙНЫЙ РЕГИСТР СДВИГА ОБРАТНОЙ СВЯЗИ

тогда возникает вопрос: "сколько битов вы хотите смоделировать?'

Википедия есть какая-то информация.


обычно генерируются псевдослучайные числа, а не фактические случайные числа, хотя оба они возможны с разной скоростью.

существует две общие категории, в зависимости от того, будет ли последовательность использоваться в криптографических целях. Основное различие заключается в том, позволяет ли знание одного числа в последовательности предсказывать следующее. Общецелевые RNG не беспокоятся о том, позволит ли знание алгоритма наблюдателю дублировать последовательность, и они бежать немного быстрее.

типичным алгоритмом общего назначения RNG является Вихрь Мерсена. Существует множество публичных реализаций различных алгоритмов. посмотреть здесь для одного.

Если MT требует слишком много памяти, на полпути-приличный резерв-это линейный конгруэнтный генератор. (МТ был изобретен только в 1997 году.) У этого генератора есть определенные проблемы, но он не требует почти никакой памяти, почти никакого кода и очень быстр. Реализации повсюду, и это было подробно описано в Кнут Получисловые Алгоритмы.

чтобы засеять любой ГСЧ, вам понадобится источник энтропии, см. http://en.wikipedia.org/wiki/Entropy_ (вычисление) (Примечание: так что путается о () в этой ссылке.) Это обычно получается путем синхронизации событий, которые ЦП может наблюдать, таких как нажатия клавиш (я думаю, что это не сработает для вас) прерывания и прибытия пакетов. Часы реального времени часто допустимый источник, если он поддерживает свое собственное состояние, так как перезагрузки редко синхронизируются в какой-либо последовательности.


вы можете хранить семя в EEPROM, и когда устройство загружается, Вы можете увеличить семя и сохранить его снова. Таким образом, каждая перезагрузка будет иметь разное случайное число.


Если у вас есть доступ к АЦП, то вы можете прочитать наименее значимый бит из него и использовать его в качестве семени для генератора псевдослучайных чисел, как и другие опубликовали. Очевидно, вам нужно будет прочитать более одного бита из АЦП, поэтому требуется несколько чтений, что может занять некоторое время. Но вам нужно сделать это только один раз, при запуске, например, а затем использовать более быстрый PRNG для генерации новых случайных чисел.

многие встроенные устройства построили inn ADC, например ATMega семейная форма компании Atmel.


Если у оборудования есть кнопка для пользователя, простой трюк-подсчитать, как долго кнопка нажата. С достаточно быстрым коротким счетчиком вы получаете "случайное" число.


генераторы псевдослучайных чисел, которые являются самыми быстрыми и наименее требовательными w.r.т. набор команд (только shift и xor, без умножения или деления) - это меньшие варианты идеи Мерсенна твистера (так называемый обобщенный регистр сдвига линейной обратной связи). Сам Mersenne twister требует слишком много памяти для микроконтроллеров.

проблема с этими генераторами заключается в том, что они могут генерировать длинные последовательности около нуля, если вам не повезет. С разумным размером государственного пространства и инициализация от другой PNRG это, однако, маловероятно.

Они также не безопасны для криптографии или азартных игр, интеллектуальный противник может предсказать будущие состояния после наблюдения за выходом. Это потому, что они линейны.

Я когда-то разработал такой генератор для небольшого нестандартного процессора с пространством состояний около 50 24-битных слов. Я тестировал варианты с помощью набора тестов Diehard, пока не нашел хороший. Приложение генерировало случайные вариации для тестирования оборудования.


чтение таймера и xoring/nanding / etc он с серией битов даст полу случайный пользователю, так как время между событиями, вероятно, будет достаточно отдельно, что пользователь действительно не сможет сказать корреляцию с таймером.


Если вы можете оставить булавку плавающей, это может помочь генерировать случайные числа с линейный регистр сдвига обратной связи. Я не уверен, что это путь, но, пожалуйста, посмотрите на мой код:

// 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

}

EDIT: я узнал, что мой ответ может быть плохим. Подробнее о том, почему не следует использовать плавающий цифровой pin-код: https://electronics.stackexchange.com/questions/50476/random-number-generators-using-a-gpio-pin