![](https://habrastorage.org/files/e30/adf/a5d/e30adfa5d3b4484abffa9d167f1f8c3d.jpg)
Доброго времени суток! Решил рассказать о простом и интересном способе получения честных случайных чисел на микроконтроллерах, не имеющих на борту аппаратного генератора случайных чисел. Достаточно, чтобы у микроконтроллера был АЦП и один свободный вход. Подробности под катом.
Идея не нова и много кому приходила в голову. Я её реализовал в одном из своих старых проектов на 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) + (result & 0x01); ADC_CSR = 4; //Сбрасываем флаг окончания преобразования } return result; }
Вот такая небольшая хитрость. Код восстанавливал по памяти, так что могут быть ошибки — о них прошу написать в ЛС.
Буду очень рад мнению опытных людей о таком способе получения случайных чисел.
ссылка на оригинал статьи http://habrahabr.ru/post/259623/
Добавить комментарий