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:
- Importar la librer铆a
avr/interrupt.c
#include<avr/interrupt.h>
- Definir la rutina de interrupci贸n
ISR
para el vector de interrupci贸n deseadoINT0_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 }
-
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
- Importar la librer铆a
avr/interrupt.c
#include<avr/interrupt.h>
-
Definir la rutina de interrupci贸n
ISR
para el vector de interrupci贸n deseadoINT0_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 }
-
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 }