Існує два типи переривань типу "pin pin". Зовнішні переривання, яких на Уно є два. Вони називаються 0 і 1, однак вони посилаються на цифрові штифти 2 і 3 на дошці. Вони можуть бути налаштовані для виявлення підйому, падіння, зміни (піднесення або падіння) або НИЗКО.
На додаток до цього є переривання "pin pin", які виявляють зміну стану штифта в будь-якому з 20-ти контактів (від A0 до A5 і D0 до D13). Ці переривання штифтових змін також є апаратними, тому самі по собі будуть такими ж швидкими, як і зовнішні переривання.
Обидва типи злегка використовувати на рівні реєстру, але стандартний IDE включає в себе attachInterrupt (n) та detachInterrupt (n), що спрощує інтерфейс до зовнішніх переривань. Ви також можете скористатися бібліотекою змін змін пін для спрощення переривань зміни пін.
Однак, відхилившись від бібліотеки на хвилину, ми можемо встановити, що переривання зміни штифтів можуть бути настільки ж швидшими чи швидшими, ніж зовнішні переривання. З одного боку, хоча зміна штифтів перериває роботу на партіях штифтів, вам не потрібно включати всю партію. Наприклад, якщо ви хочете виявити зміни на штифті D4, цього буде достатньо:
Приклад ескізу:
ISR (PCINT2_vect)
{
// handle pin change interrupt for D0 to D7 here
if (PIND & bit (4)) // if it was high
PORTD |= bit (5); // turn on D5
else
PORTD &= ~bit (5); // turn off D5
} // end of PCINT2_vect
void setup ()
{
// pin change interrupt (example for D4)
PCMSK2 |= bit (PCINT20); // want pin 4
PCIFR |= bit (PCIF2); // clear any outstanding interrupts
PCICR |= bit (PCIE2); // enable pin change interrupts for D0 to D7
pinMode (4, INPUT_PULLUP);
pinMode (5, OUTPUT);
} // end of setup
void loop ()
{
}
Моє тестування вказує, що реакція на зміну штифта переривання (контакт 4) знадобилася 1,6 мкс, щоб контактний "тест" (контакт 5) реагував на зміну.
Тепер, якщо ви скористаєтеся простим (лінивим?) Підходом і використовуєте attachInterrupt (), ви знайдете результати повільніші, а не швидші.
Приклад коду:
void myInterrupt ()
{
if (PIND & bit (2)) // if it was high
PORTD |= bit (5); // turn on D5
else
PORTD &= ~bit (5); // turn off D5
} // end of myInterrupt
void setup ()
{
attachInterrupt (0, myInterrupt, CHANGE);
pinMode (2, INPUT_PULLUP);
pinMode (5, OUTPUT);
} // end of setup
void loop ()
{
}
Для зміни тестового штиря потрібно 3,7 мкс, набагато більше, ніж 1,6 мкс вище. Чому? Оскільки код, який повинен створити компілятор для "загального" обробника переривань, повинен зберегти кожен можливий реєстр (натиснути їх) при вступі до ISR, а потім відновити їх (спливати) перед поверненням. Плюс є накладні витрати іншого виклику функції.
Тепер ми можемо обходити це, уникаючи приєднання InterInrupt () і робимо це самостійно:
ISR (INT0_vect)
{
if (PIND & bit (2)) // if it was high
PORTD |= bit (5); // turn on D5
else
PORTD &= ~bit (5); // turn off D5
} // end of INT0_vect
void setup ()
{
// activate external interrupt 0
EICRA &= ~(bit(ISC00) | bit (ISC01)); // clear existing flags
EICRA |= bit (ISC00); // set wanted flags (any change interrupt)
EIFR = bit (INTF0); // clear flag for interrupt 0
EIMSK |= bit (INT0); // enable it
pinMode (2, INPUT_PULLUP);
pinMode (5, OUTPUT);
} // end of setup
void loop ()
{
}
Це найшвидший з них у всіх 1,52 мкс - схоже, що один тактовий цикл десь врятувався.
Однак є одне застереження для перерв на переключення. Вони видозмінені, тому, якщо ви хочете мати перерви на багатьох штирях, вам потрібно перевірити всередині переривання, яке змінилося. Ви можете зробити це, збереживши попередній статус штифта та порівнявши його з новим статусом шпильки. Це не обов'язково особливо повільно, але чим більше штифтів потрібно перевірити, тим повільніше буде.
Партії:
- Від A0 до A5
- Від D0 до D7
- Від D8 до D13
Якщо ви хочете отримати ще кілька шпильок для переривання, ви можете уникнути будь-якого тестування, просто вибравши використовувати штифти різних партій (наприклад, D4 і D8).
Детальніше на http://www.gammon.com.au/interrupts