Luego de un buen tiempo volví a programar en lenguaje de máquina, esta vez quería hacer un programa sencillo utilizando interrupciones (más exactamente la interrupción por desborde del timer 0), básicamente, la idea era crear un contador de 0 a 99 utilizando 2 displays de 7 segmentos (con cátodo o ánodo común) el cual se incrementa con un pulsador conectado en terminal RC0, hasta aquí todo funciona bien, el micro detecta el pulso de incremento, la rutina de interrupción hace la respectiva multiplexación en el respectivo display, el problema es que 9.5 s de iniciar la simulación ocurre un reset y el programa vuelve e inicia desde el vector 0x00. Aclaro que estoy programando en un 16f887.
Acá el código en lenguaje de máquina:
;******************** Declaración de registros especiales *********************************
tmr0 equ 01h
status equ 03h
porta equ 05h
portb equ 06h
portc equ 07h
portd equ 08h
porte equ 09h
intcon equ 0bh
option_reg equ 81h
trisa equ 85h
trisb equ 86h
trisc equ 87h
trisd equ 88h
trise equ 89h
adcon1 equ 9fh
wdtcon equ 105h
;******************* registros de usuario *************************************************
conta equ 20h ; contador
loop equ 21h
loop1 equ 22h ; registro de para la rutina de tiempo
decenas equ 23h ; Registro que contiene el valor de las
; decenas
unidades equ 24h ; Registro que contiene el valor de las
; unidades
list p = 16f887
;***************** va a empezar el programa ***********************************************
org 00
goto inicio
org 04
goto inter
;**************** Rutina de manejo de interrupción ****************************************
inter btfsc intcon,2 ; pregunto si hubo interrupción por timer0
goto timer0
retfie
timer0 movf conta,0 ; paso lo de conta a w
xorlw d'0'
btfss status,2 ; pregunto si conta es cero para saber que display activar
goto display2
goto display1
display1
bcf portc,1
bsf portc,2 ; activo el display 1 por 11.008ms
movf unidades,0
movwf portb
movlw d'1'
movwf conta
movlw d'84'
movwf tmr0 ; vuelvo cargar el valor 84d para que el timer se
; desborde de nuevo en 11.008ms
bcf intcon,2 ; borro el flag
retfie ; retorno al pcl+1
display2
bcf portc,2
bsf portc,1 ; activo el display 2 por 11.008ms
movf decenas,0 ; paso digito1 a w
movwf portb ; paso el valor a visualizar
clrf conta ; limpio a conta para que en el otro ciclo refresque al
; display1
movlw d'84'
movwf tmr0 ; vuelvo cargar el valor 84d para que el timer se
; desborde de nuevo en 11.008ms
bcf intcon,2 ; borro el flag
retfie ; retorno al pcl+1
;*************** Rutina de tiempo antirebote **********************************************
retar movlw d'100'
movwf loop
movlw d'100'
movwf loop1
decfsz loop1,1
goto $-1
decfsz loop,1
goto $-5
return
;*************** rutina de principal (main) ***********************************************
inicio bsf status,6
bcf status,5 ; banco 2
movlw b'00000000'
movwf wdtcon ; desactivo el wdt (perro guardian)
bcf status,6
bsf status,5 ; banco 1
movlw b'11111111'
movwf trisa
movwf trisd
movwf trise ; puerto C,D,E como entradas digitales
movlw b'11111001'
movwf trisc ; configuro el pueto A los primeros 2 terminales como salidas
; digitales las otras 4 como entradas digitales
movlw b'11110000'
movwf trisb ; puerto B como salidas digitales
movlw b'11010101'
movwf option_reg ; configuro el timer a un predivisor de frecuancia de 1:64
movlw b'00000110'
movwf adcon1 ; configuro puerto A Y E como entradas digitales
bcf status,5 ; banco 0
clrf porta
clrf portb
clrf portc
clrf portd
clrf porte ; limpio todo los puertos
movlw b'10100000'
movwf intcon ; habilito la interrupcion global y por desborde del timer0
; ya estamos listos solo falta cargar el valor correspondiente
; en el registro tmro
clrf conta ; limpio el contador
clrf decenas ; pongo el display en ceros
clrf unidades
movlw d'84'
movwf tmr0 ; pongo 84 en el timer para que cuente 11.008 ms y se
; desborde
clrf portb
pulsa btfsc portc,0
goto pulsa
call retar
pulsa1 btfss portc,0 ; ha pulsado el botom
goto pulsa1
incf unidades,1 ; incremento digito1
movf unidades,0
xorlw d'10'
btfss status,2
goto pulsa
clrf unidades ; si llego a 10 pongo el digito2 en 1 y el otro en 0 para escribir 20
; 30.....99
incf decenas,1
movf decenas,0 ; paso digito2 a w
xorlw d'10'
btfss status,2
goto pulsa ; si no a llegado a 99 sigo incrementado
clrf decenas ; vuelvo a inicializar el ciclo desde 00 hasta 99
goto pulsa
nada goto nada ; Bucle infinito esperando a que ocurra la interrupción
end
He leído en varias oportunidades el datasheet más exactamente el capítulo 14, pero no logro dar con el problema, de la misma forma, adaptando el código al pic16f877 (homólogo ya descontinuado) este no presenta problema alguno y el programa corre sin interrupción alguna. Para finalizar adjunto la simulación en proteus, cualquier sugerencia es bienvenida.