По своей сути макрос является обыкновенным шаблоном для подстановки исходного кода. Применение макросов оправданно в тех случаях, когда в программе часто встречается похожие последовательности команд, но при этом имеющие различные параметры.
Каждый макрос нужно предварительно объявить в разделе описания переменных. Объявление макроса имеет вид типа:
.macro {имя макроса} . текст для подстановки . .endmacro или .endm
В дальнейшем макрос можно будет использовать неограниченное число раз, простой подстановкой его имени в текст программы. За именем макроса через запятую могут последовать несколько параметров (до 10). В самом теле макроса ссылка на параметры производится через символ “@”, после которого идет порядковый номер (@0…@9). Так, например, может выглядеть макрос, реализующий вычитание содержимого регистровой пары с 16-разрядным числом
.macro add16 ;объявление макроса add16 subi @1,low(-@2) ;вычитаем из регистровой пары @0:@1 16-разрядное sbci @0,high(-@2) ;число @2 в дополнительном коде .endm
На месте употребления в программе макроса
.
add16 XH,XL,0x1234 ;вычитание XH:XL с 16-разрядным числом 0x1234
.
будет сгенерирован следующий код подстановки:
subi R26,0xCC ;XH:XL = XH:XL - 0xEDCC sbci R27,0xED
В макросах часто применяются директивы условной компиляции, такие как .else, elif, .endif и т.д., а также .message, .warning и .error. С их помощью можно производить подстановку различных фрагментов кода в зависимости от начальных значений входных параметров, а также выявлять ошибки, выдавать сообщения и предупреждения в ходе компиляции программы. На листинге ниже показан макрос pulse_low, формирующий на одном из выводов импульс низкого уровня.
.macro pulse_low ;объявление макроса pulse_low .if @0 == 0x18 ;если параметр @0 порта C, то выводим сообщение .message "Порт C содержит только 7 линий ввода-вывода." .elif @1 == 7 ;если параметр @1 линия 7, то выводим ошибку .error "Линия 7 порта C отсутствует в модели ATmega8!" .endif .if @2 > 65535 ;если параметр @2 больше 2 б, то выводим предупреждение .warning "Слишком большая задержка времени!" .endif cbi @0,@1 ;устанавливаем лог.0 на линии @1 порта @0 ldi R24,low(@2);заносим в счетчик циклов R25:R24 значение @2 ldi R25,high(@2) loop: sbiw R24,1 ;производим цикл вычитания brne loop sbi @0,@1 ;устанавливаем лог.1 на линии @1 порта @0 .endm ̣̣̣̣̣̣̣̣ pulse_low PORTB,PB0,10000 ;импульс на линии 0 порта B около 40000 циклов .
Макрос принимает 3 значения: адрес регистра данных порта (PORTB, PORTC или PORTD), номер линии ввода-вывода (0…7) и двухбайтовую константу, определяющую длительность задержки (0…65535). В нутрии макроса производится проверка адреса порта. Если в качестве порта был задан PORTC (адрес регистра PORTС = 0x18), то будет выдано сообщение о том, что в модели ATmega8 этот порт содержит только 7 линий ввода-вывода. И если, кроме этого, будет выбрана линия 7 (произойдет попытка обратиться к несуществующему биту) – из-за ошибки сборка проекта будет приостановлена. Дополнительную проверку на переполнение проходит, и параметр задержки времени. В случае если его значение превышает 0xFFFF, будет выдано предупреждение.
Все метки в теле макроса, как, например, метка loop в макросе pulse_low, являются локальными. Область их видимости ограничена директивами .macro и .endm. В ассемблере AVR допускается использование макросов в макросе (до 8 уровней вложения).
Перейти к следующей части: Создание и отладка программ
Комментарии (1) | Я собрал (0) | Подписаться
Для добавления Вашей сборки необходима регистрация