Это старая версия документа!
Иногда в программе для микроконтроллера требуется создавать случайные числа. Возьмем пример из книги Мартина Райзера и Никлауса Вирта Программирование на Обероне. С него начинается введение в программирование на Обероне со страницы 9. Также этот пример входит в комплект примеров системы Блэкбокс (модуль ObxRandom).
Немного адаптируем его под последний диалект Оберона, который мы используем для микроконтроллеров, а именно — сделаем явное преобразование типов между REAL и INTEGER с помощью встроенных в язык процедур FLT и FLOOR.
FLT преобразует переменную типа INTEGER в переменную типа REAL
FLOOR округляет REAL до меньшего целочисленного значения INTEGER
MODULE Random; VAR z: INTEGER; (* global variable *) PROCEDURE Uniform* (): REAL; CONST a = 16807; m = 2147483647; q = m DIV a; r = m MOD a; VAR gamma: INTEGER; BEGIN gamma := a * (z MOD q) - r * (z DIV q); IF gamma > 0 THEN z := gamma ELSE z := gamma + m END; RETURN FLT(z) * (1.0 / FLT(m)) (* value of the function *) END Uniform; PROCEDURE InitSeed* (seed: INTEGER); BEGIN z := seed END InitSeed; BEGIN z := 314159 (* initial value of seed *) END Random.
Теперь попробуем применить этот модуль, напишем небольшую программу для микроконтроллера STM32F401CC.
В этой программе модуль Random используется, чтобы установить задержку до переключения состояния светодиода.
MODULE Main;
IMPORT SYSTEM,
ARMv7M := MicroARMv7M,
SysTick0 := MobxARMv7MSTM32SysTick0,
MCU := MicroSTM32F4,
Pins := MicroSTM32F4Pins,
Sys := MicroSTM32F4System,
Rnd := Random;
VAR
delay: INTEGER; ledOn: BOOLEAN;
PROCEDURE Setup;
BEGIN
delay := 0;
SysTick0.Init(Sys.HCLK, 1000);
Pins.Configure(Pins.C, 13, Pins.output,
Pins.pushPull, Pins.medium, Pins.noPull, Pins.AF0);
SYSTEM.PUT(MCU.GPIOCBSRR, {13 + 16});
ledOn := FALSE;
(* тут может быть инициализация от какого-то источника случайных чисел *)
(* Rnd.InitSeed(someIntSource); *)
delay := FLOOR(Rnd.Uniform() * 1000.0);
END Setup;
PROCEDURE Loop;
BEGIN
REPEAT
IF SysTick0.OnTimer() THEN
IF delay <= 0 THEN
IF ledOn THEN
SYSTEM.PUT(MCU.GPIOCBSRR, {13})
ELSE
SYSTEM.PUT(MCU.GPIOCBSRR, {13 + 16})
END;
ledOn := ~ledOn;
delay := FLOOR(Rnd.Uniform() * 1000.0);
ELSE
DEC(delay)
END;
END;
ARMv7M.WFI
UNTIL FALSE
END Loop;
BEGIN
Setup;
Loop
END Main.
Получаем результат.
https://vkvideo.ru/video-198725476_456239054
Последовательность не будет повторяться, если инициализировать генератор от некоторого другого источника. Например, встроенный датчик температуры. Но это уже будет другая статья. Спасибо за чтение. Задавайте вопросы в группе или в телеграм канале: https://t.me/recordinoChat
Успехов!
<iframe src=«https://vkvideo.ru/video_ext.php?oid=-198725476&id=456239054&hash=» width=«640» height=«360» frameborder=«0» allowfullscreen=«1» style=«background-color: #000» allow=«autoplay; encrypted-media; fullscreen; picture-in-picture»></iframe>