Ile pinów przerwań może obsłużyć Uno?


16

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. Ile przerwań Arduino może obsługiwać natywnie? Czy różni się to od liczby obsługiwanych programów, takich jak PinChangeInt?

Odpowiedzi:


13

Istnieją dwa rodzaje przerwań typu „zmiana pinów”. Zewnętrzne przerwania, których są dwa na Uno. Nazywa się je 0 i 1, jednak odnoszą się do cyfrowych stykó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 są przerywane „zmiany pinów”, które wykrywają zmianę stanu pinów w dowolnym z 20 pinów (od A0 do A5 i od D0 do D13). Przerwania zmiany pinów są również oparte na sprzęcie, więc same w sobie będą tak szybkie, jak przerwania zewnętrzne.

Oba typy są nieco kłopotliwe w użyciu na poziomie rejestru, ale standardowe IDE obejmuje attachInterrupt (n) i detachInterrupt (n), co upraszcza interfejs do zewnętrznych przerwań. Możesz także użyć biblioteki zmiany pinów, aby uprościć przerwania zmiany pinów.

Jednak omijając bibliotekę przez minutę, możemy ustalić, że przerwania zmiany pinów mogą być tak szybkie lub szybsze niż przerwania zewnętrzne. Po pierwsze, chociaż zmiana pinów przerywa pracę na partiach pinów, nie musisz włączać całej partii. Na przykład, jeśli chcesz wykryć zmiany na pinie D4, wystarczy:

Przykładowy 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 wskazują, że zajęło 1,6 µs, aby pin „testowy” (pin 5) zareagował na zmianę na szpilce przerywającej (pin 4).


Teraz, jeśli zastosujesz proste (leniwe?) Podejście i użyjesz attachInterrupt (), zobaczysz, że 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 ()
  {
  }

Wymaga to 3,7 µs, aby zmienić pin testowy, o wiele 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) przy wejściu do ISR, a następnie przywrócić je (pop) przed powrotem. Dodatkowo narzut związany jest z innym wywołaniem funkcji.


Teraz możemy obejść ten problem, unikając metody attachInterrupt () i robiąc to sami:

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 najszybszy ze wszystkich przy 1,52 µs - wygląda na to, że gdzieś zapisano jeden cykl zegara.


Jest jednak jedno zastrzeżenie, dotyczące przerwań związanych ze zmianą pinów. Są one podzielone na partie, więc jeśli chcesz mieć przerwania na wielu pinach, musisz przetestować przerwanie, które zmieniło się. Możesz to zrobić, zapisując poprzedni status PIN i porównując go z nowym statusem PIN. Niekoniecznie jest to szczególnie wolne, ale im więcej pinów musisz sprawdzić, tym wolniej będzie.

Partie to:

  • A0 do A5
  • D0 do D7
  • D8 do D13

Jeśli chcesz tylko kilka pinów przerywających, możesz uniknąć testowania, po prostu wybierając piny z różnych partii (np. D4 i D8).


Więcej informacji na stronie http://www.gammon.com.au/interrupts


9

Istnieją dwa rodzaje przerwań. Co powiedział Arduino Playground :

Procesor w sercu każdego Arduino ma dwa różne rodzaje przerwań: „zewnętrzne” i „zmiana pinów”. Są tylko dwa zewnętrzne piny przerwań w ATmega168 / 328 (tj. W Arduino Uno / Nano / Duemilanove), INT0 i INT1, i są one odwzorowane na piny 2 i 3. Arduino. UPADEK zbocze sygnału lub na niskim poziomie. Wyzwalacze są interpretowane przez sprzęt, a przerwanie jest bardzo szybkie. Arduino Mega ma jeszcze kilka dostępnych zewnętrznych pinów przerwań.

Z drugiej strony przerwania zmiany pinów można włączyć na wielu innych pinach. W przypadku Arduinos opartych na ATmega168 / 328 można je włączyć na dowolnym lub wszystkich 20 pinach sygnałowych Arduino; w Arduinos opartych na ATmega można je włączyć na 24 pinach. Są one wyzwalane jednakowo na krawędziach sygnałów RISING lub FALLING, więc to do kodu przerwania należy ustawić odpowiednie piny do odbierania przerwań, aby ustalić, co się stało (który pin? ... czy sygnał wzrósł lub spadł?), I radzić sobie z tym poprawnie. Ponadto przerwania zmiany pinów są zgrupowane w 3 „portach” na MCU, więc istnieją tylko 3 wektory przerwań (podprogramy) dla całego korpusu pinów. To jeszcze bardziej komplikuje zadanie rozwiązania akcji po jednym przerwie.

Zasadniczo przerwania zewnętrzne są niezwykle szybkie, ponieważ wszystkie oparte są na sprzęcie. Istnieją jednak również przerwania zmiany pinów, ale wydaje się, że są one znacznie wolniejsze, ponieważ są w większości oparte na oprogramowaniu.

tl; dr: 20 pinów przerwań razem jest znacznie wolniejszych. 2 piny przerwań są najszybsze i najbardziej wydajne.


EDYCJA: Właśnie spojrzałem na arkusz danych i mówi, że przerwanie zmiany pinów jest wyzwalane dla każdego wybranego pina bez wskazania, który pin się zmienił (chociaż jest podzielony na trzy wektory przerwań).

  • W przypadku zewnętrznych przerwań poinformuje cię, że pin 3 został właśnie zmieniony
  • W przypadku zmiany numeru PIN pojawi się komunikat, że monitor został zmieniony!

Jak widać, przerwanie zmiany pinów powoduje znaczne obciążenie ISR, z którym musisz sobie poradzić, przechowując poprzednie stany i sprawdzając, czy martwisz się o pin. Może to być dobre dla stanu uśpienia, ale lepiej jest użyć zewnętrznych przerwań.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.