Работа с прерываниями PCINT0…23

Atmega328


PCINT0…23 — это входы для внешнего прерывания которое срабатывает при изменении состояния на входах PCINT0..23.

За внешние прерывания отвечают несколько регистров:

 

Регистр PCICR — определяет какую группу входов использовать в качестве источника прерывания:

7 6 5 4 3 2 1 0
PCIE2 PCIE1 PCIE0

Группа PCIE2 отвечает за входы PCINT[23:16], PCIE1 за PCINT[14:8], а группа PCIE0 за входы PCINT[7:0].

Пример использования:

PCICR |= (1 << PCIE0); // определяет группу входов PCIE0 PCINT0…7

 

Далее используются при необходимости три регистра, каждый регистр отвечает за выход PCINTх в своей группе:

  • Регистр PCMSK2 отвечает за выходы PCINT[23:16]
7 6 5 4 3 2 1 0
PCINT23 PCINT22 PCINT21 PCINT20 PCINT19 PCINT18 PCINT17 PCINT16
  • Регистр PCMSK1 отвечает за выходы PCINT[14:8]
7 6 5 4 3 2 1 0
PCINT14 PCINT13 PCINT12 PCINT11 PCINT10 PCINT9 PCINT8
  • Регистр PCMSK0 отвечает за выходы PCINT[7:0]
7 6 5 4 3 2 1 0
PCINT7 PCINT6 PCINT5 PCINT4 PCINT3 PCINT2 PCINT1 PCINT0

Установка какого-нибудь бита из PCINT0…23 разрешает соответствующему выводу работать в качестве источника.

Одновременно можно задействовать несколько входов, которые будут работать как источник прерывания.

Пример использования:

PCMSK0 |= (1 << PCINT0); // использовать PCINT0 в группе PCIE0

 

PCIFR — регистр флагов

7 6 5 4 3 2 1 0
PCIF2 PCIF1 PCIF0

При смене логического уровня на любом из выводов PCINT0…23 происходит вызов прерывания, при этом устанавливается соответствующий флаг прерывания PCIF0…3 (на одну группу один флаг). Этот флаг очищается аппаратно после выхода из подпрограммы обработки прерывания.

Обработчики прерывания PCINTx_vect, каждый для своей группы.

Пример использования:

ISR(PCINT0_vect){ // — код — //} — при возникновении прерывания исполняется // — код — //

ISR(PCINT1_vect){ // — код — //} — при возникновении прерывания исполняется // — код — //

ISR(PCINT2_vect){ // — код — //} — при возникновении прерывания исполняется // — код — //

 

Пример:

int i;

void setup() {
  DDRB |= (1 << PB5);// выход светодиода D13 (PB5) на плате Arduino
  DDRB &= ~(1 << 0); PORTB |= (1 << 0); // выход PCINT0 (D8) как выход, подтягивающий резистор включить
  PCICR |= (1 << PCIE0); // определяет группу входов PCIE0 PCINT0...7
  PCMSK0 |= (1 << PCINT0); // использовать PCINT0 в группе PCIE0
}

void loop() {
  PORTB |= (1 << 5); // PB5 выход 1
  if (i == 1)delay(5000); i = 0; // как сработает прерывание подождать 5 секунд
}

ISR(PCINT0_vect) {
  PORTB &= ~(1 << 5); // погасить светодиод на D13
  i = 1;
}

Светодиод на плате Arduino Uno который подключен к PB5 горит всегда, если кратковременно замкнуть вход PCINT0 на GND, светодиод погаснет на 5 секунд и загорится вновь.

Добавить комментарий

Войти с помощью: