Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
УП МПУ-13.doc
Скачиваний:
3
Добавлен:
01.04.2025
Размер:
5.78 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.

//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х, действует подобно описанному для МК AT90S8515. Отличия сводятся к использованию ранее зарезервированной комбинации битов выбора события (ISCx1 = 0, ISCx0 = 1) для выявления любого изменения вывода, а также к смене символьных имен регистров [MCUCR, GIFR, GIMSK] на соответствующие им [EICRA, EIFR, EIMSK].

Механизм аппаратного выявления изменения состояния вывода PCINTn различает только любое изменение сигнала. Он имеет по одному вектору [PCINT0,1,2] и флагу прерывания на группу из 8 выводов, маскирование прерываний выполняется как общее на группу (например, PCICR.PCIE0 – для PCINT0…7), так и индивидуальное (PCMSK0.PCINT0). Для уточнения причины прерывания: фронт или срез и на каком из 8 выводов группы произошло изменение состояния, необходимо иметь память предыдущего состояния текущего порта и затратить время на анализ. Эти действия не нужны, если разрешен только один из 8 выводов данной группы и не имеет значение тип события (фронт или срез), тогда временные затраты не отличаются от механизма INTx.

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

Pin Change Interrupt Flag Register – PCIFR: Bit 0 - PCIF0: Pin Change Interrupt Flag 0, 1, 2

Pin Change Mask Register 0 – PCMSK0(1, 2): Bit 7..0 – PCINT7..0: Pin Change Enable Mask 7..0

Ориентирован для сравнительно медленных сигналов,

Сгруппированы по 8 входов - флаги (по фронту/срезу, вектора), индивидуальны - маска прерывания PCMSKx. Следовательно, для сравнительно медленных нет проблем, если используется один из входов в данном порту, иначе - требуется анализ предыдущего состояния, хотя для разбора фронт или срез...