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 секунд и загорится вновь.