image/svg+xml

Interrupciones

El ATmega328P tiene varios vectores de interrupci贸n. Existe una bandera de interrupciones global I del registro SREG, que habilita 1 o deshabilita 0 las interrupciones de forma global. Adem谩s de la bandera global l, se necesita habilitar la m谩scara asociada a cada interrupci贸n para que funcione la misma. Otra forma de activar/desactivar la bandera de interrupci贸n global, es con los m茅todos cli()/sei() respectivamente.

De forma autom谩tica, la bandera I, es desactivada cuando una interrupci贸n ocurre, luego, cuando la interrupci贸n es atendida (al ejecutar la operaci贸n RETI), vuelve a activarse I. Una buena pr谩ctica de programaci贸n al trabajar con interrupciones, es desactivarlas durante puntos cr铆ticos del c贸digo, para ser activadas posteriormente.

Interrupciones externas

El ATmega328P, cuenta con 2 vectores de interrupci贸n externos y se activan mediante una se帽al en los pines PD2 (INT0) y PD3 (INT1). Para controlar qu茅 activa la llamada a interrupciones en los pines, se utiliza el registro EICRA, donde ISC11, ISC10 est谩n asociados a INT1 y ISC01, ISC00 est谩n asociados a INT0.

ISC11/ISC01 ISC10/ISC00 Descripci贸n
0 0 Un nivel bajo en INT1/INT0 genera una llamada de interrupci贸n
0 1 Cualquier cambio de estado l贸gico en INT1/INT0 genera una llamada de interrupci贸n
1 0 Un flanco de bajada en INT1/INT0 genera una llamada de interrupci贸n
1 1 Un flanco de subida en INT1/INT0 genera una llamada de interrupci贸n

Por default, las interrupciones externas est谩n deshabilitadas. Para activarlas, se utilizan los bits 1 y 0 del registro EIMSK, para activar el INT1 e INT0 respectivamente.

Cuando sucede una interrupci贸n, autom谩ticamente su bandera asociada es activada INTF1 e INTF0 para INT1 e INT0 respectivamente. Estas se encuentran en el registro EIFR. Cuando la interrupci贸n es atendida (al ejecutar la operaci贸n RETI), vuelve a 0. La librer铆a avr/interrupt.h ejecuta RETI por debajo. Estas banderas sirven para conocer la fuente de la interrupci贸n.

Programaci贸n en C de interrupciones externas

Para utilizar las interrupciones externas del ATmega328P en lenguaje C, se puede seguir este procedimiento:

  1. Importar la librer铆a avr/interrupt.c
     #include<avr/interrupt.h>
    
  2. Definir la rutina de interrupci贸n ISR para el vector de interrupci贸n deseado INT0_vect/INT1_vect
     ISR (INT0_vect) {
         // C贸digo de rutina de interrupci贸n para INT0
     }
     ISR (INT1_vect) {
         // C贸digo de rutina de interrupci贸n para INT1
     }
    
  3. Configurar las interrupciones externas

    Ejemplo que habilita las interrupciones por INT0 por flanco de subida:

     int main(void)
     {
         cli(); // Deshabilitar interrupciones de forma global
         //otras configuraciones
         EICRA |= (1<<ISC01)|(1<<ISC00); // Interrupci贸n en flanco de subida para INT0
         EICRA |= (1<<ISC01)|(1<<ISC00); // Interrupci贸n en flanco de subida para INT0
         EIMSK |= (1<<INT0); // Habilitar interrupci贸n con INT0
         sei(); // Habilitar interrupciones de forma global
     }
    

Interrupci贸n por cambio de pin

Estas son otro tipo de interrupci贸n externa donde no se puede cambiar el tipo de se帽al de activaci贸n por otro que no sea el cambio l贸gico de un pin. El ATmega328P, permite seleccionar uno o varios pines de cada puerto para este prop贸sito.

Se activan o desactivan las interrupciones por cambio de pin de los pines asociados a los puertos PORTB, PORTC y PORTD con los pines PCIE0, PCIE1 y PCIE2 del registro PCICR respectivamente.

Cuando ocurre la interrupci贸n, se levantan y bajan las banderas PCIE0, PCIE1 y PCIE2, asociadas a los pines de los puertos PORTB, PORTC y PORTD respectivamente, de forma autom谩tica. Para pines dentro del mismo puerto, no hay banderas independientes.

Para configurar qu茅 pines causen la interrupci贸n, se utilizan los bits PCINT0-PCINT7 del registro PCMSK0 para habilitar o desactivar la interrupci贸n en los pines PB0-PB7 respectivamente. De igual manera los registros PCMSK1 y PCMSK2 est谩n asociados a los pines de los puertos PORTC y PORTD.

Programaci贸n en C de interrupciones por cambio de pin

  1. Importar la librer铆a avr/interrupt.c
     #include<avr/interrupt.h>
    
  2. Definir la rutina de interrupci贸n ISR para el vector de interrupci贸n deseado INT0_vect/INT1_vect

    Ejemplo de definiciones de rutina de interrupci贸n para PCINT1:

     ISR (PCINT1_vect) {
         // C贸digo de rutina de interrupci贸n para PCINT1
     }
    
  3. Configurar las interrupciones por cambio de pin

    Ejemplo que habilita las interrupciones por PCINT1:

     int main(void)
     {
         cli(); // Deshabilitar interrupciones de forma global
         //otras configuraciones
         PCICR |= (1<<PCIE1); // Habilitar interrupciones por cambio de pin en PORTC
         PCMSK1 |= (1<<PCINT8)|(1<<PCINT11) // Habilitar pines PCINT11 y PCINT8 para interrupci贸n
         sei(); // Habilitar interrupciones de forma global
     }