Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
УП МПУ-13.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
6.43 Mб
Скачать

4.2. Входы прерываний inTx и pcinTx.

Внешние прерывания

Внешние прерывания в МК серии AVR ранних моделей состоят только из альтернативных функций INTx. Они поддерживают аппаратное выявление фронта, среза, пр. и формирование индивидуального запроса прерывания, такими функциями оснащались от 2-х до 8-ми отдельных выводов портов. В более поздних моделях к этим функциям добавились функции аппаратного выявления изменения состояния вывода PCINTn [Pin Change INTerrupt], которыми оснащаются все выводы портов.

Оба механизма ориентированы на автоматизацию обслуживания входов, то есть контроля состояния внешних сигналов. Но это не мешает использовать их для контроля изменения состояния выводов в режиме выхода, то есть формировать программно управляемые прерывания.

В МК AT90S8515 имеется два входа прерывания INT0/PD2, INT1/PD3. Событием может быть (табл. 4.1): низкий уровень, фронт, срез, либо любое изменение (фронт/срез). Тип события задается программно битами ISCX1, ISCX0 в регистре MCUCR (табл. 4.2).

Таблица 4.1. Внешние прерывания МК at90s8515

Источник

Вектор

Флаг

Маска

Выбор формы сигнала

INT0 / PD2

INT0_vect = 0x02

GIFR:INTF0

GIMSK:INT0

MCUCR:ISC01, ISC00

INT1 / PD3

INT1_vect = 0x04

GIFR:INTF1

GIMSK:INT1

MCUCR:ISC11, ISC10

Таблица 4.2. Настройка регистра MCUCR на событие на входах INT0, INT1

ISCх1

ISCх0

Форма прерывающего сигнала

0

0

Низкий уровень

0

1

Резерв

1

0

Срез (переход от 1 к 0)

1

1

Фронт (переход от 0 к 1)

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

Прерывание по низкому уровню отличается от других отсутствием триггера запоминания, поэтому это прерывание активно все время, пока на входе присутствует низкий уровень, и «забывается», если к моменту предоставления прерывания уровень стал высоким.

Программное обеспечение прерываний состоит из подготовки (инициализации) и собственно ISR. На этапе инициализации программируются регистры маски [GIMSK], настройки на событие [MCUCR], настройки соответствующего вывода на вход [DDRD]. Последним действием этапа инициализации обычно выполняется команда общего разрешения прерывания [sei].

Обязательными элементами ISR являются целевые действия и команда выхода из прерывания [reti].

Ниже приведен пример использования входов прерывания INT0 и INT1 с реализацией на ассемблере и на GNU-C, схема примера и результаты измерений в симуляторе AVR-Studio, находятся в папке Primer / p2 Interrupt & TimerCounter / Int0cnt.

//INT0/PD2 – счет импульсов, если частота выше порога 200 Гц, то включить красный светодиод на выходе PD4, иначе переключать светодиод с частотой 10 Гц

//INT1/PD3 – по срезу кнопки на этом входе переключать зеленый светодиод на выходе PD0

Пример на Ассемблере

Пример на GNU-С

.include <8515def.inc>

.macro LOAD ;@0, @1

ldi r16,@1

out @0,r16

.endm

.def cnt = r17

.def tmp_int0 = r0

.equ N = 10

rjmp START

.org INT0addr

rjmp ISR_INT0

rjmp ISR_INT1

.org INT_VECTORS_SIZE

START:

LOAD SPL,LOW(RAMEND)

LOAD SPH,HIGH(RAMEND)

LOAD DDRD,(1<<PD0)|(1<<PD4)

LOAD PORTD, (1<<PD3)|(1<<PD0)

LOAD GIMSK, (1<<INT0)|(1<<INT1)

LOAD MCUCR, (1<<ISC11)|(1<<ISC01)|(1<<ISC00)

clr cnt

sei

LOOP:

ldi r18, 100

rcall WAIT_ms

cpi cnt, N

brlo LL

sbi PORTD,PD0

rjmp MM

LL:

sbic PORTD,PD0

rjmp BB

sbi PORTD,PD0

rjmp MM

BB: cbi PORTD,PD0

MM: clr cnt

rjmp LOOP

; ***********************************

ISR_INT0:

in tmp_int0,SREG

inc cnt

out SREG,tmp_int0

reti

; ===================================

ISR_INT1:

sbic PORTD,PD4

rjmp AA

sbi PORTD,PD4

reti

AA: cbi PORTD,PD4

reti

; ===================================

#include <avr/io.h>

#include <avr/interrupt.h>

#include <avr/delay.h>

#define N 10

char cnt;

ISR(INT0_vect) { cnt++; }

ISR(INT1_vect) {

if(PORTD & (1<<PD4)) PORTD &= ~(1<<PD4);

else PORTD |= (1<<PD4);

}

int main() {

DDRD = (1<<PD0)|(1<<PD4);

PORTD = (1<<PD3)|(1<<PD0);

GIMSK = (1<<INT0)|(1<<INT1);

MCUCR = (1<<ISC11)|(1<<ISC01)|(1<<ISC00);

GIFR = (1<<INTF1)|(1<<INTF0);

sei();

while(1) {

_delay_ms(100);

if(cnt > N) {

PORTD |= (1<<PD0);

} else {

if(PORTD & (1<<PD0)) PORTD &= ~(1<<PD0);

else PORTD |= (1<<PD0);

}

cnt=0;

}

} //***********************************

Fclk = 1 МГц

Задержка выполнения действия

в ISR_INT0: 10 мкс, 10 м.ц.

в ISR_INT1: 7 мкс, 7 м.ц.

Время выполнения

в ISR_INT0: 16 мкс, 16 м.ц.

в ISR_INT1: 15 мкс, 15 м.ц.

Период основного цикла 100318 мкс

Задержка выполнения действия

в ISR_INT0: 23 мкс, 23 м.ц.

в ISR_INT1: 33 мкс, 33 м.ц.

Время выполнения

в ISR_INT0: 48 мкс, 48 м.ц.

в ISR_INT1: 85 мкс, 85 м.ц.

Период основного цикла 103540 мкс

Задержка выполнения измерялась от изменения состояния PIND.2 / PIND.3 до первой команды / оператора, выполняющей заданное действие (или выбор действия), то есть время реакции на событие. Время выполнения показывает задержку основного цикла на обслуживание данного прерывания.

Преимущество варианта на ассемблере перед свободно распространяемым транслятором GNU-C (avr-gcc) объясняется оптимальным расходом на сохранение/восстановление контекста.

Любопытные могут увидеть машинный код в файле листинга <*.lss>.и сравнить его с ассемблерным вариантом. Подпрограмма ISR_INT0 использует в качестве ячейки «глобальной» памяти РОН, для сохранения регистра состояния используется еще один РОН. Любой транслятор поместит «глобальную» ячейку в SRAM, для сохранения контекста использует стек в SRAM. Подпрограмма ISR_INT1 использует команды, которые не используют РОН и не меняют содержимое регистра состояния.

В МК более поздних разработок (ATmega48/88/168/328 и др.) входы прерывания INTх имеют расширенный набор выявляемых событий, все выводы параллельных портов оснащены функцией выявления изменения состояния [PCINT023].

Отличия в работе входов прерывания INTх сводятся к использованию ранее зарезервированной комбинации битов выбора события (ISCx1 = 0, ISCx0 = 1) для выявления любого изменения вывода, а также к смене символьных имен регистров [MCUCR, GIFR, GIMSK] на соответствующие им [EICRA, EIFR, EIMSK].

Механизм аппаратного выявления изменения состояния входа PCINTn выявляет изменение сигнала на выводе МК, но не выявляет тип (фронт или срез). В МК указанных выше серий такой функцией оснащены 24 вывода трех параллельных портов. Прерывания представлены тремя векторами PCINT0,1,2, один вектор на группу из 8 входов, общим на группу является и флаг PCIFR. Маскирование прерываний выполняется как общее на группу (например, PCICR.PCIE0 – для PCINT0…7), так и индивидуальное (PCMSK0.PCINT0).

Рассмотрим подробнее состав и назначение регистров механизма PCINTn.

Регистр PCICR [Pin Change Interrupt Control Register] содержит три бита: PCIE0 [.. Interrupt Enable] – разрешение прерывания при изменении состояния на 8 выводах PCINT0…7, PCIE1 – на выводах PCINT8…15, PCIE1 – на выводах PCINT16…23.

Регистр PCIFR [Pin Change Interrupt Flag Register] содержит три бита PCIF0 [Pin Change Interrupt Flag] – флаг прерывания по выводам PCINT0…7, PCIF1 – на выводах PCINT8…15, PCIF2 – на выводах PCINT16…23.

Регистры PCMSK0, 1, 2 [Pin Change Mask Register] содержит биты PCINT0..7 [Pin Change Enable Mask], PCINT8..15, PCINT16..23 соответственно для индивидуального разрешения прерываний по каждому выводу.

Данный механизм ориентирован для сравнительно медленных сигналов. Для уточнения причины прерывания: фронт или срез и на каком из 8 выводов группы произошло изменение состояния, необходимо иметь память предыдущего состояния текущего порта и затратить время на анализ. Эти действия не нужны, если разрешен только один из 8 выводов данной группы и не имеет значение тип события (фронт или срез), тогда временные затраты не отличаются от механизма INTx.