Patrzę na użycie 7-kanałowego odbiornika RC z Arduino Uno R3. W dokumentacji są wzmianki o maksymalnie 2 pinach przerwań, podczas gdy na niektórych innych blogach widziałem wzmianki o użyciu do 20 pinów jako przerwań, z biblioteką PinChangeInt. Więc ile przerwań może obsłużyć Arduino natywnie? I czy to się różni od tego, ile można obsłużyć dzięki obsłudze oprogramowania, takiej jak PinChangeInt?
Odpowiedź
Istnieją dwa rodzaje „ Przerwania typu „zmiana pinu”. Przerwania zewnętrzne, których są dwa na Uno. Nazywają się 0 i 1, jednak odnoszą się do cyfrowych pinów 2 i 3 na płycie. Można je skonfigurować tak, aby wykrywały wzrost, spadek, zmianę (wzrost lub spadek) lub NISKI.
Oprócz tego istnieją przerwania typu „zmiana pinu”, które wykrywają zmianę stanu pinu w dowolnym z 20 styków (A0 na A5 i D0 na D13). Te przerwania zmiany pinów są również oparte na sprzęcie , więc same w sobie będą równie szybkie, jak przerwania zewnętrzne.
Oba typy są nieco kłopotliwe w użyciu na poziomie rejestru, ale standardowe IDE zawiera attachInterrupt (n) i detachInterrupt (n), co upraszcza interfejs do zewnętrznych przerwań. Możesz również skorzystać z biblioteki zmiany pinów , aby uprościć przerwania zmiany pinów.
Jednak omijając bibliotekę na minutę, można ustalić, że przerwania zmiany pinów mogą być równie szybkie lub szybsze niż przerwania zewnętrzne. Po pierwsze, chociaż przerwania zmiany pinów działają na partiach pinów, nie musisz włączać całej wiązki. Na przykład, jeśli chcesz wykryć zmiany na pinie D4, to wystarczy:
Przykład szkic:
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 () { }
Moje testy wykazały, że „test trwał 1,6 µs” „pin (pin 5), aby zareagować na zmianę na pinie przerwania (pin 4).
Teraz, jeśli podejmiesz proste (leniwe?) podejście i użyjesz attachInterrupt (), znajdziesz wyniki są wolniejsze, a nie szybsze.
Przykładowy kod:
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 () { }
Zmiana pinów testowych zajmuje 3,7 µs, dużo więcej niż 1,6 µs powyżej. Dlaczego? Ponieważ kod, który kompilator musi wygenerować dla „ogólnej” procedury obsługi przerwań, musi zapisać każdy możliwy rejestr (wypchnąć je) na wpis do ISR, a następnie przywróć je (zdejmij) przed powrotem. Dodatkowo istnieje narzut innego wywołania funkcji.
Teraz możemy to obejść, unikając attachInterrupt () i robiąc to samodzielnie:
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 () { }
To jest najszybsze z nich przy 1,52 µs – wygląda na to, że gdzieś zapisano jeden cykl zegara.
Jest jednak jedno zastrzeżenie, dotyczące przerwań ze zmianą pinów. Są one grupowane, więc jeśli chcesz mieć przerwania na wielu pinach, musisz przetestować wewnątrz przerwania , które zostało zmienione . Możesz to zrobić, zapisując poprzedni status pinezki i porównując go z nowym statusem pinezki. Niekoniecznie jest to szczególnie powolne, ale im więcej pinów musisz sprawdzić, tym wolniej.
Partie to:
- A0 do A5
- D0 do D7
- D8 do D13
Jeśli potrzebujesz tylko kilku więcej pinów przerwań, możesz uniknąć testów, wybierając po prostu użycie pinów z różnych partie (np. D4 i D8).
Więcej szczegółów pod adresem http://www.gammon.com.au/interrupts
Odpowiedź
Istnieją dwa rodzaje przerwań. Co powiedział Plac zabaw Arduino :
Procesor w sercu każdego Arduino ma dwa różne rodzaje przerwań: „zewnętrzne” i „zmiana pinów”. Istnieją tylko dwa zewnętrzne piny przerwań na ATmega168 / 328 (tj. W Arduino Uno / Nano / Duemilanove), INT0 i INT1 i są one zmapowane do pinów 2 i 3 Arduino. FALLING zbocza sygnału lub niski poziom. Wyzwalacze są interpretowane przez sprzęt, a przerwanie jest bardzo szybkie. Arduino Mega ma kilka dodatkowych zewnętrznych pinów przerwań.
Z drugiej strony przerwania zmiany pinów mogą być włączone na wielu innych pinach. W przypadku Arduino bazujących na ATmega168 / 328, można je włączyć na dowolnym lub wszystkich 20 pinach sygnałowych Arduino; w Arduino na bazie ATmega można je włączyć na 24 pinach. więc to do kodu przerwania należy ustawienie odpowiednich pinów do odbierania przerwań, określenie, co się stało (który pin? … czy sygnał wzrósł, czy spadł?) i odpowiednio go obsłużyć.Co więcej, przerwania zmiany pinów są zgrupowane w 3 „portach” na MCU, więc są tylko 3 wektory przerwań (podprogramy) dla całego korpusu pinów. To sprawia, że rozwiązywanie akcji na pojedynczym przerwaniu jest jeszcze bardziej skomplikowane.
Zasadniczo, zewnętrzne przerwania są bardzo szybkie, ponieważ „są oparte na sprzęcie . Jednak jest też przerwanie zmiany pinów, ale wydaje się, że są one znacznie wolniejsze, ponieważ są głównie oparte na oprogramowaniu.
tl; dr: razem 20 pinów przerwań jest znacznie wolniejszych. 2 piny przerwań są najszybsze i najbardziej wydajne.
EDYCJA: Właśnie spojrzałem na arkusz danych i jest tam napisane, że przerwanie zmiany pinu jest wyzwalane dla dowolnego wybranych pinów bez wskazania który pin się zmienił (chociaż jest podzielony na trzy wektory przerwań).
- W przypadku przerwań zewnętrznych, powie ci pin 3 właśnie się zmienił
- Aby zmienić pin, „powiem ci zmienił pin, który monitorowałeś!
Jak widać, przerwanie zmiany pinu dodaje wiele narzutów do ISR, z którymi musisz sobie poradzić, przechowując poprzednie stany i sprawdzając, czy to jest ten pin, o który się martwisz. To może być dobre dla stanu uśpienia, ale lepiej jest używać zewnętrznych przerwań.