Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
AVR_01-2010.doc
Скачиваний:
10
Добавлен:
19.09.2019
Размер:
368 Кб
Скачать
☆

Врезка. Пример использования.

#include <avr/io.h> FUSES ={

  • low = LFUSE_DEFAULT,

• high = (FUSE_BOOTSZ0 & FUSE_EESAVE & FUSE_SPIEN & FUSE_JTAGEN),

  • extended = EFUSE_DEFAULT, };

Int main(void){

return 0; }

34 Т.к. fuse-биты отличаются в зависимости от модели микроконтроллера, следует ознакомиться с их наименованием по соответствующей документации к выбранному контроллеру; в настоящей документации они не приводятся.

В WinAVR принято, что каждому оп­ределенному вектору прерывания сопо­ставлена особым образом поименован­ная функция-обработчик. Определение в

программе функции, названной в соответ­ствии с определенными соглашениями, при­водит к тому, что компилятор генерирует для нее нестандартный код пролога и эпилога, в частности, обязательно сохраняет SREG в начале и восстанавливает в конце, а так же использует для возврата из функции ко­манду RETI. Кроме того, в таблице векто­ров прерываний для каждой определенной пользователем функции-обработчика поме­щается команда перехода к соответствую­щей функции.

Далее кратко перечислены основные характерные особенности реализации об­работчиков прерываний WinAVR. Подроб­ности следует искать в описаниях соответ­ствующих макросов.

Детали реализации этого подхода ос­таются за кадром, т.к. программисту доста­точно определить при помощи макроса ISR() функцию - и она будет назначена (и соот­ветственно оформлена) обработчиком оп­ределенного прерывания.

Особенность аппаратного строения AVR заключается в том, что во время работы одного обработчика прерываний все про­чие прерывания запрещены. Такая ситуа­ция в некоторых случаях может быть неже­лательной, для чего можно (естественно, осознавая последствия, к которым это мо­жет привести) разрешить прерывания при­нудительно внутри функции-обработчика, используя макрос sei(). Но можно поступить и проще, указав для макроса ISR() параметр ISR_NOBLOCK, что заставит компилятор поместить соответствующую инструкцию глобального разрешения прерываний сра­зу после пролога функции (т.е. инициали­зирующего участка кода).

При разработке программ не исключе­на ситуация, когда случайно будет сгенери­ровано прерывание, для которого нет на­значенного обработчика (ситуация «баг про­граммы»). По умолчанию компилятор гене­рирует код, который в этом случае приве­дет к переходу на адрес 0х0000, т.е. пове­дение кода равносильно сбросу микрокон­троллера. Однако такое поведение можно изменить, определив особый обработчик «неверного прерывания», который автома­тически назначается все «незанятым» век­торам прерываний. Делается это при помо­щи указания для ISR() «плохого» вектора BADISR_vect. Такой обработчик будет исполь­зован для всех векторов прерываний, для которых не указаны явно их обработчики.

Так же часто может возникать ситуа­ция, когда один и тот же обработчик дол­жен использоваться для нескольких пре­рываний. Можно, конечно, определить не­сколько абсолютно идентичных функций, однако, можно и сэкономить память, ука­зав для ISR() параметр ISR_ALIASOF().

Еще одной занимательной ситуаци­ей, связанной с прерываниями, является пробуждение микроконтроллера по пре­рыванию из «спящего» режима. В этом случае обработчик прерывания вызыва­ется, однако, часто в нем никаких полез­ных действий выполняться не должно. Для таких случаев предусмотрен мак­рос EMPTY_INTERRUPT(), позволяющий определить обработчик, который не дела­ет ничего.

Наконец, во многих случаях может оказаться, что неизбежно генерируемый компилятором для обработчика прерыва­ния код пролога и эпилога оказывается слишком велик. Было бы удобно в таком случае использовать обработчик, реали­зованный на ассемблере, либо попы­таться обойтись средствами Си для по­лучения более оптимального кода. Сде­лать это можно при помощи параметра ISR_NAKED, указываемого для ISR(). В этом случае компилятор не генерирует вообще никакого пролога и эпилога, по­этому программист сам должен обеспе­чить сохранение контекста программы (в частности, содержимого SREG), и, глав­ное, использовать макрос reti() для выхо­да из обработчика.

Для каждого микроконтроллера опре­делены свои константы для указания со­ответствующего вектора прерывания. Эти константы содержат в своем составе суффиктс _vect. Для совместимости с предыдущими версиями WinAVR сохране­на и возможность определять обработчик прерывания при помощи «сигналов», т.е. констант, имеющих «префикс» SIG_ (пре­фиксы и суффиксы соответствующих век­торов определены в заголовочных фай­лах для каждого типа микроконтролле­ров). Рекомендуется использовать «но­вую» форму _vect.

Макросы и определения

sei()

sei() - глобальное разрешение преры­ваний

cli()

cli() - глобальное запрещение преры­ваний

reti()

reti() - макрос принудительно помеща­ет в код программы инструкцию RETI, обес­печивая возврат из прерывания.

ISR()

ISR(vector, attributes) - макрос для оп­ределения обработчика прерываний.

Врезка ISR_ALIAS

// определяем обработчик внешнего запроса прерывания №0 ISR(INT0_vect){

PORTB = 42; }

// назначаем этот обработчик и для запроса №1 ISR_ALIAS(INT1_vect, INT0_vect);

Врезка ISR_ALIASOF

// определяем обработчик внешнего запроса прерывания №0 и одновременно №1 ISR(INT0_vect, ISR_ALIASOF(INT1_vect)){

PORTB = 42; }

Первый параметр vector - это одна из констант, определяющих номер век­тора прерывания. Реальные константы определены в соответствующем заголовоч­ном файле модели микроконтроллера (оканчиваются на суффикс _vect, например, ADC_vect). Кроме этого можно использо­вать константу BADISR_vect для задания об­работчика «по умолчанию».

Второй параметр attributes - необяза­тельный, определяет опциональные вари­анты реализации соответствующего обра­ботчика. Допустимо использовать несколь­ко атрибутов из числа следующих (атрибу­ты разделяются запятыми):

ISR_BLOCK - атрибут по умолчанию, означает запрет прерываний, пока не отра­ботает текущий обработчик

ISR_NOBLOCK - разрешает глобально прерывания сразу после пролога обработ­чика

ISR_NAKED - указывает, что вся реа­лизация кода обработчика делается про­граммистом (нет никакого пролога и эпило­га)

ISR_ALIASOF(v) - позволяет назначить текущему обработчику несколько векторов (см. врезку для ISR_ALIASOF).

SIGNAL()

SIGNAL(vector) - макрос определения обработчика, сохраненный исключительно для совместимости со старым кодом. Не ре­комендуется использование в новых разра­ботках. В качестве параметра vector дол­жен получать константу с префиксом SIG_ из заголовочного файла конкретного мик­роконтроллера (например, SIG_ADC).

EMPTY_INTERRUPT()

EMPTY_INTERRUPT(vector) - макрос определения «пустого» обработчика, т.е. состоящего только из команды RETI. В ка­честве параметра принимаются те же зна­чения, что и для ISR().