Hvor mange afbrydestifter kan en Uno håndtere?

Jeg kigger på at bruge en 7-kanals RC-modtager med Arduino Uno R3. I dokumentationen er der nævnt maksimalt 2 interrupt pins, mens jeg på visse andre blogs har set omtaler at bruge op til 20 pins som interrupts med PinChangeInt-biblioteket. Så hvor mange afbrydelser kan Arduino håndtere indbygget? Og er dette forskelligt fra, hvor mange der kan håndteres med softwaresupport såsom PinChangeInt?

Svar

Der er to typer ” pin-ændring “type afbryder. De eksterne afbrydelser, hvoraf der er to på Uno. De kaldes 0 og 1, men de henviser til digitale ben 2 og 3 på tavlen. Disse kan konfigureres til at registrere stigende, faldende, ændring (stigende eller faldende) eller LAV.

Derudover er der “pin-skift” -afbrydelser, som registrerer en ændring i pin-tilstanden i en hvilken som helst af de 20 ben (A0 til A5 og D0 til D13). Disse pin-skift-afbrydelser er også hardware-baserede så i sig selv vil de være lige så hurtige som de eksterne afbrydelser.

Begge typer er svær at bruge på registerniveau, men standard IDE inkluderer attachInterrupt (n) og detachInterrupt (n), der forenkler grænsefladen til eksterne interrupts. Du kan også bruge Pin Change Library til at forenkle pin-switch-afbrydelser.

Dog styrer vi biblioteket i et minut, vi kan fastslå, at pin-skift-afbrydelser kan være så hurtige eller hurtigere end eksterne afbrydelser. For det første, selvom pin-skift afbryder arbejde på batcher af pins, behøver du ikke aktivere hele batchen. Hvis du f.eks. Vil opdage ændringer på pin D4, er dette tilstrækkeligt:

Eksempel skitse:

 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 () { }  

Min test indikerer, at det tog 1,6 µs for “testen “pin (pin 5) for at reagere på en ændring på interrupt pin (pin 4).


Nu hvis du tager den enkle (dovne?) tilgang og bruger attachInterrupt () finder du resultaterne er langsommere, ikke hurtigere.

Eksempelkode:

 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 () { }  

Det tager 3,7 µs at skifte testnål, meget mere end 1,6 µs ovenfor. Hvorfor? Fordi koden, som kompilatoren skal generere til den “generiske” afbrydningshåndterer, skal gemme alle tænkelige register (skubbe dem) på adgang til ISR, og gendan dem derefter (pop dem) inden du vender tilbage. Plus der er overhead for et andet funktionsopkald.


Nu kan vi løse det ved at undgå attachInterrupt () og gøre det selv:

 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 () { }  

Det er den hurtigste af dem alle ved 1,52 µs – det ser ud til, at en urcyklus blev gemt et eller andet sted.


Der er dog en advarsel for afbrydelser af pin-skift. De er batchede, så hvis du vil have afbrydelser på mange ben, skal du teste inde i afbrydelsen hvilken en ændrede . Du kan gøre det ved at gemme den forrige pin-status og sammenligne den med den nye pin-status. Dette er ikke nødvendigvis særlig langsomt, men jo flere ben du skal kontrollere, jo langsommere ville det være.

Batcherne er:

  • A0 til A5
  • D0 til D7
  • D8 til D13

Hvis du bare vil have et par flere afbrydestifter, kan du undgå enhver test ved blot at vælge at bruge stifter fra forskellige batcher (f.eks. D4 og D8).


Flere detaljer på http://www.gammon.com.au/interrupts

Svar

Der er to typer afbrydelser. Hvad Arduino Playground sagde:

Processoren i hjertet af enhver Arduino har to forskellige slags afbrydelser: “ekstern” og “pin skift”. Der er kun to eksterne afbrydestifter på ATmega168 / 328 (dvs. i Arduino Uno / Nano / Duemilanove), INT0 og INT1, og de kortlægges til Arduino stifter 2 og 3. Disse afbrydelser kan indstilles til at udløse ved RISING eller FALDENDE signalkanter eller på lavt niveau. Triggerne fortolkes af hardware, og afbrydelsen er meget hurtig. Arduino Mega har et par flere eksterne afbrydelsesstifter til rådighed.

På den anden side kan pin-skift-afbrydelser aktiveres på mange flere ben. For ATmega168 / 328-baserede Arduinos kan de aktiveres på en hvilken som helst eller alle 20 af Arduinos signalstifter; på ATmega-baserede Arduinos kan de aktiveres på 24 stifter. De udløses ens ved RISING eller FALLING signal kanter så det er op til afbrydelseskoden at indstille de rigtige stifter til at modtage afbrydelser, at bestemme hvad der skete (hvilken stift? … steg signalet eller faldt?) og at håndtere det ordentligt.Desuden er pin-skift-afbrydelserne grupperet i 3 “porte” på MCUen, så der er kun 3 afbrydelsesvektorer (subrutiner) til hele kroppen af stifter. Dette gør jobbet med at løse handlingen ved en enkelt afbrydelse endnu mere kompliceret.

Dybest set er de eksterne afbrydelser ekstremt hurtige, da de alle er hardware-baserede Der er dog også afbrydelser med pin-skift, men de ser ud til at være meget langsommere, fordi de for det meste er softwarebaserede.

tl; dr: de 20 afbrydestifter sammen er meget langsommere. De 2 afbrydestifter er de hurtigste og mest effektive.


EDIT: Jeg kiggede lige på databladet, og der står, at en pin-skift-afbrydelse udløses for enhver af de valgte ben uden indikation af hvilken pin der er ændret (selvom den er opdelt i tre afbrydelsesvektorer).

  • For eksterne afbrydelser fortæller den dig pin 3 er netop ændret
  • For pin skift det “fortæller dig en pin ændret, som du overvågede!

Som du kan se, en afbrydelse af pin-skift tilføjer en masse overhead til ISR, som du skal håndtere ved at gemme tidligere tilstande og se om det er den pin, du er bekymret for. Det kan være fint for en søvntilstand, men det er bedre at bruge de eksterne afbrydelser.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *