TODOPIC
Microcontroladores PIC => Almacén del Assembler => Mensaje iniciado por: Chenao en 20 de Febrero de 2013, 23:17:40
-
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.
-
¿No te saltara el WDT? ¿lo tienes dehabilitado? A mi me salto en el MPLAB.
Otra cosa en este PIC tienes que deshabilitar las entradas analogicas en ANSEL y ANSELH que estan en banco 3.
banksel ANSEL
clrf ANSEL; para PORTA digital
clrf ANSELH;PORTB digital
-
Según he leído en el datasheet el pic16f887 el wdt se controla por medio del registro wdtcon, el cual se encuentra ubicado en el banco 2 de la memoria ram, la parte del código que deshabilita el wdt se muestra a continuación:
inicio bsf status,6
bcf status,5 ; banco 2
movlw b'00000000'
movwf wdtcon ; desactivo el wdt (perro guardian)
¿No te saltara el WDT?
Yo creo que eso es lo que esta pasando por que el simulador me indica la siguiente advertencia:
1.[PIC16WDT] Initialised/restarted with interval of 9.216s
2.[PIC16WDT] Prescaler cleared
Eso son los mensajes que me arroja el simulador. ¿ahora no sé si nos referimos al mismo problema?. Por otro lado estoy tratando de configurar el registro config, con la esperanza de deshabilitar el perro guardián.
Otra cosa en este PIC tienes que deshabilitar las entradas analogicas en ANSEL y ANSELH que estan en banco 3.
Gracias por el dato ya agregue esta líneas al código.
-
Eso son los mensajes que me arroja el simulador. ¿ahora no sé si nos referimos al mismo problema?. Por otro lado estoy tratando de configurar el registro config, con la esperanza de deshabilitar el perro guardián.
Yo en el MPLAB voy a configure-configuration bits, ahi configuro todos los FUSES, me pregunta si quiero que me los escriba en el codigo, le doy a aceptar y listo. De hecho en tu programa lo dehabilite y ya no se me reseteaba.
-
He ha agregado la siguiente instrucción en la rutina de interrupción y no pone problema alguno, el código es el siguiente:
;**************** Rutina de manejo de interrupción ****************************************
inter clrwdt
Con esta instrucción no ocurre el reset (al parecer ocurre el reset porqué hay desborde del wdt).
Yo en el MPLAB voy a configure-configuration bits, ahi configuro todos los FUSES, me pregunta si quiero que me los escriba en el codigo, le doy a aceptar y listo. De hecho en tu programa lo dehabilite y ya no se me reseteaba.
El programa lo he hecho en el bloc de notas, entonces, ¿existe una manera de poder configurar los fuses por medio de software (código)?, lo pregunto porque llevo un buen tiempo tratando de configurar el registro config de la siguiente manera:
__CONFIG _CP_OFF & _WDT_OFF & _XT_OSC & _PWRTE_ON
Pero al compilar el código, el proteus me genera error y la verdad no se que hacer.
-
Con esta instrucción no ocurre el reset (al parecer ocurre el reset porqué hay desborde del wdt).
Si, claro, si pones esa instruccion cada 9ms de ejecucion del programa el WDT no se desborda y no se resetea, para eso es, para que nunca se quede colgado el programa, hay que ponerla en sitios extrategicos de manera que si no pasa por ahi es porque se queda colgado o se esta ejecutando mal y para evitar eso se resetea y empieza de nuevo.
El programa lo he hecho en el bloc de notas, entonces, ¿existe una manera de poder configurar los fuses por medio de software (código)?, lo pregunto porque llevo un buen tiempo tratando de configurar el registro config de la siguiente manera:
Yo tambien hago los programas en el block de notas, despues lo pego en el editor del MPLAB y ahi lo configuro. En la configuracion te da la palabra de configuracion, por ejemplo a mi me sale esta:
Address Value
2007 3FE4
2008 3FFF
Con estos datos que tu das y oscilador interno sin salida de reloj en RA6 y RA7:
__CONFIG _CP_OFF & _WDT_OFF & _XT_OSC & _PWRTE_ON
En proteus no se como se hace, pero creo que puedes generar el codigo ya compilado en MPLAB y pasarlo a Proteus ya con todo hecho.
-
Yo tambien hago los programas en el block de notas, despues lo pego en el editor del MPLAB y ahi lo configuro. En la configuracion te da la palabra de configuracion, por ejemplo a mi me sale esta:
Address Value
2007 3FE4
2008 3FFF
Con estos datos que tu das y oscilador interno sin salida de reloj en RA6 y RA7:
__CONFIG _CP_OFF & _WDT_OFF & _XT_OSC & _PWRTE_ON
En proteus no se como se hace, pero creo que puedes generar el codigo ya compilado en MPLAB y pasarlo a Proteus ya con todo hecho.
Lo que pasa, es que sólo utilizo el MPLAB para ensamblar el .hex al micro (configurando previamente los fuses antes del ensamble), pero el .hex lo creo directamente con el PROTEUS. La siguientes líneas de código debería configurar los fuses desde soft pero me bota error al realizar la respectiva compilación. las líneas son las siguientes:
_CP_OFF EQU H'FFFF'
_WDT_OFF EQU H'3FFB'
_XT_OSC EQU H'FFFD'
_PWRTE_ON EQU H'FFF7'
__CONFIG _CP_OFF & _WDT_OFF & _XT_OSC & _PWRTE_ON
Lo raro es que estas líneas con el 16f877 no dan problema alguno pero con el 16f887 al compilar genera error ¿?.
-
En el MPLAB si pongo ese encabezado que tu pones tambien me da error, en cambio poniendo este otro:
LIST p = 16F887 ;PIC a usar
#INCLUDE <P16F887.INC> ;fichero de registros del PIC
__CONFIG _CONFIG1, _XT_OSC & _WDT_OFF & _PWRTE_ON & _MCLRE_ON & _CP_OFF & _LVP_OFF
Ya me compila sin problemas, prueba si en Proteus tambien va, mira si le quieres cambiar algo.
-
__CONFIG _CONFIG1, _XT_OSC & _WDT_OFF & _PWRTE_ON & _MCLRE_ON & _CP_OFF & _LVP_OFF
Definitivamente no funciona voy a compilar más bien desde el MPLAB para no complicar más el asunto. Muchas gracias compañero tapi8.
-
En MPLAB no pone ningun problema, tambien he probado asi y compila perfectamente:
LIST p = 16F887 ;procesador a usar
#INCLUDE <P16F887.INC> ;definir registros de RAM
; __CONFIG _CONFIG1, _XT_OSC & _WDT_OFF & _PWRTE_ON & _MCLRE_ON & _CP_OFF & _LVP_OFF
__CONFIG _CONFIG1, 3FE4
__CONFIG _CONFIG2, 3FFF
-
En MPLAB no pone ningun problema, tambien he probado asi y compila perfectamente:
LIST p = 16F887 ;procesador a usar
#INCLUDE <P16F887.INC> ;definir registros de RAM
; __CONFIG _CONFIG1, _XT_OSC & _WDT_OFF & _PWRTE_ON & _MCLRE_ON & _CP_OFF & _LVP_OFF
__CONFIG _CONFIG1, 3FE4
__CONFIG _CONFIG2, 3FFF
Si tienes razón en el MPLAB no pone problema alguno, la verdad sigo sin entender porque en el bloc de notas pone problemas al hacer las definiciones manualmente, nunca me había pasado ya que programaba en el 16f84, 16f628, 16f877 configurando el config y me andaba sin problemas, voy a seguir investigando cuanto tenga algún resultado lo comento.
Saludos y gracias por la atención prestada.