AVR Interrumpir "Interferencia"

2

Actualmente estoy trabajando para recibir señales de un control remoto RC. He usado los pines A8 a A15 en mi placa Arduino Mega.

Los puertos y las interrupciones se configuran con la ayuda de este código:

DDRK = 0b00000000;      // Set port A8-A15 to input
PCICR |= (1<<PCIE2);    // Enable interrupt on PCMSK2 containing receiver pins
PORTK = 0b11111111;     
PCMSK2 = 0b11111111;    // Enable all interrupts on receiver pins

Luego, he configurado una interrupción que encuentra el pin que interrumpió y cronometra el pulso.

// Interrupts whenever a signal is received.
ISR(PCINT2_vect) {  
static uint32_t startTime[8];
static uint8_t lastState;
uint8_t mask;
uint8_t changedPin;

mask = PINK ^ lastState;
lastState = PINK;

if(mask & (1 << 0)) changedPin = 0;
if(mask & (1 << 1)) changedPin = 1;
if(mask & (1 << 2)) changedPin = 2;
if(mask & (1 << 3)) changedPin = 3;
if(mask & (1 << 4)) changedPin = 4;
if(mask & (1 << 5)) changedPin = 5;
if(mask & (1 << 6)) changedPin = 6;
if(mask & (1 << 7)) changedPin = 7; 

// Check if the changed pin is high
if(lastState & (1 << changedPin)) {
    // Start counting if it is
    startTime[changedPin] = micros();
} else {
    // Save if it has gone down again
    rcValue[changedPin] = micros() - startTime[changedPin];
}
}

Esto realmente funciona realmente bien, excepto por la parte cuando conecto un total de 4 o más pines.

Ejemplo:
A8: trabajando bien
A8 a A9: trabajando bien
A8 a A10: trabajando bien
A8 a A11: A9 y A11 funcionan bien, A10 no registra ninguna entrada, A8 salta de valores normales (1000-2000) a valores que son aproximadamente 17000.

Mi conjetura es que puede tener algo que ver con el enmascaramiento y la detección del pin desde allí, pero he buscado en todo el Internet todopoderoso y no me ha dado una respuesta clara.

    
pregunta Boren

1 respuesta

3

Veo tres problemas con tu código:

Volatilidad y alcance variables

Las variables a continuación se corromperán debido a que las define solo en el ISR. Pero claramente desea conservar su valor entre interrupciones. Cree las siguientes variables volatile y defíngalas globalmente, no en el ISR:

  • uint8_t lastState;
  • uint32_t startTime[8];

Tiempo preciso

Ejecute el código crítico de tiempo tan pronto como sea posible después de que ocurrió la interrupción. Lea micros() en una variable temporal al inicio del ISR para que el código condicional no influya en el tiempo. Luego, asigne la variable temporal a startTime[changedPin] una vez que su código haya decidido dónde colocarlo.

Bordes simultáneos

Tenga en cuenta que su código no hace frente a los cambios de pin simultáneos, el pin más alto tendrá prioridad. Luego, cuando esos pines no tengan bordes descendentes simultáneos, se dañará la sincronización del pin con el número más bajo.

    
respondido por el jippie

Lea otras preguntas en las etiquetas