Пишем программный код для настройки внешнего прерывания микроконтроллера Atmega8 в среде программирования Microchip Studio.

В контроллерах Atmega8 есть только 2 входа для внешнего прерывания, это вывода PD2 (INT0) и PD3(INT1):

Для настройки прерывания используют следующие реестры:

GICR:

В данном регистре нас интересуют 6 и 7 бит. Установка данного бита в 1 разрешает прерывания INT0 или INT1.

MCUCR:

В данном регистре нас интересуют биты 0-3:

Бит 0-1 отвечают за настройку прерывания INT0, бит 2-3 отвечают за настройку прерывания INT1.

Значения бит ISC01 и ISC00:

ISC01 ISC00 Значение
0 0 Прерывание вызывается по уровню лог.0 на входе INT0.
0 1 Прерывание вызывается по изменению любого состояния.
1 0 Прерывание вызывается по ниспадающему фронту сигнала на входе INT0.
1 1 Прерывание вызывается по возрастающему фронту сигнала на входе INT0.
Прерывания по входу INT1 настраиваются так же 
Так же необходимо разрешить глобально работу прерывания, выполняется это командой:
sei();//Разрешить прерывания
или через реестр:
SREG|= (1<<7); //разрешить общие прерывания

Для проверки работы прерывания, мы подключим к ножкам PD0 и PD1 светодиоды, а к ножке PD2 и PD3 кнопки, при нажатии на которых мы будем включать/выключать светодиоды. Так  же мы дополнительно подключим к ножке PD4 светодиод, который будет переключать свое состояние раз в пол секунды — имитация работы самостоятельного программного кода .

Пример кода (переключения светодиодов HL1 и HL2 происходят в не рабочего цикла):

#define F_CPU 4000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>// подключаем библиотеку
void init_interrupt(void);
void int_pcb(void);

#define HL1_on PORTD|=(1<<PD0)
#define HL1_off PORTD&=~(1<<PD0)
#define HL2_on PORTD|=(1<<PD1)
#define HL2_off PORTD&=~(1<<PD1)
#define HL3_on PORTD|=(1<<PD4)
#define HL3_off PORTD&=~(1<<PD4)

ISR(INT0_vect){ // прерывание по ножке PD2
HL1_on;
HL2_off;
}

ISR(INT1_vect){ // прерывание по ножке PD3
HL2_on;
HL1_off;
}

int main(void){
init_interrupt();
int_pcb();
while (1) {
HL3_on;
_delay_ms(500);
HL3_off;
_delay_ms(500);
}
}

void init_interrupt(void){// настройка прерывания
GICR|=(1<<INT0)|(1<<INT1); // включаем прерывания
MCUCR|=(1<<ISC00)|(1<<ISC10);//устанавливаем тип срабатывания
sei();// разрешаем работу прерываниям
}

void int_pcb(void){
PORTD=0b00001100;//РD2 PD3 - подключаем подтягивающие резисторы для работы кнопки
DDRD= 0b00010011;//PD0 PD1 PD4 - настраиваем ножки на выход
}