¿Cuántos pines de interrupción puede manejar un Uno?

Estoy pensando en usar un receptor RC de 7 canales con el Arduino Uno R3. En la documentación, hay menciones de un máximo de 2 pines de interrupción, mientras que en algunos otros blogs he visto menciones de usar hasta 20 pines como interrupciones, con la biblioteca PinChangeInt. Entonces, ¿cuántas interrupciones puede manejar Arduino de forma nativa? ¿Y esto es diferente de cuántos se pueden manejar con soporte de software como PinChangeInt?

Respuesta

Hay dos tipos de » tipo cambio de pin «interrupciones. Las interrupciones externas, de las cuales hay dos en el Uno. Se denominan 0 y 1, sin embargo se refieren a los pines digitales 2 y 3 de la placa. Estos se pueden configurar para detectar subidas, bajadas, cambios (subiendo o bajando) o BAJAS.

Además de eso, hay interrupciones de «cambio de pin», que detectan un cambio en el estado del pin en cualquiera de los 20 pines (A0 a A5 y D0 a D13). Estas interrupciones de cambio de pin también están basadas en hardware por lo que, en sí mismas, serán tan rápidas como las interrupciones externas.

Ambos tipos son un poco complicados de usar a nivel de registro, pero el IDE estándar incluye attachInterrupt (n) y detachInterrupt (n) que simplifican la interfaz a interrupciones externas. También puede utilizar la Biblioteca de cambio de pin para simplificar las interrupciones de cambio de pin.

Sin embargo, alejándose de la biblioteca por un minuto, puede establecer que las interrupciones de cambio de pin pueden ser tan rápidas, o más rápidas, que las interrupciones externas. Por un lado, aunque las interrupciones de cambio de pines funcionan en lotes de pines, no tiene que habilitar el lote completo. Por ejemplo, si desea detectar cambios en el pin D4, esto será suficiente:

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

Mi prueba indica que se necesitaron 1,6 µs para la «prueba «pin (pin 5) para reaccionar a un cambio en el pin de interrupción (pin 4).


Ahora, si toma el enfoque simple (¿perezoso?) y usa attachInterrupt () encontrará el los resultados son más lentos, no más rápidos.

Código de ejemplo:

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

Esto toma 3.7 µs para cambiar el pin de prueba, mucho más que los 1.6 µs anteriores. ¿Por qué? Porque el código que el compilador tiene que generar para el manejador de interrupciones «genérico» tiene que guardar todos los registros imaginables (presionarlos) en entrada al ISR, y luego restaurarlos (abrirlos) antes de regresar. Además, existe la sobrecarga de otra llamada de función.


Ahora podemos solucionarlo evitando attachInterrupt () y haciéndolo nosotros mismos:

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

Ese es el más rápido de todos con 1,52 µs; parece que un ciclo de reloj se guardó en alguna parte.


Sin embargo, hay una advertencia para las interrupciones de cambio de pin. Están agrupados, por lo que si desea tener interrupciones en muchos pines, debe probar dentro de la interrupción cuál cambió . Puede hacerlo guardando el estado del pin anterior y comparándolo con el nuevo estado del pin. Esto no es necesariamente particularmente lento, pero cuantos más pines necesite verificar, más lento será.

Los lotes son:

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

Si solo desea un par de pines de interrupción más, puede evitar cualquier prueba eligiendo usar pines de diferentes lotes (por ejemplo, D4 y D8).


Más detalles en http://www.gammon.com.au/interrupts

Respuesta

Hay dos tipos de interrupciones. Lo que dice Arduino Playground :

El procesador en el corazón de cualquier Arduino tiene dos tipos diferentes de interrupciones: “externa” y “cambio de pin”. Solo hay dos pines de interrupción externos en el ATmega168 / 328 (es decir, en el Arduino Uno / Nano / Duemilanove), INT0 e INT1, y están asignados a los pines 2 y 3 de Arduino. Estas interrupciones se pueden configurar para disparar en RISING o FALLING señal de flancos, o en nivel bajo. Los disparadores son interpretados por hardware y la interrupción es muy rápida. El Arduino Mega tiene algunos pines de interrupción externos más disponibles.

Por otro lado, las interrupciones de cambio de pines se pueden habilitar en muchos más pines. Para los Arduinos basados en ATmega168 / 328, se pueden habilitar en cualquiera o en todos los 20 pines de señal del Arduino; en los Arduinos basados en ATmega se pueden habilitar en 24 pines. Se activan por igual en los bordes de señal ASCENDENTE o DESCENDENTE, por lo que depende del código de interrupción establecer los pines adecuados para recibir interrupciones, determinar qué sucedió (¿cuál pin? … ¿la señal subió o bajó?) y manejarlo correctamente.Además, las interrupciones de cambio de pin se agrupan en 3 “puertos” en la MCU, por lo que solo hay 3 vectores de interrupción (subrutinas) para todo el cuerpo de pines. Esto hace que el trabajo de resolver la acción en una sola interrupción sea aún más complicado.

Básicamente, las interrupciones externas son extremadamente rápidas ya que «están todas basadas en hardware . Sin embargo, también existen las interrupciones de cambio de pin, pero parecen ser mucho más lentas porque en su mayoría están basadas en software.

tl; dr: los 20 pines de interrupción juntos son mucho más lentos. Los 2 pines de interrupción son los más rápidos y eficientes.


EDIT: Acabo de mirar la hoja de datos y dice que se activa una interrupción de cambio de pin para cualquiera de los pines seleccionados sin indicación de qué pin ha cambiado (aunque está dividido en tres vectores de interrupción).

  • Para interrupciones externas, «le dirá pin 3 acaba de cambiar
  • ¡Para cambiar el pin, le dirá un pin cambiado que estaba monitoreando!

Como puede ver, un La interrupción de cambio de pin agrega mucha sobrecarga al ISR que tiene que manejar almacenando estados anteriores y viendo si es el pin que le preocupa. Puede que esté bien para un estado de suspensión, pero es mejor usar las interrupciones externas.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *