Tutoriales

Curso Básico AVR AT90S1200 - Página 4


Programa con interrupción externa

Ahora entremos con las interrupciones. Les presento un programa que hice muy básico sobre la interrupción externa.

La aplicación que le di fue generar un número aleatorio (random) para obtener la lectura de un dado, es decir, un número que fuera 1, 2, 3, 4, 5 ó 6 al momento en que uno aprieta un botón.

Hay registros que habilitan las interrupciones:
GIMSK - Tiene el bit INT0, el cuál al estar en 0 deshabilita la interrupción externa. Si está en 1 pues la habilita.
MCUCR - Sólo interesan los bits ISC00 y ISC01. Sirve para decir que flanco es el que dispara la int. ext. Los otros pónganlos a cero.

 
ISC01 ISC00
0 0 LOW 0
0 1 reservado
1 0 flanco derecho
1 1 flanco izquierdo
 
STATUS - La bandera I habilita el llamado a interrupción en general. La instrucción SEI habilita el bit I de status.
 
Ahora les pongo una imagen de cómo conectar los 7 leds en un arreglo que simule los puntos de un dado real:
 


Los AVR tienen un vector de interrupción único para cada interrupción:
 
0x00 RESET
0x01 Interrupción externa (GIMSK)
0x02 TIMER, OVF0 (TIMSK)
0x03 ANA_COMP
 
Para cada interrupción el contador de programa va a caer en un vector en específico.
 
El avr va a estar incrementando R17 hasta que llegue la presión del botón, sale del loop infinito y adecua el estado de R17 para convertirlo a una salida de 1 a 6 en el dado.

Para regresar de una interrupción hay que usar RETI para que regrese al programa normal y rehabilite I en status.

;dado electrónico hecho con interrupción externa
; B0 B1 B2 B3 B4 B5 B6 B7
; 1 2 3 4 5 6 7 NC
;
;MigSantiago
; _______
; 1|O 4 O|5
; 2|O O O|6
; 3|O O |7
; -------
;PD2 Push Button a tierra con r pull-up
 
.include "1200def.inc"
 
rjmp inicio
rjmp int_ext
nop
nop
inicio: ser r16
out ddrb,r16 ;ptob salida
out gimsk,r16 ;habilita int. externa
ldi r16,$03
out mcucr,r16 ;flanco izquierdo activa interrupción
sei ;activa interrupciones
random: inc r17 ;inc. random r17
rjmp random
 
int_ext: rcall rebote ;espera rebote de push button
andi r17,$07 ;filtra 5 primeros bits a cero
cpi r17,$00 ;si hubo cero saca 1
breq sacauno
cpi r17,$01 ;si hubo 1 saca 1
breq sacauno
cpi r17,$02 ;si hubo 2 saca 2
breq sacados
cpi r17,$03
breq sacatres
cpi r17,$04
breq sacacuatro
cpi r17,$05
breq sacacinco
cpi r17,$06
breq sacaseis
cpi r17,$07 ;si hubo 7 saca seis
breq sacaseis
 
sacauno: ldi r16,$08 ;prende 4
sacadado: out portb,r16
reti
sacados: ldi r16,$41 ;prende 1 y 7
rjmp sacadado
sacatres: ldi r16,$49 ;prende 1, 4 y 7
rjmp sacadado
sacacuatro: ldi r16,$55 ;prende 1,3,5,7
rjmp sacadado
sacacinco: ldi r16,$5d ;prende 1,3,4,5,7
rjmp sacadado
sacaseis: ldi r16,$77 ;prende 1,2,3,5,6,7
rjmp sacadado
 
; delay loop generator
; 800000 cycles:
; -----------------------------
; delaying 799995 cycles:
rebote: ldi R20, $5F
WGLOOP0: ldi R18, $17
WGLOOP1: ldi R19, $79
WGLOOP2: dec R19
brne WGLOOP2
dec R18
brne WGLOOP1
dec R20
brne WGLOOP0
; -----------------------------
; delaying 3 cycles:
ldi R20, $01
WGLOOP3: dec R20
brne WGLOOP3
; -----------------------------
; delaying 2 cycles:
ret
; =============================

 
Es importante que acomoden bien los LEDs para que le encuentren forma a las salidas del dado.