| Предыдущая версия справа и слева
Предыдущая версия
Следующая версия
|
Предыдущая версия
|
ob:o7:first [2026/04/24 16:29] iadenisov |
ob:o7:first [2026/04/24 16:44] (текущий) саша |
| ====== Первая программа на языке программирования Оберон ====== | ====== Первая программа на языке программирования Оберон ====== |
| |
| В [[https://vk.com/@mcuoberon-recordino-flash-stm32|предыдущей заметке]] было описано, как создать новый проект в среде разработки Рекордино, компилировать модуль-заготовку и затем — сформировать файл прошивки и записать его в память микроконтроллера. | В [[ob:o7:recordino-flash-stm32|предыдущей заметке]] было описано, как создать новый проект в среде разработки Рекордино, компилировать модуль-заготовку и затем — сформировать файл прошивки и записать его в память микроконтроллера. |
| |
| Теперь разберём детально сам код этого небольшого модуля, чтобы лучше понять идеологию модульного подхода и особенности [[https://online.oberon.org/oberon|языка программирования Оберон]]. | Теперь разберём детально сам код этого небольшого модуля, чтобы лучше понять идеологию модульного подхода и особенности [[https://online.oberon.org/oberon|языка программирования Оберон]]. |
| Программа прошивки состоит из модулей, как из кирпичиков Лего. | Программа прошивки состоит из модулей, как из кирпичиков Лего. |
| |
| **Модуль** всегда начинается с слова ''MODULE'', после которого следует его название. И заканчивается словом //**END**//, после которого повторяется название, и завершается точкой. | **Модуль** всегда начинается с слова ''MODULE'', после которого следует его название. И заканчивается словом ''END'', после которого повторяется название, и завершается точкой. |
| |
| <code> | <code> |
| В общем случае название модуля может быть любым, название главного модуля редактируется в настройках проекта. Именно для главного модуля будет создаваться прошивка при нажатии на кнопку сборки на панели меню. | В общем случае название модуля может быть любым, название главного модуля редактируется в настройках проекта. Именно для главного модуля будет создаваться прошивка при нажатии на кнопку сборки на панели меню. |
| |
| Секция импорта начинается ключевым словом //**IMPORT**//, после которого через запятую идут названия других модулей — строительных блоков программы. При этом с помощью оператора присваивания //**:=**// для модулей допускается указывать короткие обозначения. | Секция импорта начинается ключевым словом ''IMPORT'', после которого через запятую идут названия других модулей — строительных блоков программы. При этом с помощью оператора присваивания '':='' для модулей допускается указывать короткие обозначения. |
| |
| <code> | <code> |
| </code> | </code> |
| |
| После секции импорта возможно указывать константы и описывать новые типы данных. Однако в этой простой программе это не используются, поэтому за секцией импорта следует секция глобальных переменных //**VAR**//. После идентификатора (имени) переменной через двоеточие указывается тип данных, который будет хранить переменная. | После секции импорта возможно указывать константы и описывать новые типы данных. Однако в этой простой программе это не используются, поэтому за секцией импорта следует секция глобальных переменных ''VAR''. После идентификатора (имени) переменной через двоеточие указывается тип данных, который будет хранить переменная. |
| |
| <code> | <code> |
| После описания переменных идёт описание процедур и программный код модуля. В этом примере две процедуры: | После описания переменных идёт описание процедур и программный код модуля. В этом примере две процедуры: |
| |
| //**Setup**// — отвечает за настройку микроконтроллера, | ''Setup'' — отвечает за настройку микроконтроллера, |
| |
| //**Loop**// — содержит главную петлю программы, которая повторяется во время работы микроконтроллера после настройки. | ''Loop'' — содержит главную петлю программы, которая повторяется во время работы микроконтроллера после настройки. |
| |
| <code> | <code> |
| </code> | </code> |
| |
| Процедура настройки //**Setup**// имеет три выражения: | Процедура настройки ''Setup'' имеет три выражения: |
| |
| - установка начального значения глобальной переменной; | - установка начального значения глобальной переменной; |
| - настройка частоты таймера делается вызовом процедуры //*Init*// из модуля //**SysTick0**//. Процедура имеет два аргумента, мы передаём ей частоту работы главного кварца микроконтроллера и желаемую частоту вызова таймера в Герцах (так таймер будет вызываться 1000 раз в секунду); | - настройка частоты таймера делается вызовом процедуры ''Init'' из модуля ''SysTick0''. Процедура имеет два аргумента, мы передаём ей частоту работы главного кварца микроконтроллера и желаемую частоту вызова таймера в Герцах (так таймер будет вызываться 1000 раз в секунду); |
| - настройка вывода **PC13** осуществляется с помощью специального модуля //**Pins**// через процедуру //**Configure**//, 6 параметров задают порт, номер вывода, тип вывода (вход/выход), наличие/отсутствие подтяжки, скорость работы, тип подтяжки, и вариант альтернативной функции для вывода. (если ножка будет работать в режиме **GPIO**, то нужно использовать значение //**Pins.AF0**//). | - настройка вывода **PC13** осуществляется с помощью специального модуля ''Pins'' через процедуру ''Configure'', 6 параметров задают порт, номер вывода, тип вывода (вход/выход), наличие/отсутствие подтяжки, скорость работы, тип подтяжки, и вариант альтернативной функции для вывода. (если ножка будет работать в режиме **GPIO**, то нужно использовать значение ''Pins.AF0''). |
| |
| <code> | <code> |
| </code> | </code> |
| |
| Процедура //**Loop**// содержит бесконечный цикл //**REPEAT UNTIL FALSE**//, в котором находится два выражения: | Процедура ''Loop'' содержит бесконечный цикл ''REPEAT UNTIL FALSE'', в котором находится два выражения: |
| |
| - условие проверки срабатывание таймера //**SysTick0.OnTimer()**// с кодом, который выполняется, если таймер сработал; | - условие проверки срабатывание таймера ''SysTick0.OnTimer()'' с кодом, который выполняется, если таймер сработал; |
| - команда которая отправляет микроконтроллер в спящий режим до срабатывания следующего вызова таймера или иного прерывания //**ARMv7M.WFI**// | - команда которая отправляет микроконтроллер в спящий режим до срабатывания следующего вызова таймера или иного прерывания ''ARMv7M.WFI'' |
| |
| <code> | <code> |
| </code> | </code> |
| |
| Внутри условия, есть выражение для добавления единицы к счётчику милисекунд //**INC(msec)**//, а также условия сброса счётчика в //**0**//, когда его значение достигнет константы //**999**//: | Внутри условия, есть выражение для добавления единицы к счётчику милисекунд ''INC(msec)'', а также условия сброса счётчика в ''0'', когда его значение достигнет константы ''999'': |
| |
| <code> | <code> |
| </code> | </code> |
| |
| Второе условное ветвление, в зависимости от значения глобальной переменной //**msec**// с помощью команды //**SYSTEM.PUT**// устанавливает значение битов регистра //**GPIOC_BSRR**// , так что сначала на вывод **PC13** подаётся напряжение 3,3 Вольта, а затем через половину секунды напряжение устанавливается в 0 Вольт. | Второе условное ветвление, в зависимости от значения глобальной переменной ''msec'' с помощью команды ''SYSTEM.PUT'' устанавливает значение битов регистра ''GPIOC_BSRR'' , так что сначала на вывод **PC13** подаётся напряжение 3,3 Вольта, а затем через половину секунды напряжение устанавливается в 0 Вольт. |
| |
| <code> | <code> |