Главная страница
Библиотека (скачать книги)
Скачать софт
Введение в программирование
Стандарты для C++
Уроки по C#
Уроки по Python
HTML
Веб-дизайн
Ассемблер в среде Windows
ActiveX
Javascript
Общее о Линукс
Линукс - подробно
Линукс - новое
Delphi
Паскаль для начинающих
Турбопаскаль
Новости
Партнеры
Наши предложения
Архив новостей





Обработка прерываний
AVR по умолчанию ожидает, что сразу после первой команды с адресом $0000 идет таблица т. н. векторов прерываний. Вектор — это просто отсылка по нужному адресу с помощью команды rjmp. Вообще-то вектор по нулевому адресу, на который программа переходит по сбросу (вектор сброса или вектор начальной загрузки), тоже считается прерыванием, хотя оно занимает особое место (вызывается только аппаратно, как рассказано в главе 2).

Адрес обозначается меткой, может располагаться в любом месте программы и содержит начало процедуры обработки прерывания. Первый вектор располагается по адресу $0001 (а для МК с памятью более 8 К— по адресу $0002, потому что по адресу $0001 находится вторая половина более длинной команды jmp), причем напомним, что для памяти программ адрес этот означает номер двухбайтового слова в памяти, а не отдельного байта. На самом деле по умолчанию нам вообще не нужно думать про абсолютные адреса и их нумерацию — первая команда программы (rjmp RESET) автоматически расположится по нулевому адресу, вторая— по адресу $0001 и т. д. Найдя какую-нибудь команду перехода по метке, компилятор автоматически подставит абсолютные адреса. Нужно только быть внимательным при выборе модели: если вы подставите для МК ATmega8 в таблицу прерываний jmp вместо rjmp (а для ATmegal6 и старше наоборот), то сброс у вас пройдет нормально, а вот все остальные прерывания выполняться не будут— скорее всего, программа просто "повиснет".

Порядок следования векторов и их число в таблице жестко заданы в соответствии с типом МК. Потому самое первое, что вы должны сделать, приступая к программированию, — открыть руководство по применению выбранного типа контроллеров и скопировать оттуда эту таблицу. Можно прямо через буфер обмена из PDF-описания (если вам позволят это сделать — в последних версиях описаний копирование текста через буфер обычно запрещено, что не делает чести менеджменту Atmel, но всегда можно вывернуться с помощью программ, удаляющих ограничения PDF, таких как Foxit Reader или платный Advanced PDF Password Recovery). Так меньше вероятность что-то пропустить, только придется потом удалить указанные там абсолютные адреса, стоящие в начале каждой строки. Листинг 5.4 иллюстрирует начало программы для МК ATmega8.

1 Листинг 5.4
;=========прерывания================
гjmp RESET ; Reset Handler
rjmp EXT_INT0 ; IRQO Handler
rjmp EXTJENTl ; IRQl Handler
rjmp TIM2_C0MP ; Timer2 Compare Handler
rjmp TIM2_OVF ; Timer2 Overflow Handler
rjmp TIM1_CAPT ; Timerl Capture Handler
rjmp TIM1_C0MPA ;чTimerl CompareA'Handler
rjmp TIM1_C0MPB ; Timerl CompareB Handler
rjmp TIM1_0VF ; Timerl Overflow Handler
rjmp TIM0_OVF ; TimerO 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

Но постойте: мы что, обязаны использовать все прерывания? Конечно, нет. Для неиспользуемых прерываний в контроллерах с памятью программ менее 16 кбайт команду rjmp <метка> следует заменить на reti — выход из прерывания ("return interrupt"). На самом деле можно было бы указать и команду пор — пустую операцию (см. главу б). Мы будем ставить именно reti, т. к. тогда нам неважно — если прерывание случайно инициализировано, оно все равно не будет выполняться, а писать и отлаживать программы так удобнее. Я в своих программах просто дополняю стандартные строки командой reti и точкой с запятой, чтобы закомментировать команду rjmp (листинг 5.5).

Листинг 5.5
.include "m8def.inc"
. def temp = rl6 ;рабочая переменная
rjmp RESET ; Reset Handler
reti ;rjmp EXT_INT0 ;IRQO Handler
reti ;rjmp EXT_INTl ;IRQ1 Handler

Теперь заготовка начала программы готова: при необходимости в дальнейшем использовать какое-то прерывание, мы удаляем из соответствующей строки фрагмент reti;, а затем где-то в программе ставим нужную метку и пишем обработчик, заканчивающийся командой reti (листинг 5.6).
Листинг 5.6
rjmp RESET ;Reset Handler rjmp EXT_INT0 ;IRQO Handler
EXT_INT0: ;процедура обработки прерывания INTO
reti ;окончание процедуры обработки прерывания INTO

Есть и более короткий способ оформления таблицы векторов прерываний (он особенно актуален для старших Mega, где число прерываний может достигать нескольких десятков, а из-за четырехбайтового формата команды jmp заменить ее на reti просто так не получается). Способ основан на использовании директивы org, которая устанавливает абсолютный адрес в памяти программ. В inc-файлах есть специальные определения констант для адресов прерываний, например (из файла 8515def.inc):
.equ INT0addr=$001;External InterruptO Vector Address
equ URXCaddr=$009;UART Receive Complete Interrupt Vector Address
equ UDREaddr=$00a;UART Data Register Empty Interrupt Vector Address
equ UTXCaddr=$00b;UART Transmit Complete Interrupt Vector Address

Тогда, если вам, к примеру, никакие иные прерывания не требуются, кроме прерываний URXC И UDRE ДЛЯ UART, то начало программы может быть таким, как в листинге 5.7.
Листинг 5.7
Установка векторов прерываний
.org 0 ;начало программы после сброса
4 3ак 400
rjmp RESET
.org UDREaddr ;адрес прерывания'UDRE rjmp TransUART
.org URXCaddr ;адрес прерывания URXC rjmp ReceiveUART
.org $0D /только для 8515 Classic
<программа>



     
 

Библиотека программиста. 2009.
Администратор: admin@programmer-lib.ru