Capítulo 2.
Puertos de Entrada/Salida
2.1. Pines de Entrada/Salida del ATmega328P
Figura 1 Encapsulado PDIP de 28 pines del microcontrolador ATmega328P [2]
Fuente: Microchip Technology Inc., "ATmega328P Datasheet", Rev. 7810D–AVR–01/15, 2015.
2.2. Registros de Manejo de los Puertos
• DDRx (Data Direction Register): Define la dirección de cada pin: entrada (0) o salida (1).
• PORTx: Establece el nivel lógico alto (1) o bajo (0) en los pines configurados como salida. En
los pines de entrada, este registro participa en la habilitación de la resistencia de pull-up interna.
• PINx: Permite leer el estado lógico actual de un pin configurado como entrada.
La letra x en el nombre de estos registros identifica el puerto correspondiente (B, C o D). La Tabla
1 resume el comportamiento del pin de entrada/salida Pxn en función de la configuración de los bits
DDxn, PORTxn y del bit PUD (Pull-up Disable), ubicado en el registro MCUCR. La letra n en la
notación del pin y de los bits de los registros indica el número de bit dentro del puerto: de 0 a 7 para
los puertos B y D, y de 0 a 6 para el puerto C. El bit DDxn forma parte del registro DDRx.
Tabla 1 Configuración del pin de entrada/salida Pxn
DDxn/PORTxn/PUD E/S Pull-up Comentario
0 0 X Entrada No Estado de alta impedancia (Hi-Z).
Pxn proporcionará corriente si se conecta a tierra
0 1 0 Entrada Sí
externamente.
0 1 1 Entrada No Estado de alta impedancia (Hi-Z).
1 0 X Salida No Salida en nivel bajo (sink).
1 1 X Salida No Salida en nivel alto (source).
Fuente: Microchip Technology Inc., "ATmega328P Datasheet", Rev. 7810D–AVR–01/15, 2015.
1
2.3. Circuito de una Línea de Entrada/Salida
Figura 2 Circuito de una línea de entrada/salida [2]
Fuente: Microchip Technology Inc., "ATmega328P Datasheet", Rev. 7810D–AVR–01/15, 2015.
Tabla 2 Señales del diagrama eléctrico de una línea de entrada/salida
Símbolo Significado
WDx Escritura en el registro DDRx
RDx Lectura del registro DDRx
WRx Escritura en el registro PORTx
RRx Lectura del registro PORTx
RPx Lectura del estado del pin (PINx)
WPx Escritura en el registro del pin (PINx)
PUD Deshabilitación de la resistencia de pull-up (en el registro MCUCR)
SLEEP Control de modo sleep (desactiva el pin en modo Sleep)
CLKI/O Reloj para la sincronización de entrada/salida (I/O Clock)
Fuente: Microchip Technology Inc., "ATmega328P Datasheet", Rev. 7810D–AVR–01/15, 2015.
2
Figura 3 Operación de escritura en un pin de salida
3
Figura 4 Operación de lectura de un pin de entrada
4
2.4. Rebote Mecánico en Pulsadores y Procedimiento Antirrebote
Ejemplo 1. Determinación del valor inmediato en el procedimiento antirrebote
1. Planteamiento del problema
En el siguiente procedimiento, se desea determinar el valor que debe cargarse en el registro R18
(representado por la constante simbólica W) en la instrucción LDI R18, W (línea 42), de modo que
el procedimiento en lenguaje ensamblador denominado RETARDO genere un retardo de 20
milisegundos. El programa se ejecuta en una tarjeta Arduino Uno basada en el microcontrolador
ATmega328P, el cual opera con una frecuencia de reloj de 16 MHz.
39 RETARDO:
40 PUSH R18
41 PUSH R16
42 LDI R18, W
43 BUCLE_EXTERNO:
44 LDI R16, 255
45 BUCLE_INTERNO:
46 NOP
47 NOP
48 DEC R16
49 BRNE BUCLE_INTERNO
50 DEC R18
51 BRNE BUCLE_EXTERNO
52 POP R16
53 POP R18
54 RET
2. Datos necesarios para realizar el cálculo
• Frecuencia del reloj del sistema: fCPU = 16 MHz
• Período de un ciclo de reloj: T = 1 / fCPU = 1 / (16 ×106) = 62.5 ns
• Tiempo total deseado del procedimiento: ttotal = 20 ms
• Instrucciones y su duración en ciclos de reloj (según hoja de datos del ATmega328P):
PUSH, POP: 2 ciclos
LDI: 1 ciclo
NOP: 1 ciclo
DEC: 1 ciclo
BRNE: 2 ciclos si se realiza el salto, 1 si no se realiza
RET: 4 ciclos
3. Desarrollo del cálculo
Se parte del análisis del procedimiento, el cual tiene dos bucles anidados: un bucle interno que se
ejecuta 255 veces por cada iteración del bucle externo, y un bucle externo que se ejecuta W veces.
Instrucciones fuera de los bucles (se ejecutan solo una vez):
• Línea 40: PUSH R18 → 2 ciclos
• Línea 41: PUSH R16 → 2 ciclos
• Línea 42: LDI R18, W → 1 ciclo
5
• Línea 52: POP R16 → 2 ciclos
• Línea 53: POP R18 → 2 ciclos
• Línea 54: RET → 4 ciclos
• Total de ciclos fuera de los bucles: 2 + 2 + 1 + 2 + 2 + 4 = 13 ciclos
Iteración del bucle interno (líneas 45 a 49)
Se ejecuta 255 veces por cada iteración externa:
• Línea 46: NOP → 1 ciclo
• Línea 47: NOP → 1 ciclo
• Línea 48: DEC R16 → 1 ciclo
• Línea 49: BRNE BUCLE_INTERNO: 254 veces con salto (2 ciclos), 1 vez sin salto (1 ciclo)
Total por 255 iteraciones:
• Para 254 iteraciones: 254 × (1+1+1+2) = 254 × 5 = 1270 ciclos
• Última iteración: 1+1+1+1 = 4 ciclos
• Total de ciclos en el bucle interno: 1270 + 4 = 1274 ciclos
Iteración del bucle externo (líneas 43 a 51):
• Línea 44: LDI R16, 255 → 1 ciclo
• Bucle interno → 1274 ciclos
• Línea 50: DEC R18 → 1 ciclo
• Línea 51: BRNE BUCLE_EXTERNO: 2 ciclos cuando se realiza el salto (para W – 1 veces), 1
ciclo al finalizar (última vez)
Entonces, para W – 1 iteraciones del bucle externo:
• Por iteración: 1 + 1274 + 1 + 2 = 1278 ciclos
• Total: (W−1) × 1278
Última iteración (BRNE no se realiza el salto):
• Total: 1 + 1274 + 1 + 1 = 1277 ciclos
Total de ciclos del procedimiento:
Ctotal = 13 + (W−1) × 1278 + 1277
Ctotal =13 + 1278W – 1278 + 1277 = 1278W + 12
Se desea que el procedimiento dure 20 ms, por lo tanto: ttotal = Ctotal × 62.5 ns = 20 ms
Despejando:
1278W + 12 = (20×10−3) / ( 62.5×10−9) = 320000 ciclos
1278W = 319988 ⇒ W = 319988/1278 ≈ 250.27
4. Respuesta
Para que el procedimiento RETARDO tenga una duración de 20 milisegundos, el valor de W debe
ser igual a 251.
6
Ejemplo 2. Conmutación de LEDs mediante pulsadores utilizando el
microcontrolador ATmega328P en lenguaje ensamblador
1. Planteamiento del ejercicio
En el presente ejercicio se plantea el desarrollo de un programa en lenguaje ensamblador para el
microcontrolador ATmega328P implementado en la tarjeta Arduino Uno, utilizando como entorno
de desarrollo Microchip Studio. El sistema propuesto consiste en la interacción entre cuatro
pulsadores conectados al puerto D (PD0–PD3) y cuatro LEDs conectados al puerto B (PB0–PB3)
del ATmega328P (ver Figura 5). La lógica del programa exige que cada vez que se presione un
pulsador, el LED asociado conmute su estado, es decir, si estaba encendido se apague y viceversa.
Figura 5 Esquema para encendido y apagado de LEDs usando pulsadores
Programa 1 Programa en lenguaje ensamblador que cambia el estado del LED cada vez que se
activa el pulsador correspondiente
1 .INCLUDE "M328PDEF.INC"
2 LDI R16, HIGH(RAMEND) ; Inicializar parte alta de la pila
3 OUT SPH, R16 ; Cargar parte alta del stack pointer
4 LDI R16, LOW(RAMEND) ; Inicializar parte baja de la pila
5 OUT SPL, R16 ; Cargar parte baja del stack pointer
6 IN R20,MCUCR
7 ANDI R20,0B11101111
8 OUT MCUCR,R20
9 IN R16, DDRB
10 ORI R16, 0B00001111
11 OUT DDRB, R16 ; Configurar PB0-PB3 como salidas digitales para LEDs
12 IN R16, DDRD
13 ANDI R16, 0B11110000
14 OUT DDRD, R16 ; Configurar PD0-PD3 como entradas para pulsadores
15 IN R16, PORTB
16 ORI R16, 0B00001111
17 OUT PORTB, R16
18 IN R16, PORTD
19 ORI R16, 0B00001111
20 OUT PORTD, R16 ; Activar resistencias pull-up en PD0-PD3
21 ESPERAR_FLANCO_BAJADA:
22 IN R18, PIND
23 ANDI R18, 0X0F ; Leer el estado de los pulsadores (PD0-PD3)
24 CPI R18, 0X0F
25 BREQ ESPERAR_FLANCO_BAJADA ; Esperar hasta que se detecte flanco de bajada
26 RCALL RETARDO ; Llamar a rutina antirrebote (retardo)
27 IN R17, PORTB ; Leer el estado actual de los LEDs
7
28 LDI R16, 0B00001111 ; Preparar máscara para trabajar con PB0-PB3
29 EOR R16, R18 ; Determinar qué LEDs cambiar según pulsadores
30 EOR R17, R16 ; Cambiar estado del LED correspondiente
31 ESPERAR_FLANCO_SUBIDA:
32 IN R18, PIND
33 ANDI R18, 0X0F
34 CPI R18, 0X0F
35 BRNE ESPERAR_FLANCO_SUBIDA ; Esperar flanco de subida (liberación del pulsador)
36 RCALL RETARDO ; Llamar a rutina antirrebote (retardo)
37 OUT PORTB, R17 ; Actualizar salida de LEDs con nuevo estado
38 RJMP ESPERAR_FLANCO_BAJADA ; Repetir la detección continuamente
39 RETARDO:
40 PUSH R18 ; Guardar registros usados en la pila
41 PUSH R16
42 LDI R18, 251 ; Cargar contador externo para retardo
43 BUCLE_EXTERNO:
44 LDI R16, 255 ; Cargar contador interno para retardo
45 BUCLE_INTERNO:
46 NOP
47 NOP
48 DEC R16
49 BRNE BUCLE_INTERNO ; Espera interna (retardo fino)
50 DEC R18
51 BRNE BUCLE_EXTERNO ; Espera externa (retardo grueso)
52 POP R16 ; Restaurar registros
53 POP R18
54 RET ; Fin del retardo
2. Creación y compilación del proyecto en Microchip Studio
La creación y compilación del proyecto que incluye únicamente un archivo denominado main.asm
es como sigue:
• En Microchip Studio, se selecciona la opción File > New > Project.... Luego, se elige la
opción AVR Assembler Project.
• Se asigna un nombre al proyecto y se selecciona el microcontrolador ATmega328P como
dispositivo de destino.
• En el archivo main.asm creado automáticamente reemplazamos la plantilla por el Programa
1 en lenguaje ensamblador.
• La compilación se realiza seleccionando Build > Build Solution.
3. Simulación del proyecto
En la Figura 6, se muestra el circuito, organizado en Proteus, para la simulación del funcionamiento
del programa.
8
Figura 6 Circuito de simulación del programa que cambia el estado del LED al activar el pulsador.
2.5. Teclado Matricial 4x4
Figura 7 Teclado matricial 4x4
9
Ejemplo 3. Teclado matricial 4x4 conectado al microcontrolador ATmega328P
1. Planteamiento del ejercicio
En este ejercicio se propone el desarrollo de un sistema basado en el microcontrolador
ATmega328P, implementado en la tarjeta Arduino Uno, que permita la lectura de un teclado
matricial de 4x4 y la transmisión del símbolo de la tecla pulsada mediante la interfaz UART hacia
un computador personal para su visualización.
El teclado matricial cuenta con 4 filas y 4 columnas. Las filas están conectadas a los pines PB0,
PB1, PB2 y PB3 del puerto B, mientras que las columnas se encuentran conectadas a los pines PC0,
PC1, PC2 y PC3 del puerto C del microcontrolador. El programa a desarrollar debe incluir tres
funciones escritas en lenguaje ensamblador: función de inicialización de teclado matricial, función
de detección de tecla presionada y función de identificación de tecla presionada. Luego, el carácter
correspondiente deberá ser transmitido por la UART para su visualización en un terminal serial en
la PC.
2. Archivos del proyecto
Nombre del archivo Descripción
main.c Archivo principal del programa. Incluye la inicialización de UART,
inicialización del teclado y el envío de caracteres a la PC.
kb4x4.S Archivo en lenguaje ensamblador que contiene tres funciones:
iniciarTeclado, detectarTeclaPresionada y leerTeclado.
uart.h Archivo de cabecera con las definiciones y funciones para manejo de UART.
Se usará el archivo uart.h empleado en ejemplos anteriores.
Programa 2 Programa en C de gestión de teclado matricial 4x4 por consulta con funciones en
lenguaje ensamblador.
1 #include <avr/io.h>
2 #include "uart.h"
3 #include <util/delay.h>
4 #include <stdio.h>
5 #define F_CPU 16000000UL
6 extern void iniciarTeclado();
7 extern uint8_t leerTeclado();
8 extern uint8_t detectarTeclaPresionada();
9 int main() {
10 iniciarTeclado();
11 uart_init(9600);
12 uart_puts("Teclas presionadas: ");
13 while (1) {
14 uint8_t res = detectarTeclaPresionada();
15 if (res) {
16 _delay_ms(20);
17 char key = leerTeclado();
18 uart_putc(key);
19 while (detectarTeclaPresionada()){
20 }
21 _delay_ms(20);
22 }
23 }
24 }
10
Programa 3 Funciones en lenguaje ensamblador para gestión de teclado matricial 4x4.
1 #include <avr/io.h>
2 .global iniciarTeclado
3 .global leerTeclado
4 .global detectarTeclaPresionada
5 .section .text
6 .equ DDRB_, 0x04
7 .equ PORTB_, 0x05
8 .equ PINC_, 0x06
9 .equ DDRC_, 0x07
10 .equ PORTC_, 0x08
11 iniciarTeclado:; Configura puertos de entrada/salida
12 LDS R16,MCUCR
13 ANDI R16,0B11101111
14 STS MCUCR,R16
15 LDI R16,0XFF
16 OUT DDRB_,R16
17 LDI R16,0X00
18 OUT DDRC_,R16
19 LDI R16,0XFF
20 OUT PORTC_,R16
21 RET
22 leerTeclado:; Salida: R24 - Símbolo de tecla presionada
23 PUSH R16
24 PUSH R17
25 LDS R16,SREG
26 PUSH R16
27 LDI R16, 0B11110111 ; Activar primera fila PB3
28 CLR R20 ;Inicializar número de filas analizadas
29 CLR R19
30 LDI R24,0;Inicializar símbolo
31 SIGUIENTE_FILA:
32 INC R20
33 OUT PORTB_, R16; Activar fila
34 NOP
35 IN R18, PINC_ ;Leer columnas
36 ANDI R18,0B00001111; Nibble bajo se conserva
37 CPI R18,0B00001111;
38 BREQ CAMBIAR_FILA ;Si no hay fila activada pasar a la siguiente
39 LDI R19, 0 ;Hay fila activa, identificar columna activa
40 SIGUIENTE_COLUMNA:
41 LSR R18 ;Desplazamiento a la derecha a través de Acarreo C
42 BRCC IDENTIFICAR_TECLA ;Si el bit es 0, se hallo columna activa
43 INC R19
44 CPI R19, 4
45 BRNE SIGUIENTE_COLUMNA
46 RJMP FINALIZAR_BARRIDO;No hay columna activa
47 CAMBIAR_FILA:
48 LSR R16 ; Mover a la siguiente fila
49 CPI R16,0B00001111; Si se han revisado todas las filas, salir
50 BRNE SIGUIENTE_FILA
51 RJMP FINALIZAR_BARRIDO
52 IDENTIFICAR_TECLA:
53 LDI R18, 4
54 DEC R20;
55 MUL R18, R20 ; R18 = fila * 4
56 MOV R18, R0
57 ADD R18, R19 ; R18 = fila * 4 + columna
58 LDI ZL, lo8(KEYMAP) ; Cargar dirección de KEYMAP
59 LDI ZH, hi8(KEYMAP)
60 ADD ZL, R18 ; Desplazar a la tecla presionada
61 LDI R18,0
11
62 ADC ZH,R18
63 LD R24, Z ; Cargar el código ASCII
64 FINALIZAR_BARRIDO:
65 POP R16
66 STS SREG,R16
67 POP R17
68 POP R16
69 RET
70 detectarTeclaPresionada:;En R24, devuelve 0 si no hay tecla presionada,
71 LDI R24, 0X00 ;caso contrario devuelve 1.
72 LDI R18, 0B11110000 ;
73 OUT PORTB_, R18; Activar todas las filas
74 NOP
75 IN R18, PINC_ ;Leer columnas
76 ANDI R18, 0B00001111;
77 CPI R18,0B00001111;
78 BREQ SALIR
79 LDI R24, 0X01
80 SALIR: RET
81 .section .data
82 KEYMAP:
83 .BYTE '1', '2', '3', 'A'
84 .BYTE '4', '5', '6', 'B'
85 .BYTE '7', '8', '9', 'C'
86 .BYTE '*', '0', '#', 'D'
3. Simulación del sistema
Para la simulación del sistema en Proteus, organizamos el circuito de la Figura 8, cargamos el
archivo .hex generado en Microchip Studio al microcontrolador y establecemos la frecuencia de la
señal de reloj en 16 MHz. En el terminal virtual establecemos la velocidad de transmisión en 9600
baudios (de acuerdo con el valor del programa). Los símbolos de las teclas pulsadas se verán en el
terminal virtual.
Figura 8 Simulación en Proteus del programa de gestión de teclado matricial 4x4 por consulta.
12
Capítulo 3. Sistema de Interrupciones
Podemos definir una interrupción en un microcontrolador como la detención temporal de la
ejecución del programa principal para atender una tarea de mayor prioridad, denominada Rutina de
Servicio de Interrupción (ISR por sus siglas en inglés). Este mecanismo permite al
microcontrolador responder de manera inmediata a condiciones externas o internas sin la necesidad
de realizar un monitoreo continuo mediante bucles de sondeo.
3.1. Fuentes de Interrupción
Tabla 3 Tabla de vectores de interrupción.
N.º de Dirección Fuente Evento
Vector
1 0x0000 RESET Reset externo, Reset de encendido, Reset por reducción de
voltaje y Reset por Watchdog.
2 0x0002 INT0 Solicitud de interrupción externa 0.
3 0x0004 INT1 Solicitud de interrupción externa 1.
4 0x0006 PCINT0 Solicitud de interrupción por cambio en pin 0.
5 0x0008 PCINT1 Solicitud de interrupción por cambio en pin 1.
6 0x000A PCINT2 Solicitud de interrupción por cambio en pin 2.
7 0x000C WDT Interrupción por desbordamiento del Watchdog.
8 0x000E TIMER2 COMPA Igualdad en la comparación A del Timer 2.
9 0x0010 TIMER2 COMPB Igualdad en la comparación B del Timer 2.
10 0x0012 TIMER2 OVF Desbordamiento del Timer 2.
11 0x0014 TIMER1 CAPT Evento de captura del Timer 1.
12 0x0016 TIMER1 COMPA Igualdad en la comparación A del Timer 1.
13 0x0018 TIMER1 COMPB Igualdad en la comparación B del Timer 1.
14 0x001A TIMER1 OVF Desbordamiento del Timer 1.
15 0x001C TIMER0 COMPA Igualdad en la comparación A del Timer 0.
16 0x001E TIMER0 COMPB Igualdad en la comparación B del Timer 0.
17 0x0020 TIMER0 OVF Desbordamiento del Timer 0.
18 0x0022 SPI, STC Transferencia serial SPI completa.
19 0x0024 USART, RX Recepción completa en el USART.
20 0x0026 USART, UDRE Registro de datos del USART vacío.
21 0x0028 USART, TX Transmisión completa en el USART.
22 0x002A ADC Conversión completa en el ADC.
23 0x002C EE READY EEPROM lista para lectura o escritura.
24 0x002E ANALOG COMP Comparador analógico activado.
25 0x0030 TWI Interfaz serial de 2 hilos (I2C/TWI).
26 0x0032 SPM READY Memoria de programa lista para escritura.
Fuente: Microchip Technology Inc., "ATmega328P Datasheet", Rev. 7810D–AVR–01/15, 2015.
3.2. Habilitador Local, habilitador Global y Bandera de Interrupción
Al inicializar el microcontrolador ATmega328P, las interrupciones se encuentran deshabilitadas por
defecto. Cada fuente de interrupción cuenta con un habilitador local, configurado a través de
registros de control como el EIMSK para interrupciones externas o el TIMSK para las
interrupciones de los Timers. Adicionalmente, existe un habilitador global de interrupciones
controlado por el bit I (Interrupt Enable) del registro de estado SREG.
13
Asimismo, cada fuente de interrupción posee una bandera de interrupción, ubicada en registros
como EIFR para interrupciones externas o TIFR0 para el Timer 0. Estas banderas funcionan como
indicadores de eventos: cuando ocurre el evento, su bandera correspondiente se establece en 1,
independientemente de si la interrupción está habilitada. Tras la atención de la interrupción, algunas
banderas se borran automáticamente, mientras que otras requieren un borrado manual (mediante
instrucciones). Un manejo incorrecto de estas banderas puede provocar retriggering (reentradas no
deseadas a la ISR) o pérdida de eventos, especialmente en entornos con múltiples fuentes de
interrupción concurrentes. Por ello, en el código de una ISR, es esencial verificar y limpiar las
banderas siguiendo las especificaciones del datasheet para garantizar un funcionamiento seguro.
Antes de que una interrupción pueda ser atendida, deben cumplirse tres condiciones:
1. Que el habilitador global de interrupciones esté activado, lo que se logra mediante la
instrucción SEI (Set Global Interrupt Enable).
2. Que el habilitador local correspondiente a la fuente de interrupción también esté activado.
Por ejemplo, para habilitar la interrupción externa INT0, se debe colocar un 1 en el bit 0 del
registro EIMSK.
3. Que se haya establecido la bandera de interrupción (Interrupt Flag) correspondiente a la
fuente, lo que significa que ocurrió el evento.
Solo cuando se cumplen simultáneamente estas tres condiciones, el microcontrolador interrumpe el
flujo normal del programa y transfiere el control a la ISR correspondiente.
Figura 9 Mecanismo de llamado y retorno de una interrupción.
14
3.3. Interrupciones Externas
Las interrupciones externas en el microcontrolador ATmega328P permiten que el procesador
responda de manera inmediata a eventos externos sin la necesidad de consulta permanente por parte
del programa principal. Estas interrupciones se generan cuando ocurre un cambio en el nivel lógico
de pines específicos configurados como entradas, denominados INT0 e INT1, ubicados en los pines
PD2 y PD3, respectivamente.
La configuración de las interrupciones externas en el ATmega328P se gestiona mediante el
Registro de Control de las Interrupciones Externas (EICRA). Este registro permite definir las
condiciones bajo las cuales se genera una interrupción en los pines INT0 e INT1, como flanco
ascendente, flanco descendente, cualquier cambio de nivel lógico o nivel bajo constante (ver Tabla
4).
Tabla 4 Registro de Control de las Interrupciones Externas (EICRA).
Bit Nombre Función
7-4 – Reservados, sin uso.
3-2 ISC11:ISC10 Configuran la condición de activación de la interrupción INT1.
00-El nivel bajo de INT1 genera una solicitud de interrupción.
01-Cualquier cambio lógico en INT1 genera una solicitud de interrupción.
10-El flanco descendente de INT1 genera una solicitud de interrupción.
11-El flanco ascendente de INT1 genera una solicitud de interrupción.
1-0 ISC01:ISC00 Configuran la condición de activación de la interrupción INT0.
00-El nivel bajo de INT0 genera una solicitud de interrupción.
01-Cualquier cambio lógico en INT0 genera una solicitud de interrupción.
10-El flanco descendente de INT0 genera una solicitud de interrupción.
11-El flanco ascendente de INT0 genera una solicitud de interrupción.
El Registro de Máscaras de Interrupción Externa EIMSK (External Interrupt Mask Register)
contiene los habilitadores locales de las interrupciones externas INT0 e INT1 (ver Tabla 5).
Tabla 5 Registro de Máscaras de Interrupción Externa (EIMSK).
Bit Nombre Función
7-2 – Reservados, sin uso.
1 INT1 Habilita la interrupción externa del pin INT1 (PD3).
0 INT0 Habilita la interrupción externa del pin INT0 (PD2).
El Registro de Banderas de Interrupción Externa (EIFR) contiene las banderas de las
interrupciones externas INT0 e INT1. Cuando ocurre el evento, el bit correspondiente en el EIFR
(ver Tabla 6) se establece automáticamente en nivel alto. Este bit se borra automáticamente al
ejecutar la rutina de servicio de interrupción (ISR) o escribiendo un “1” lógico en el bit
correspondiente, garantizando que el sistema no procese repetidamente la misma interrupción
innecesariamente.
15
Tabla 6 Registro de Banderas de Interrupción Externa (EIFR).
Bit Nombre Función
7-2 – Reservados, sin uso.
1 INTF1 Bandera de interrupción externa para el pin INT1.
0 INTF0 Bandera de interrupción externa para el pin INT0.
Ejemplo 4. Control de un LED mediante una interrupción externa en el
microcontrolador ATmega328P
1. Planteamiento del ejercicio
El presente ejercicio tiene como propósito desarrollar una aplicación básica que permita ilustrar el
uso de interrupciones externas en el microcontrolador ATmega328P, específicamente empleando la
tarjeta Arduino Uno como sistema de desarrollo. Se requiere elaborar un programa en lenguaje
ensamblador que controle el encendido y apagado de un LED a través de la pulsación de un
interruptor externo (pulsador). La detección del evento de pulsación se realizará utilizando la
interrupción externa INT0, correspondiente al pin digital PD2 del microcontrolador. Por otro lado,
el LED se conectará al pin digital PB0 (ver Figura 10). Cada vez que el usuario presione el pulsador
conectado al pin PD2, se generará una interrupción que efectúe el cambio de estado del LED, es
decir, si el LED se encuentra encendido deberá apagarse, y viceversa.
Figura 10 Esquema para encendido y apagado de LED usando pulsador gestionado por interrupción
2. Descripción del programa
En el Programa 4, cada vez que el usuario presiona el pulsador, el microcontrolador genera una
interrupción que invierte el estado lógico del LED.
16
Programa 4 Programa de cambio del estado de un led por activación de un pulsador
haciendo uso de interrupción externa.
1 .INCLUDE "M328PDEF.INC"
2 JMP PROG
3 .ORG 2
4 JMP INTEXT0 ; Vector de interrupción externa INT0 (PD2)
5 PROG:
6 LDI R16, HIGH(RAMEND)
7 OUT SPH, R16 ; Inicializa el byte alto del stack pointer
8 LDI R16, LOW(RAMEND)
9 OUT SPL, R16 ; Inicializa el byte bajo del stack pointer
10 IN R16,MCUCR
11 ANDI R16,0B11101111
12 OUT MCUCR,R16 ; Prepara PUD para habilitar las resistencias pull-up
13 IN R16, DDRB
14 ORI R16, 0B00000001
15 OUT DDRB, R16 ; Configura PB0 como salida (LED)
16 IN R16, DDRD
17 ANDI R16, 0B11111011
18 OUT DDRD, R16 ; Configura PD2 como entrada (pulsador)
19 IN R16, PORTB
20 ORI R16, 0B00000001
21 OUT PORTB, R16 ; Apaga inicialmente el LED (PB0)
22 IN R16, PORTD
23 ORI R16, 0B00000100
24 OUT PORTD, R16 ; Activa resistencia pull-up en PD2
25 LDI R16, 0B00000010
26 STS EICRA, R16 ; Configura INT0 para flanco de bajada
27 IN R16,EIMSK
28 ORI R16, 0B00000001
29 OUT EIMSK,R16 ; Habilita la interrupción externa INT0
30 SEI ; Habilita interrupciones globales
31 BUCLE: RJMP BUCLE
32 INTEXT0:
33 RCALL RETARDO ; Antirebote: espera breve al detectar interrupción
34 IN R16,PORTB
35 LDI R17, 0B00000001
36 EOR R16, R17
37 OUT PORTB, R16 ; Invierte el estado del LED (PB0)
38 ESPERAR_FLANCO_SUBIDA:
39 IN R16, PIND
40 ANDI R16, 0B00000100
41 CPI R16, 0B00000100
42 BRNE ESPERAR_FLANCO_SUBIDA ; Espera hasta que se suelte el botón
43 RCALL RETARDO ; Segundo antirebote tras soltar el botón
44 RETI ; Finaliza la rutina de interrupción
45 RETARDO:
46 PUSH R18
47 PUSH R16
48 LDI R18, 50
49 BUCLE_EXTERNO:
50 LDI R16, 255
51 BUCLE_INTERNO:
52 NOP
53 NOP
54 DEC R16
55 BRNE BUCLE_INTERNO
56 DEC R18
57 BRNE BUCLE_EXTERNO
58 POP R16
59 POP R18
60 RET
17
Figura 11 Simulación en Proteus del programa de cambio del estado de un LED por activación de un
pulsador haciendo uso de interrupción externa
18