Подведем некоторый итог: мы уже узнали многое о структуре типовой программы для AVR. Она должна начинаться с безусловного перехода на метку RESET, а само начало этой программы будет располагаться сразу после этой метки где-то в другом месте программы. А почему так странно? Нельзя ли начать прямо сразу с нулевого адреса, строка за строкой, зачем нужны какие-то переходы? Можно, отвечают нам авторы описаний AVR. Простейшая программа может начинаться с нулевого адреса без переходов, но только в одном случае: если мы обязываемся отказаться от прерываний. А без них контроллер теряет 90 % своей функциональности. Конечно, можно придумать пример программы, которая бы делала что-нибудь полезное, но при этом работала совсем без прерываний. Но на практике без прерываний обходятся только тогда, когда штатных прерываний хватает (например, для отслеживания состояния большого количества кнопок), или когда без них программа получается компактнее (такие случаи мы еще встретим).
Обработка прерываний
AVR по умолчанию ожидает, что сразу после первой команды с адресом $0000 идет таблица т. н.
Порядок векторов и их количество в таблице жестко задано в соответствии с типом МК. Потому самое первое, что вы должны сделать, приступая к программированию, — открыть руководство по применению выбранного типа контроллеров и скопировать оттуда эту таблицу. Можно попытаться сделать это прямо через буфер обмена из PDF-описания или преобразовав его в другой формат, так меньше вероятность что-то пропустить, только придется потом удалить указанные там абсолютные адреса, стоящие в начале каждой строки. Вот как будет выглядеть заготовка начала программы для МК ATmega8 (листинг 13.1).
;=======прерывания=======
rjmp RESET ;Reset Handler
rjmp EXT_INT0 ;IRQ0 Handler
rjmp EXT_INT1 ;IRQ1 Handler
rjmp TIM2_COMP ;Timer2 Compare Handler
rjmp TIM2_OVF ;Timer2 Overflow Handler
rjmp TIM1_CAPT ;Timer1 Capture Handler
rjmp TIM1_COMPA ;Timer 1 CompareA Handler
rjmp TIM1_COMPB ;Timer1 CompareB Handler
rjmp TIM1_OVF ;Timer1 Overflow Handler
rjmp TIM0_OVF ;Timer0 Overflow Handler
rjmp SPI_STC ;SPI Transfer Complete Handler
rjmp USART_RXC ;USART RX Complete Handler
rjmp USART_UDRE ;UDR Empty Handler
rjmp USART_TXC ;USART TX Complete Handler
rjmp ADC ;ADC Conversion Complete Handler
rjmp EE_RDY ;EEPROM Ready Handler
rjmp ANA_COMP ;Analog Comparator Handler
rjmp TWSI ;Two-wire Serial Interface Handler
rjmp SPM_RDY ;Store Program Memory Ready Handler
;========================
Обратите внимание, что в ассемблерной программе каждый оператор занимает отдельную строку (в большинстве языков высокого уровня операторы можно записывать в одной строке, например, разделяя их знаками препинания; здесь это не допускается). Символы пробелов и табуляции могут встречаться в произвольном количестве, и они полностью игнорируются, за исключением двух случаев: нельзя разбивать идентификатор на части и, наоборот, нельзя соединять разные идентификаторы между собой; хотя бы один пробел, знак табуляции (или знак препинания, если это предусмотрено форматом команды) между наименованиями инструкций, переменных, регистров и т. п. должен быть.