Среда программирования Arduino IDE позволяет в программу на языке C++ вставлять фрагменты кода на языке AVR Assemler.
Эта статья для начинающих программировать в среде Ардуино. Здесь мы приведём программу Blink из стандартных примеров Arduino IDE и перепишем её на языке AVR Assembler в среде Arduino IDE.
На многих Ардуино совместимых платах, в том числе и на плате Arduino UNO или Arduino NANO, присутствует светодиод, который можно использовать для тестирования работоспособности платы.
Скетч использует 932 байт (2%) памяти устройства. Всего доступно 32256 байт. Глобальные переменные используют 9 байт (0%) динамической памяти, оставляя 2039 байт для локальных переменных. Максимум: 2048 байт.
Пример 1. Программа мигающая светодиодом на плате Arduino UNO или Arduino NANO.
В программе из примера 1 есть ключевое слово, несколько функций (команд) и несколько констант.
Слово | Единица | Описание |
---|---|---|
void | ключевое слово | Определяет тип следующего за ним объекта как не возвращающий значения |
setup() | функция | Обязательно должна присутствовать в Ардуино программе. |
loop() | функция | Обязательно должна присутствовать в Ардуино программе. Организует бесконечный цикл. |
pinMode() | функция | Настраивает функционирование определённой ножки (pin) микроконтроллера. |
digitalWrite() | функция | Включает определённый логический уровень на ножке (pin), если эта ножка настроена как выход. |
delay() | функция | Останавливает выполнение программы на заданное время |
LED_BUILTIN | константа | Значение для Arduino UNO 13 |
OUTPUT | константа | true или 1 |
LOW | константа | false или 0 |
HIGH | константа | true или 1 |
Рассмотрим часть принципиальной электрической схемы платы Arduino.
Рис. 1. Светодиод на плате Ардуино подключён к выводу D13.
На рис. 1 мы видим, что порт PB5 микроконтроллера ATMega328 соединён с выводом D13 платы Ардуино. Когда на выводе D13 установлен логический 0, светодиод LD1 не горит. Когда - логическая 1 (~4,5 Вольт), ток идёт из микроконтроллера вывод D13 платы Ардуино через резистор R1, светодиод LD1 на общий провод с потенциалом 0 Вольт. Светодиод горит.
В программе из примера 1 в функции setup() функция pinMode(LED_BUILTIN, OUTPUT) настраивает вывод D13 платы Ардуино как выход. LED_BUILTIN=13.
В функции loop() функция digitalWrite(LED_BUILTIN, LOW) устанавливает на выводе D13 логический 0. Светодиод LD1 не горит. Функция digitalWrite(LED_BUILTIN, HIGH) устанавливает на выводе D13 логическую 1. Светодиод LD1 горит.
Микроконтроллер ATMega328 установленный на плате Ардуино работает очень быстро. Он выполняет 1 ассемблерную команду за 1 такт тактового генератора. Тактовая частота микроконтроллера ATMega328 на плате Ардуино 16 МГц. Значит период 1 такта 0,0000000625 сек (1/16000000). Именно за это время выполняется каждая ассемблерная команда. Если с такой скоростью переключать светодиод мы мерцаний не заметим. Поэтому в программе пример 1 добавлены функции delay(), которые выполняют задержку. После включения светодиода задержка выполнения программы 450 миллисекунд., а после включения 50 миллисекунд.
Подытожим в функции loop(), в цикле, то есть непрерывно повторяясь, светодиод LD1 выключен 450 миллисекунд и включается на 50 миллисекунд.
Перепишем программу из примера 1 учитывая значения констант и тот факт, что электрические сигналы на ножках микроконтроллера ATMega328 зависят от значений записанных в 8-ми битные управляющие регистры микроконтроллера. Уровень сигнала на порту PB5 зависит от состояния 5-го бита в регистре PORTB, а настройка порта PB5 как вход или выход зависит от состояния 5-го бита в регистре DDRB.
Скетч использует 654 байт (2%) памяти устройства. Всего доступно 32256 байт. Глобальные переменные используют 9 байт (0%) динамической памяти, оставляя 2039 байт для локальных переменных. Максимум: 2048 байт.
Пример 2. Программа мигающая светодиодом на плате Arduino UNO или Arduino NANO.
Программы из примера 1 и примера 2 не тождественны, но работают одинаково.
Заменим в программе из примера 2 операторы присваивания (=) ассемблерными вставками.
Скетч использует 654 байт (2%) памяти устройства. Всего доступно 32256 байт. Глобальные переменные используют 9 байт (0%) динамической памяти, оставляя 2039 байт для локальных переменных. Максимум: 2048 байт.
Пример 3. Программа мигающая светодиодом на плате Arduino UNO или Arduino NANO с ассемблерными вставками.
В примере 3 вы видите 3 ассемблерные вставки. Все они практически одинаковые и состоят из 2 строк кода на AVR Assembler. команда LDI загружает в регистр общего назначения восьми-битное число. Команда OUT копирует значение из регистра общего назначения (РОН) в регистр (РВВ). К сожалению, указать в команде OUT имя регистра ввода вывода DDRB или PORTB в среде разработки Arduino нельзя. Мы взяли адреса этих регистров в памяти микроконтроллера из файла m328Pdef.inc. Файл m328Pdef.inc приведён в конце статьи.
Как видите, ассемблерные вставки в скетче Ардуино не являются удобным инструментом. Мне кажется более удобно хранить программу в 2-х файлах, отдельно Си-код и отдельно код на Ассемблере. Причем, если файл с программой на Ассемблере имеет расширение "S", и хранится в той же папке что и файл с программой на Си с расширением ino, то оба файла при компиляции объединяются в одну программу автоматически. Arduino IDE открывает оба файла на редактирование.
Файл с расширением "S".
Файл с расширением "ino".
Скетч использует 672 байт (2%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 9 байт (0%) динамической памяти, оставляя 2039 байт для локальных переменных. Максимум: 2048 байт.
Пример 4. Программа мигающая светодиодом на плате Arduino UNO или Arduino NANO с функциями на ассемблере.
В программе из примера 4 на ассемблере написано 3 функции, а в коде на C++ эти функции подключаются как внешние (extern) и затем используются самым обычным образом.
Перепишем программу из примера 4 с передачей параметра.
Файл с расширением "S".
Файл с расширением "ino".
Скетч использует 662 байт (2%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 9 байт (0%) динамической памяти, оставляя 2039 байт для локальных переменных. Максимум: 2048 байт.
Пример 5. Программа мигающая светодиодом на плате Arduino UNO или Arduino NANO с функцией на ассемблере.
Файл m328Pdef.inc