Quanti pin di interrupt può gestire uno Uno?

Sto cercando di utilizzare un ricevitore RC a 7 canali con Arduino Uno R3. Nella documentazione, ci sono menzioni di un massimo di 2 pin di interrupt, mentre su alcuni altri blog ho visto menzionare luso di un massimo di 20 pin come interrupt, con la libreria PinChangeInt. Quindi, quanti interrupt può gestire in modo nativo Arduino? Ed è diverso da quanti possono essere gestiti con il supporto software come PinChangeInt?

Risposta

Ci sono due tipi di ” pin change “interrompe il tipo. Le interruzioni esterne, di cui due sullUno. Si chiamano 0 e 1, tuttavia si riferiscono ai pin digitali 2 e 3 sulla scheda. Questi possono essere configurati per rilevare aumento, diminuzione, cambiamento (aumento o calo) o BASSO.

In aggiunta a ciò ci sono interrupt “cambio pin”, che rilevano un cambiamento nello stato del pin in uno qualsiasi dei 20 pin (da A0 ad A5 e da D0 a D13). Questi interrupt di cambio pin sono anche basati su hardware quindi, di per sé, saranno veloci quanto gli interrupt esterni.

Entrambi i tipi sono un po complicati da usare a livello di registro, ma lIDE standard include attachInterrupt (n) e detachInterrupt (n) che semplifica linterfaccia agli interrupt esterni. Puoi anche utilizzare la Pin Change Library per semplificare le interruzioni di cambio pin.

Tuttavia, allontanandoci dalla libreria per un minuto, può stabilire che gli interrupt di cambio pin possono essere veloci, o più veloci, degli interrupt esterni. Per prima cosa, sebbene gli interrupt di cambio pin funzionino su batch di pin, non è necessario abilitare lintero batch. Ad esempio, se si desidera rilevare le modifiche sul pin D4, questo sarà sufficiente:

Esempio sketch:

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

Il mio test indica che ci sono voluti 1,6 µs per il test ” “pin (pin 5) per reagire a una modifica sul pin di interrupt (pin 4).


Ora se adotti lapproccio semplice (pigro?) e usi attachInterrupt () troverai il i risultati sono più lenti, non più veloci.

Codice di esempio:

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

Questo richiede 3,7 µs per cambiare il pin di test, molto di più degli 1,6 µs sopra. Perché? Poiché il codice che il compilatore deve generare per il gestore di interrupt “generico” deve salvare ogni registro immaginabile (spingerli) su ingresso allISR, quindi ripristinarli (inserirli) prima di tornare. Inoltre cè il sovraccarico di unaltra chiamata di funzione.


Ora possiamo aggirare il problema evitando attachInterrupt () e facendolo da soli:

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

Questo è il più veloce di tutti a 1,52 µs – sembra che un ciclo di clock sia stato salvato da qualche parte.


Cè però un avvertimento, per gli interrupt di cambio pin. Sono raggruppati, quindi se vuoi avere interruzioni su molti pin, devi testare allinterno dellinterrupt che è stato modificato . Puoi farlo salvando lo stato del pin precedente e confrontandolo con il nuovo stato del pin. Questo non è necessariamente particolarmente lento, ma più pin devi controllare, più sarà lento.

I batch sono:

  • Da A0 ad A5
  • Da D0 a D7
  • Da D8 a D13

Se vuoi solo un altro paio di pin di interrupt, potresti evitare qualsiasi test semplicemente scegliendo di usare pin di diversi batch (ad es. D4 e D8).


Maggiori dettagli su http://www.gammon.com.au/interrupts

Risposta

Esistono due tipi di interruzioni. Cosa ha detto Arduino Playground :

Il processore nel cuore di qualsiasi Arduino ha due diversi tipi di interrupt: “esterno” e “cambio pin”. Ci sono solo due pin di interrupt esterni sullATmega168 / 328 (cioè, in Arduino Uno / Nano / Duemilanove), INT0 e INT1, e sono mappati sui pin 2 e 3 di Arduino. Questi interrupt possono essere impostati per attivarsi su RISING o FALLING sui bordi del segnale o su un livello basso. I trigger vengono interpretati dallhardware e linterrupt è molto veloce. Arduino Mega ha altri pin di interrupt esterni disponibili.

Daltra parte gli interrupt di cambio pin possono essere abilitati su molti più pin. Per gli Arduino basati su ATmega168 / 328, possono essere abilitati su uno o tutti i 20 pin di segnale di Arduino; sugli Arduino basati su ATmega possono essere abilitati su 24 pin. Sono attivati allo stesso modo sui bordi del segnale SALITA o CADUTA, quindi spetta al codice di interrupt impostare i pin corretti per ricevere gli interrupt, determinare cosa è successo (quale pin? … il segnale è salito o è diminuito?) e gestirlo correttamente.Inoltre, gli interrupt di cambio pin sono raggruppati in 3 “porte” sullMCU, quindi ci sono solo 3 vettori di interrupt (subroutine) per lintero corpo dei pin. Questo rende ancora più complicato il compito di risolvere lazione su un singolo interrupt.

Fondamentalmente, gli interrupt esterni sono estremamente veloci poiché “sono tutti basati su hardware Tuttavia, ci sono anche gli interrupt di cambio pin, ma quelli sembrano essere molto più lenti perché sono principalmente basati su software.

tl; dr: i 20 pin di interrupt insieme sono molto più lenti. I 2 pin di interrupt sono i più veloci ed efficienti.


EDIT: Ho appena guardato il foglio dati e dice che viene attivato un interrupt di cambio pin per qualsiasi dei pin selezionati senza indicazione di quale pin è cambiato (sebbene sia diviso in tre vettori di interrupt).

  • Per gli interrupt esterni, ti dirà che pin 3 è appena cambiato
  • Per cambiare il pin “ti dirò un pin cambiato che stavi monitorando!

Come puoi vedere, un pin change interrupt aggiunge un sacco di overhead allISR che devi gestire memorizzando gli stati precedenti e vedendo se è il pin di cui sei preoccupato. Potrebbe andare bene per uno stato di sospensione, ma è meglio usare gli interrupt esterni.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *