Pull to refresh

АЦП в качестве генератора случайных чисел

Reading time 2 min
Views 37K

Доброго времени суток! Решил рассказать о простом и интересном способе получения честных случайных чисел на микроконтроллерах, не имеющих на борту аппаратного генератора случайных чисел. Достаточно, чтобы у микроконтроллера был АЦП и один свободный вход. Подробности под катом.

Идея не нова и много кому приходила в голову. Я её реализовал в одном из своих старых проектов на STM8S003F3, так что примеры кода будут к этому чипу, хотя перенести код на любую другую архитектуру не составит труда.

Суть заключается в том, что при измерении напряжения при помощи АЦП младшие биты результата наиболее подвержены шумам. Мы используем этот факт себе на пользу — будем делать несколько замеров, и записывать младший бит результата (как самый «шумный»). Таким образом сделав 8 измерений можно получить совсем случайный байт.

Ухудшим результаты измерения насколько это возможно. Установим наименьшее время выборки, а вывод микроконтроллера, на котором расположен вход АЦП, повесим «в воздухе», никуда не подтягивая и ни к чему не подключая. Чем больше шума — тем лучше.

Инициализация АЦП:
CLK_PCKENR2 |= 0x08; //Подаём тактирование на АЦП
ADC_CR1 = MASK_ADC_CR1_ADON; //Включение
ADC_CR2 = MASK_ADC_CR2_ALIGN;
ADC_CR3 = 0;
ADC_CSR = 4; //Выбор канала

Функция получения случайного байта:
unsigned char GetRandom(void) {
    unsigned char i, result;

    result = 0;
    for (i = 0; i < 8; i++) {
          ADC_CR1 = MASK_ADC_CR1_ADON; //Старт преобразования
          while (ADC_CSR == 4); //Ждём установки флага окончания преобразования
          result = (result << 1) + (ADC_DRL & 0x01);
          ADC_CSR = 4; //Сбрасываем флаг окончания преобразования
    }

    return result;
}

Вот такая небольшая хитрость. Код восстанавливал по памяти, так что могут быть ошибки — о них прошу написать в ЛС.

Буду очень рад мнению опытных людей о таком способе получения случайных чисел.
Tags:
Hubs:
+12
Comments 34
Comments Comments 34

Articles