Je cherche à utiliser un récepteur RC 7 canaux avec lArduino Uno R3. Dans la documentation, il y a des mentions dun maximum de 2 broches dinterruption, alors que sur certains autres blogs, jai vu des mentions dutiliser jusquà 20 broches comme interruptions, avec la bibliothèque PinChangeInt. Alors, combien dinterruptions lArduino peut-il gérer nativement? Et est-ce différent du nombre qui peut être géré avec un support logiciel tel que PinChangeInt?
Réponse
Il existe deux types de » interruptions de type « changement de broche ». Les interruptions externes, dont il y en a deux sur lUno. Ils sont appelés 0 et 1, mais ils se réfèrent aux broches numériques 2 et 3 de la carte. Ceux-ci peuvent être configurés pour détecter la hausse, la baisse, le changement (hausse ou baisse) ou LOW.
En plus de cela, il y a des interruptions de « changement de broche », qui détectent un changement de létat de broche dans lune des 20 broches (A0 à A5 et D0 à D13). Ces interruptions de changement de broche sont également basées sur le matériel donc, en elles-mêmes, seront aussi rapides que les interruptions externes.
Les deux types sont légèrement compliqués à utiliser au niveau du registre, mais lEDI standard inclut attachInterrupt (n) et detachInterrupt (n) qui simplifie linterface avec les interruptions externes. Vous pouvez également utiliser la Bibliothèque de changement de broche pour simplifier les interruptions de changement de broche.
Cependant, en évitant la bibliothèque pendant une minute, nous peut établir que les interruptions de changement de broche peuvent être aussi rapides, voire plus rapides, que les interruptions externes. Dune part, bien que les interruptions de changement de broche fonctionnent sur des lots de broches, vous navez pas à activer lensemble du lot. Par exemple, si vous voulez détecter des changements sur la broche D4, cela suffira:
Exemple 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 () { }
Mes tests indiquent quil a fallu 1,6 µs pour le test » « pin (pin 5) pour réagir à un changement sur la pin dinterruption (pin 4).
Maintenant, si vous adoptez lapproche simple (paresseuse?) et utilisez attachInterrupt (), vous trouverez le les résultats sont plus lents, pas plus rapides.
Exemple de code:
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 () { }
Cela prend 3,7 µs pour changer la broche de test, bien plus que 1,6 µs ci-dessus. Pourquoi? Parce que le code que le compilateur doit générer pour le gestionnaire dinterruption « générique » doit enregistrer tous les registres imaginables (les pousser) entrée dans lISR, puis restaurez-les (faites-les apparaître) avant de revenir. De plus, il y a la surcharge dun autre appel de fonction.
Maintenant, nous pouvons contourner cela en évitant attachInterrupt () et en le faisant nous-mêmes:
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 () { }
Cest le plus rapide de tous à 1,52 µs – il semble quun cycle dhorloge a été sauvegardé quelque part.
Il y a une mise en garde cependant, pour les interruptions de changement de broche. Ils sont groupés, donc si vous voulez avoir des interruptions sur beaucoup de broches, vous devez tester à lintérieur de linterruption laquelle a changé . Vous pouvez le faire en enregistrant létat précédent de la broche et en le comparant au nouvel état de la broche. Ce nest pas forcément particulièrement lent, mais plus vous devez vérifier de broches, plus ce sera lent.
Les lots sont:
- A0 à A5
- D0 à D7
- D8 à D13
Si vous voulez juste quelques broches dinterruption supplémentaires, vous pouvez éviter tout test en choisissant simplement dutiliser des broches de différentes lots (par exemple D4 et D8).
Plus de détails sur http://www.gammon.com.au/interrupts
Réponse
Il existe deux types dinterruptions. Ce que le Arduino Playground a dit:
Le processeur au cœur de tout Arduino a deux types dinterruptions: «externe» et «changement de broche». Il ny a que deux broches dinterruption externes sur lATmega168 / 328 (cest-à-dire dans lArduino Uno / Nano / Duemilanove), INT0 et INT1, et elles sont mappées sur les broches Arduino 2 et 3. Ces interruptions peuvent être configurées pour se déclencher sur RISING ou FALLING fronts du signal, ou à un niveau bas. Les déclencheurs sont interprétés par le matériel et linterruption est très rapide. LArduino Mega a quelques broches dinterruption externes supplémentaires disponibles.
Dun autre côté, les interruptions de changement de broche peuvent être activées sur beaucoup plus de broches. Pour les Arduinos basés sur ATmega168 / 328, ils peuvent être activés sur lune ou sur les 20 broches de signal de lArduino; sur les Arduinos basés sur ATmega, ils peuvent être activés sur 24 broches. cest donc au code dinterruption de définir les broches appropriées pour recevoir les interruptions, de déterminer ce qui sest passé (quelle broche? … le signal a-t-il augmenté ou diminué?), et de le gérer correctement.De plus, les interruptions de changement de broche sont regroupées en 3 «ports» sur le MCU, il ny a donc que 3 vecteurs dinterruption (sous-programmes) pour tout le corps des broches. Cela rend le travail de résolution de laction sur une seule interruption encore plus compliqué.
Fondamentalement, les interruptions externes sont extrêmement rapides car elles « sont toutes basées sur du matériel . Cependant, il y a aussi les interruptions de changement de broche, mais celles-ci semblent être beaucoup plus lentes car elles sont principalement basées sur des logiciels.
tl; dr: les 20 broches dinterruption ensemble sont beaucoup plus lentes. Les 2 broches dinterruption sont les plus rapides et les plus efficaces.
EDIT: Je viens de regarder la fiche technique et il est dit quune interruption de changement de broche est déclenchée pour nimporte quel des broches sélectionnées sans indication de quelle broche a changé (bien quelle soit divisée en trois vecteurs dinterruption).
- Pour les interruptions externes, cela vous indiquera que la broche 3 vient de changer
- Pour la modification de la broche, cela vous dira une broche modifiée que vous surveilliez!
Comme vous pouvez le voir, une Linterruption de changement de broche ajoute beaucoup de frais généraux dans lISR que vous devez gérer en stockant les états précédents et en voyant si cest la broche qui vous inquiète. Cela peut convenir pour un état de veille, mais il vaut mieux utiliser les interruptions externes.