Прерывание по изменению вывода (pin change interrupt)
У ATmega328P всего два внешних прерывания INT0 и INT1 с выбором фронта. Но прерывание можно получить почти с любого вывода — через механизм pin change: оно срабатывает при каждом изменении уровня, а выводы сгруппированы по портам.
Обновлено Редакция GAW
Прерывание по изменению вывода (pin change interrupt, PCINT) — механизм AVR, при котором любое изменение уровня на разрешённом выводе вызывает прерывание. В отличие от внешних прерываний INT0 и INT1, у него нет выбора фронта, а выводы объединены в группы с общим вектором. Зато такой вывод — почти любой: у ATmega328P это 23 вывода в трёх группах (DS40002061B, разд. 13).
Группы ATmega328P
| Группа | Выводы | Маска | Разрешение | Флаг | Вектор |
|---|---|---|---|---|---|
| PCI0 | PCINT0…7 = PB0…PB7 | PCMSK0 | PCIE0 | PCIF0 | PCINT0 |
| PCI1 | PCINT8…14 = PC0…PC6 | PCMSK1 | PCIE1 | PCIF1 | PCINT1 |
| PCI2 | PCINT16…23 = PD0…PD7 | PCMSK2 | PCIE2 | PCIF2 | PCINT2 |
Регистры — по DS40002061B (разд. 13.2.4–13.2.8), соответствие выводам — по распиновке там же. Бит в PCMSKx разрешает конкретный вывод, бит PCIEx в PCICR — всю группу; при глобальном разрешении прерываний изменение на любом разрешённом выводе группы ставит флаг PCIFx и вызывает вектор группы. Флаг сбрасывается при входе в обработчик или записью единицы.
Особенности
- Один вектор на группу. Какой вывод сработал, программа выясняет сама, сравнивая текущее значение PINx с прошлым.
- Любое изменение. И фронт, и спад вызывают прерывание; нужное направление определяют по уровню вывода.
- Работает и на выходе. Прерывание срабатывает, даже если вывод настроен на выход — так Microchip предлагает получать программное прерывание.
- Пробуждение. Изменения обнаруживаются асинхронно, поэтому PCINT будит кристалл из любых режимов сна, а не только из Idle.
Механические кнопки на PCINT стоит защищать от дребезга: каждое касание даст серию изменений. У ATtiny25/45/85 то же устроено проще: одно внешнее прерывание INT0 и группа PCINT0…5 с одним вектором (даташит 2586Q). У STM32 похожую задачу решают линии EXTI, но там у каждой линии свой фронт. Распиновка ATmega328P с номерами PCINT — на странице ATmega328P.
Частые вопросы
Как узнать, какой именно вывод вызвал прерывание PCINT?
Аппаратно — никак: на группу выводов один вектор и один флаг (DS40002061B, разд. 13). Наш вывод: в обработчике читают регистр PINx нужного порта и сравнивают с сохранённым прошлым значением — изменившиеся биты и есть источники. Если изменения быстрые, часть их можно пропустить, пока обработчик не успел прочитать порт.
Можно ли выбрать фронт для PCINT?
Нет, прерывание срабатывает при любом изменении уровня — и на фронте, и на спаде. Выбор фронта, спада или низкого уровня есть только у INT0 и INT1 через регистр EICRA (DS40002061B, разд. 13). Нужный фронт определяют программно по текущему уровню вывода.
Разбудит ли PCINT микроконтроллер из Power-down?
Да. Microchip указывает, что изменения на выводах PCINT23…0 обнаруживаются асинхронно, поэтому эти прерывания будят кристалл и из режимов сна глубже Idle, в том числе из Power-down. Для кнопок это удобно, но дребезг контактов даст несколько пробуждений подряд.
Источники
- Microchip. ATmega48A/PA/88A/PA/168A/PA/328/P Data Sheet, DS40002061B — разд. 13 — внешние прерывания от INT0, INT1 и PCINT23…0, срабатывают и при выводе, настроенном на выход; PCI2 — при изменении любого разрешённого PCINT[23:16], PCI1 — PCINT[14:8], PCI0 — PCINT[7:0]; маски PCMSK2…0; изменения обнаруживаются асинхронно, поэтому будят из любых режимов сна, не только Idle; INT0/INT1 — фронт, спад или низкий уровень (EICRA); 13.2.4 — PCICR: PCIE2…0 разрешают группы; 13.2.5 — PCIFR: флаги PCIF2…0 сбрасываются при входе в обработчик или записью 1; табл. векторов — PCINT0, PCINT1, PCINT2; распиновка — PCINT0…7 на PB0…7, PCINT8…14 на PC0…6, PCINT16…23 на PD0…7
- Microchip. ATtiny25/45/85 Data Sheet, 2586Q — разд. 9.1 — один вектор PCINT0 (Pin Change Interrupt Request 0); 9.2 — внешние прерывания от INT0 и PCINT[5:0], маска PCMSK, срабатывают и на выходе
Нашли ошибку?
Смотрите также
- ПрерываниеЗапрос периферии, вектор и обработчик прерывания
- ATmega328PРаспиновка, фьюзы, Optiboot, периферия, питание, схема и код на C
- Режимы снаSleep mode: Idle, Power-down, пробуждение и ток
- Дребезг контактовСерия переключений вместо одного при нажатии кнопки
- EXTI — внешние прерывания STM32Линии, которые превращают фронт на выводе в прерывание или событие