¿Por qué no funciona mi código de interrupción?

Antecedentes

Estoy tratando de escribir código para leer señales de un receptor RC de seis canales en un Arduino Mega 2560 . Actualmente conservo el código para leer un solo canal para facilitar la solución de problemas. El problema es que mi variable compartida no se actualiza, lo que me lleva a creer que mi interrupción La rutina de servicio no detecta ningún flanco ascendente.

Pensé que mi receptor estaba roto, así que lo probé usando la función estándar de interrupción de conexión de Arduino . Funcionó perfectamente, así que mi receptor está bien.

Usé Serial.print () para ver si mi variable de canal volátil se estaba actualizando (es decir, cambie su valor al valor de la marca del canal 1). No se estaba actualizando, por lo que mi ISR debe ser incorrecto. Puede encontrar el código original en la publicación del blog.

¿Qué ocurre? No tengo ideas.

 #include <PinChangeInt.h> //Pin assignment #define channel1PIN 10 //Bit flags #define Channel1FLAG 1 //Flag holder volatile uint8_t bFLAGUPDATESHARED; //Shared variables: Accessed by the interrupt service routine and read in "void loop". volatile uint16_t unCHANNEL1SHARED; //Start time variables: These are used to set the start time of the rising edge of //a pulse. They are only accessed by the ISR, and thus they are unsigned integers and //not volatiles. uint32_t ulCHANNEL1START; void setup() { Serial.begin(9600); Serial.print("RC Channel PWM Read Interrupt Test"); //PinChangInt library function. Used to set attach interrupts. PCintPort::attachInterrupt(channel1PIN, calcCHANNEL1, CHANGE); } void loop() { //In-loop variables to hold local copies of channel inputs. //This is static so it retains values between call loops. static uint16_t unCHANNEL1IN; //The in-loop copy of the bSHAREDFLAGUPDATE volatile flag holder static uint8_t bFLAGUPDATELOCAL; //Check to see if any channels have received signals. If so, copy //shared variables to local in loop variables. if (bFLAGUPDATESHARED) { //Switch off interrupts when I copy shared variables to local variables noInterrupts(); bFLAGUPDATELOCAL = bFLAGUPDATESHARED; if (bFLAGUPDATELOCAL & Channel1FLAG) { unCHANNEL1IN = unCHANNEL1SHARED; } bFLAGUPDATESHARED = 0; interrupts(); } Serial.println(unCHANNEL1IN); //Clear local update flags copy as all values have been copied to local variables bFLAGUPDATELOCAL = 0; } void calcCHANNEL1() { if (digitalRead(channel1PIN) == HIGH) { //If pin goes high, start timer and set ulCHANNEL1START to timer start ulCHANNEL1START = micros(); } else { //If it is not rising, it must be falling so set shared //variable to current time-start time unCHANNEL1SHARED = (uint16_t)(micros() - ulCHANNEL1START); //Tell that channel 1 has received a signal bFLAGUPDATESHARED |= Channel1FLAG; } }  

Comentarios

  • Intenta simplificar tu código. Haz que el ISR encienda un LED, por ejemplo. No ‘ veo nada intrínsecamente incorrecto.
  • Lo descubrí. Por alguna razón, solo funciona en los pines 10, 11 y 12. No obstante, ‘ no sé por qué. PinchangeInt debería funcionar en cualquier pin digital
  • ¿Pero estás usando el pin 10? De todos modos; me alegro de que lo hayas hecho funcionar.

Responder

Solo algunos puertos en el Atmega2560 admiten interrupciones de cambio de pin, específicamente los puertos B, E (bit 0), J (bits 0 a 6) y K.

Mirando el esquema de referencia que significa que estos pines en la placa son compatibles:

 Chip Name Pin Pin on board ----------------------- Port B PB0 - 19 - D53 (SS) PB1 - 20 - D52 (SCK) PB2 - 21 - D51 (MOSI) PB3 - 22 - D50 (MISO) PB4 - 23 - D10 PB5 - 24 - D11 PB6 - 25 - D12 PB7 - 26 - D13 Port E PE0 - 2 - D0 (RXD0) Port J PJ0 - 63 - D15 (RXD3) PJ1 - 64 - D14 (TXD3) PJ2 to PJ6 - not connected on board Port K PK0 - PK7 - (89 - 82) - A8 - A15 

Así puede ver que D10 a D12, que dice que funciona, están en esa lista. Otros aleatorios no lo estarían.


SoftwareSerial

Puede ver la confirmación en la página de SoftwareSerial donde dice:

No todos los pines de Mega y Mega 2560 admiten interrupciones de cambio, por lo que solo se puede usar lo siguiente para RX: 10, 11, 12, 13, 14, 15, 50, 51, 52, 53, A8 (62), A9 (63), A10 (64), A11 (65), A12 (66), A13 (67), A14 (68), A15 (69).

Esto se debe a que SoftwareSerial usa interrupciones de cambio de pin para detectar datos seriales entrantes y, por lo tanto, el descargo de responsabilidad en esa página sobre con qué pines funcionará. / p>


Pin-outs Atmega2560

Pin-outs Atmega2560


PinchangeInt debería funcionar en cualquier pin digital

Tenga en cuenta que el Atmega328P (como se usa en el Uno) tiene menos puertos, y todos están disponibles para interrupciones de cambio de pin en esa placa.

Comentarios

  • Esto puede ‘ t ser correcto. La página vinculada primero por OP afirma que los pines 2, 3, 18, 19, 20 y 21 se pueden usar para interrupciones. Estos se asignan a PE4, PE5, PD3, PD2, PD1 y PD0, de acuerdo con goo.gl/DvHEUA y goo.gl/xAwBGM Por mi parte, yo ‘ me preocupa más si se puede utilizar PORTC, como en ros_arduino_bridge: goo.gl/rq6yQO
  • La página vinculada se refiere a interrupciones externas , sin embargo, el OP está utilizando interrupciones de cambio de pin como se puede ver en #include <PinChangeInt.h>. Los pines de interrupción de cambio de pin son los que enumeré.
  • Ya veo. Tenía un indicio de que podría ser la distinción, pero asumí que todos los pines capaces de interrupciones externas también serían capaces de cambiar de pin, aunque no al revés.

Respuesta

En el ATmega1280 / 2560, solo los puertos B, J, F y K tienen capacidad de interrupción de cambio de pin. Estos se asignan aproximadamente a los pines 10 a 15, 50 a 53 y A6 a A15 (aunque parte del puerto J no está asignado a los pines de Arduino, por lo tanto, PCINT11 a PCINT15 no están disponibles en Arduino Mega / Mega 2560).

Deja una respuesta

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