¿Determinar qué pin desencadenó una interrupción PCINTn?

9

Tengo razón al pensar que si tiene dos pines que causan la misma interrupción de AVR PCINT, (p. ej., PCINT0 vector causado por pines PCINT0 o PCINT1: creo que la superposición de nombres de vectores y pines es confuso) la única forma de determinar qué pin (es) causó la interrupción es registrar su estado después de cada interrupción y comparar los valores actuales y anteriores de todos los pines que están habilitados en PCMSKn?

    
pregunta Tom Davies

1 respuesta

10
  

Creo que la superposición de nombres de vectores y pines es confusa

¡Lo es!

La razón por la que hay 8 pines externos diferentes para un vector de interrupción es para facilitar el diseño de la PCB o usar un pin diferente si hay un conflicto con otra función de pines.

  

¿Tengo razón al pensar ... la única forma de determinar qué pin (s)   causado la interrupción es registrar su estado después de cada interrupción y   Compare los valores anteriores y actuales de todos los pines que están   habilitado en PCMSKn?

Mucho, digamos que solo te preocupa PB0 (PCINT0) y PB1 (PCINT1). Por lo tanto, la máscara de activación de cambio de pin PCMSK0 se establecería en 0x03.

// External Interrupt Setup
...

volatile u_int8 previousPins = 0; 
volatile u_int8 pins = 0; 

ISR(SIG_PIN_CHANGE0)
{
    previousPins = pins; // Save the previous state so you can tell what changed
    pins = (PINB & 0x03); // set pins to the value of PB0 and PB1
    ...
}

Entonces, si pins es 0x01, sabes que era PB0 ... Y si necesitas saber qué ha cambiado, necesitas compararlo con previousPins , casi exactamente lo que pensaste.

En algunos casos, tenga en cuenta que pins puede no ser preciso si el pin cambia de estado desde la interrupción pero antes de pins = (PINB & 0x03) .

Otra opción sería usar vectores de interrupción separados con un pin de cada vector para que sepa cuál ha cambiado. Nuevamente, esto también tiene algunos problemas, como la prioridad de interrupción y una vez que la CPU ingresa al ISR, el bit de habilitación de interrupción global I-bit en SREG se borrará para que todas las demás interrupciones se deshabiliten, aunque puede configurarlo dentro de la interrupción Si lo desea, sería una interrupción anidada.

Para obtener más información, consulte la nota de aplicación de Atmel Uso de interrupciones externas para dispositivos megaAVR.

Actualizar

Aquí hay un ejemplo de código completo que acabo de encontrar aquí .

#include <avr/io.h>
#include <stdint.h>            // has to be added to use uint8_t
#include <avr/interrupt.h>    // Needed to use interrupts
volatile uint8_t portbhistory = 0xFF;     // default is high because the pull-up

int main(void)
{
    DDRB &= ~((1 << DDB0) | (1 << DDB1) | (1 << DDB2)); // Clear the PB0, PB1, PB2 pin
    // PB0,PB1,PB2 (PCINT0, PCINT1, PCINT2 pin) are now inputs

    PORTB |= ((1 << PORTB0) | (1 << PORTB1) | (1 << PORTB2)); // turn On the Pull-up
    // PB0, PB1 and PB2 are now inputs with pull-up enabled

    PCICR |= (1 << PCIE0);     // set PCIE0 to enable PCMSK0 scan
    PCMSK0 |= (1 << PCINT0);   // set PCINT0 to trigger an interrupt on state change 

    sei();                     // turn on interrupts

    while(1)
    {
    /*main program loop here */
    }
}

ISR (PCINT0_vect)
{
    uint8_t changedbits;

    changedbits = PINB ^ portbhistory;
    portbhistory = PINB;

    if(changedbits & (1 << PB0))
    {
    /* PCINT0 changed */
    }

    if(changedbits & (1 << PB1))
    {
    /* PCINT1 changed */
    }

    if(changedbits & (1 << PB2))
    {
    /* PCINT2 changed */
    }
}
    
respondido por el Garrett Fogerlie

Lea otras preguntas en las etiquetas

Comentarios Recientes

Anteriormente, se esperaba que las interrupciones (impulsadas por el nivel de interrupción a uno o más subprocesos) activaran pcom (2), que activó pcom (2), llamando a pcom (1), rsp , Etcétera. SNA utiliza un reloj basado en interrupciones que sabe cuándo y por qué se debe activar una interrupción y la causa. Si una interrupción no activó una interrupción PCINTn, no habría tiempo suficiente para identificar la variable que la causó. El primer prototipo: FAQQ: ¿BTD se ajustará a nuestro FPGA, coincidirá... Lees verder