Professional Documents
Culture Documents
Las interrupciones tienen muchas ventajas, ya que se puede de cierta manera obtener
una especie de "paralelismo" porque el micro puede ejecutar el código principal, y en
momentos especiales por las interrupciones, ejecutar una parte de código como si todo
sucediera a la misma vez y volver al programa principal. Pero a la vez se debe tener
cuidado en su manejo, pues son un arma de doble filo si no son bien administradas, en
caso de tener que usar muchas interrupciones, o al tener mucho código que ejecutar
en la rutina de interrupción.
En los micros AVR cada interrupción posee su propio vector de interrupción lo que hace
más cómoda su ejecución y programación de la rutina correspondiente (ver tabla 11-1
del datasheet, adjunto en la siguiente página de este documento).
Ahora se describen las configuraciones para utilizar la interrupción externa INT0, cabe
mencionar que el micro ATMEGA16 posee dos fuentes de interrupción externa, estas
son INT0 ya mencionada además de INT1, alojadas en los pines D2 y D3 del micro
respectivamente.
Bit 3, 2 – ISC11, ISC10: Interrupt Sense Control 1 Bit 1 and Bit 0: Se usan para
la INT1.
Bit 1, 0 – ISC01, ISC00: Interrupt Sense Control 0 Bit 1 and Bit 0: Se usan para
la INT0, y responde a la siguiente tabla:
Que nos dice como se generará la interrupción, puede ser con un estado bajo en el pin
(00), por cualquier cambio de estado (01), por flanco de bajada (10), o por flanco de
subida (11).
Bit 6 – INT0: External Interrupt Request 0 Enable: Mediante este bit puesto en 1
se activa la máscara de Interrupción Externa 0, esto quiere decir que activando el bit
de interrupciones globales se podrá esperar por la interrupción configurada.
Ahora como ejemplo se muestra una forma de controlar la interrupción externa del
micro por el pin D2 (INT0). Mediante 2 displays de 7 segmentos se visualiza un conteo
ascendente de 0 a 99, conteo que será incrementado por la INT0.
;Constantes utilizadas
.def flag=r22
;PROGRAMA PRINCIPAL
inicio:
;Cargar el puntero de pila
ldi r16,high(ramend) ;Configuracion de...
out sph,r16
ldi r16,low(ramend)
out spl,r16 ;...la pila: Stack: $045F=RAMEND
;Confirugracion de los registros a usar
ser r16 ;r16 <- $FF
out ddrc,r16 ;portC todo de salida
out ddrb,r16 ;portB todo de salida
ldi r16,$fb ;r16 <- $fb
out ddrd,r16 ;portD salidas, excepto D2
;configuración de la Interrupción.
ldi r16,3 ;r16 <- 3
out mcucr,r16 ;configuramos nivel bajo para INT1, y flanco de subida para
INT0
ldi r16,$40 ;r16 <- $40
out gicr,r16 ;activamos la INT0 solamente
clr r16 ;r16 <- 0
out gifr,r16 ;limpiarmos flags de interrupcion INTF0 e INTF1 e INTF2
;Cargar los valores de datos para mostrar los datos en el display de ánodo común
;Puerto: B7 B6 B5 B4 B3 B2 B1
B0
;Segmentos: g f e d c X b a
ldi r16, $80 ; 1 0 0 0 0 0 0 0
mov r5,r16 ;Cero en R5
ldi r16, $F1 ; 1 1 1 1 0 0 0 1
mov r6,r16 ;Uno en R6
ldi r16, $48 ; 0 1 0 0 1 0 0 0
mov r7,r16 ;Dos en R7
ldi r16, $60 ; 0 1 1 0 0 0 0 0
mov r8,r16 ;Tres en R8
ldi r16, $31 ; 0 0 1 1 0 0 0 1
mov r9,r16 ;Cuatro en R9
ldi r16, $22 ; 0 0 1 0 0 0 1 0
mov r10,r16 ;Cinco en R10
ldi r16, $02 ; 0 0 0 0 0 0 1 0
mov r11,r16 ;Seis en R11
ldi r16, $B0 ; 1 0 1 1 0 0 0 0
mov r12,r16 ;Siete en R12
ldi r16, $00 ; 0 0 0 0 0 0 0 0
mov r13,r16 ;Ocho en R13
ldi r16, $20 ; 0 0 1 0 0 0 0 0
mov r14,r16 ;Nueve en R14
multiplexar:
cbi portc,0 ;apagamos ambos
cbi portc,1 ;displays
mov r28,r30 ;copiamos la dirección donde estan
mov r29,r31 ;los datos del display
add r30,r20 ;se suma el valor de unidades, para desplazarse en la tabla
ld r16,Z ;r16 <- (Z)
mov r30,r28 ;r30 <- r28
add r30,r21 ;se suma el valor de decenas, para desplazarse en la tabla
ld r15,Z ;r17 <- (Z)
mov r30,r28 ;r30 <- r28
out portb,r16 ;se muestra en el display de unidades, el valor correspondiente
sbi portc,0 ;enciende el display correspondiente
;call unseg
call delay1m ;tiempo de retardo para que sea visible al ojo
cbi portc,0 ;se apaga el display encendido anteriormente
out portb,r15 ;se muestra en el display de decenas, el valor correspondiente
sbi portc,1 ;enciende el display correspondiente
;call unseg
call delay1m ;tiempo de retardo para que sea visible al ojo
cbi portc,1 ;se apaga el display encendido anteriormente
ret
; =============================
; delay loop generator
; 4000 cycles:
; -----------------------------
; delaying 3999 cycles:
delay1m:
ldi R17, $1F
WGLOOP00: ldi R18, $2A
WGLOOP11: dec R18
brne WGLOOP11
dec R17
brne WGLOOP00
; -----------------------------
; delaying 1 cycle:
nop
ret
; =============================
; =============================
;Subrutina de 1seg
; 4000000 cycles:
; -----------------------------
; delaying 3999996 cycles:
unseg: ldi R17, $24
WGLOOP03: ldi R18, $BC
WGLOOP04: ldi R19, $C4
WGLOOP05: dec R19
brne WGLOOP05
dec R18
brne WGLOOP04
dec R17
brne WGLOOP03
; -----------------------------
; delaying 3 cycles:
ldi R17, $01
WGLOOP06: dec R17
brne WGLOOP06
; -----------------------------
; delaying 1 cycle:
ret
; =============================
Esquema de conexiones:
Programa para uso de teclado de matriz de 4x4
Ahora, un programa que lee una tecla presionada en un teclado 4x4. Una buena
manera de ahorrar líneas de entrada al micro es, en lugar de dedicar una línea
exclusiva por cada tecla utilizada, emplear un teclado matricial. El teclado matricial se
caracteriza por estar cada una de las teclas conectada a dos líneas (una columna y una
fila) que la identifican. De este modo el número de teclas que pueden conectarse es el
producto de filas por el de columnas.
La técnica de programación requiere tanto de entradas como de salidas. Las filas están
conectadas a las patillas de salida y las columnas a las de entrada.
También pueden usarse resistencias externas, e incluso llevarlas a tierra. En tal caso,
lo que se busca es un UNO en las líneas de entrada.
Las instrucciones que son útiles para saber cuando se presiona la tecla son:
sbic pinb,5
Si fuera sbis, brinca la siguiente instrucción si el bit 5 del puerto B está en UNO.
El programa es:
;----------------------------------------
;
; Autor: MigSantiago
; Adaptación ATMEGA16 por Lewin Lopez
;
; Notas: Este programa realiza un barrido por filas
; en el puerto B donde se encuentra conectado un teclado
; matricial 4x4. En el puerto D se muestra el valor de la
; tecla de acuerdo a la tabla siguiente:
;
; pb4 pb5 pb6 pb7
; | | | |
; pb0 -> 0 1 2 3
; pb1 -> 4 5 6 7
; pb2 -> 8 9 a b
; pb3 -> c d e f
;
; Registros: r16 -> registro temporal para pasar datos.
; r17 -> registro de mostrar tecla presionada
; r18 -> registro para contar el barrido
; r19 -> registro para contar la fila actual
;
; Conexiones: Puerto B -> Teclado
; pb0, pb1, pb2, pb3 Salidas matriz
; pb4, pb5, pb6, pb7 Entradas matriz
; Puerto D -> Salida Hexadecimal de tecla presionada
; pd4 -> salida estado tecla presionada (E)
;----------------------------------------
.include "m16def.inc"
.device ATMEGA16
.org 0000
jmp inicio
inicio:
;Cargar el puntero de pila
LDI R16, HIGH(RAMEND)
OUT SPH, R16
LDI R16, LOW(RAMEND)
OUT SPL, R16
;Configuracion de puertos
linea2:
inc r19
inc r18 ;en subrutina barrido, la primer línea
;no hace incremento, por eso se
;incrementa aquí
ldi r16,$02
out portb,r16 ;rb1=1 línea 2 activa
rjmp barrido
linea3:
inc r19 ;incrementa indicador de línea
inc r18
ldi r16,$04
out portb,r16 ;rb2=1 línea 3 activa
rjmp barrido
linea4:
inc r19 ;incrementa indicador de línea
inc r18
ldi r16,$08
out portb,r16 ;rb3=1 línea 4 activa
rjmp barrido
nopresion:
clr r16 ;pon E y LEDS a cero
out portd,r16 ;no hubo presión
rjmp reinicio
barrido:
sbic pinb,4 ;si rb4=0 no hay presión
rjmp presion
inc r18 ;siguiente tecla
sbic pinb,5
rjmp presion
inc r18 ;siguiente tecla
sbic pinb,6
rjmp presion
inc r18 ;siguiente tecla
sbic pinb,7
rjmp presion
rjmp quelinea ;no hubo presión en X línea
presion:
mov r17,r18 ;r17=r18
out portd,r17 ;saca tecla y E por portd
sbi portd,4 ;pd4=1 es decir E=1
rjmp reinicio ;que ya no haga barrido
quelinea:
cpi r19,$00 ;determina en que línea de barrido va
breq linea2 ;va a línea 2
cpi r19,$01
breq linea3
cpi r19,$02
breq linea4
cpi r19,$03
breq nopresion ;se va a limpiar ptod
;-----------------------------
Declaración de variables
No uso la declaración de variables para los registros del AVR, pero les explico unas
directivas para usarlas:
Y se usan normalmente:
EJERCICIO EN CLASE 9.