TODOPIC
Microcontroladores PIC => Almacén del Assembler => Mensaje iniciado por: bluesboy en 28 de Mayo de 2013, 22:56:19
-
Buenas gente, soy novato en esto.
Antes que nada gracias por el tiempo que le pongan a esto. Gracias.
Hice el programa que pongo a continuacion. la idea es que si se activa un sensor, por rb7 config como interrupcion, cuente en unos display de 7 seg, de 4 cifras. tengo 2 chips pq necesitaba hacer otras cosas y en los dos hace lo mismo. lo borro, lo grabo y nada.
Lo pruebo en el pic simulator y va genial, pero en la realidad no funciona, lo que hace es mostrar alternativamente, la unidad en todos los display y el cero, con lo cual quedan los 4 displays en 0 y la cifra de la unidad apenas mas intensa. Baje los tiempos para ver que pasaba y ponia en un tiempo todos ceros y en otro la unidad en los 4.
No tengo idea de donde puede estar el error :(. Y lamentablemente necesito solucionarlo. :shock:
Les dejo el programa.
SE AGRADECE CUALQUIER SUGERENCIA.
Gracias. Sebastián.
; **** Encabezado ****
LIST P=16F627A ; Microcontrolador utilizado.-
INCLUDE <P16F627A.INC> ; Definicion de registros SFR.-
__CONFIG _INTOSC_OSC_NOCLKOUT & _PWRTE_OFF & _WDT_OFF & _CP_OFF & _MCLRE_ON & _BOREN_OFF & _LVP_OFF &_CPD_OFF
;**** Definicion de Variables ****
; En esta posicion se declaran los registros de usuario (GPR).
UNIDAD EQU 0X29 ;Guardo Conteo unidad.
DECENA EQU 0X2A ;Decena.
CENTENA EQU 0X2B ;Centena.
MILLAR EQU 0X2C ;Unidad de mil.
CONTADOR1 EQU 0X20 ;registro utlizado en demora 5mS
CONTADOR2 EQU 0X21 ;registro usado en demora 5mS
CONTADOR EQU 0X22 ;registro usado en Rutina Activ de Display RAD
CONTADOR3 EQU 0X23 ;Registro utilizado en demora antirrebote
CONTADOR4 EQU 0X24 ;Registro utilizado en demora antirrebote
W_TEMP EQU 0X25 ;REGISTRO TEMPORAL PARA INTERRUPCION
STATUS_TEMP EQU 0X26 ;REGISTRO TEMPORAL PARA INTERRUPCION
DEMORADO1 EQU 0X27
DEMORADO2 EQU 0X28
; FINAL DE DECLARACION DE REGISTROS.
;Empieza declaración de bits.
MUESTROU EQU 3 ;CONTROL 1º DISPLAY
MUESTROD EQU 2 ;control 2º display
MUESTROC EQU 1 ;control 3º display
MUESTROM EQU 0 ;control 4 display
CUENTA EQU 6 ;BIT6 porta para saber si cuenta o descuenta.
;
;**** Inicio del Microcontrolador ****
RESET ORG 0x00
GOTO INICIO ; Salto a inicio del programa.-
ORG 0X04 ;VECTOR INTERRUPCION
BTFSC INTCON,RBIF
GOTO INTEXT
RETFIE
;**** Programa principal ****
ORG 0X07
INICIO
;CONFIGURACIONES PIC
BCF STATUS,6
BSF STATUS,5 ;CAMBIO A BANCO1
MOVLW 0x70
MOVWF TRISA ;seeessss
MOVLW 0x80
MOVWF TRISB ;Esssssss RB7 como entrada para rbif
MOVLW 0xDF
MOVWF OPTION_REG ; Pull-Up deshabilitados, , Timer0|interno, 1:1
BCF STATUS,5
BCF STATUS,6 ;PASO A BANCO 0
MOVLW 0x07 ; Configuro Comparador Analogico
MOVWF CMCON ; V1in-=GND, V1in+=GND, C1out=Off| V2in-=GND, V2in+=GND, C2out=Off
BSF INTCON,GIE
BSF INTCON,RBIE
;PROGRAMA
CLRF PORTB
CLRF PORTA ;Desactivo todos los displays y sensores, botones.
CLRF UNIDAD
CLRF DECENA
CLRF CENTENA
CLRF MILLAR
;
;RUTINA DE ACTIVACION DE DISPLAY
RAD
MOVLW D'20' ;Cargo contador de repeticiones display
MOVWF CONTADOR
REFRESCO
MOVF UNIDAD,0 ;Obtengo código 7 seg para unidad
CALL BCD7SEG
BCF PORTA,MUESTROM ;Apago display MILLAR
MOVWF PORTB ;Cargo unidad en PORTB
BSF PORTA,MUESTROU ;Enciendo display unidad.
CALL DEMORA5MS
MOVF DECENA,0 ;Obtengo código 7 seg para decena
CALL BCD7SEG
BCF PORTA,MUESTROU ;apago display unidad
MOVWF PORTB ;cargo decena en portb
BSF PORTA,MUESTROD ;Enciendo display decena
CALL DEMORA5MS
MOVF CENTENA,0 ;Obtengo código 7 seg para centena
CALL BCD7SEG
BCF PORTA,MUESTROD ;APAGO DISPLAY DECENA
MOVWF PORTB ;Cargo centena en portB
BSF PORTA,MUESTROC ;Enciendo display Centena
CALL DEMORA5MS
MOVF MILLAR,0 ;Obtengo código 7 seg para centena
CALL BCD7SEG
BCF PORTA,MUESTROC ;Apago display centena
MOVWF PORTB ;Cargo millar en portB
BSF PORTA,MUESTROM ;Enciendo display Millar
CALL DEMORA5MS
DECFSZ CONTADOR,1 ;¿Se repitió 20 veces?
GOTO REFRESCO
GOTO RAD ;queda constantemente mostrando display hasta que llega interrupcion.
BCD7SEG ; retlw b'gfedcba' para display catodo comun
ADDWF PCL,1 ; Se incrementa el contador del programa.-
DT 0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0xFF, 0x6F
;
;DEMORA 5mS
DEMORA5MS
MOVLW 0XFF
MOVWF CONTADOR1
REPETICION1
MOVLW 0X05
MOVWF CONTADOR2
REPETICION2
DECFSZ CONTADOR2,1
GOTO REPETICION2
DECFSZ CONTADOR1,1
GOTO REPETICION1
RETURN
;INTERRUPCION
INTEXT
MOVWF W_TEMP ; Copiamos W a un registro Temporario.-
SWAPF STATUS, W ;Invertimos los nibles del registro STATUS.-
MOVWF STATUS_TEMP ; Guardamos STATUS en un registro temporal.-
CALL ANTIRE
ESPERA BTFSC PORTB,7 ;¿Sigue pasando POR EL SENSOR?
GOTO ESPERA ;sigue pasando SENSOR ¡SI SE QUEDA COLGADO, SE DETIENE EL DISPLAY!
BTFSS PORTA,CUENTA ;NO ¿CUENTA O DESCUENTA?
GOTO DESCUENTA ;NO ESTA APRETADO, DESCUENTA.
;CALL ANTIRE ;CUENTA ANTIRREBOTE EMPIEZA RUTINA DE CUENTA ¡¡tal vez se saque esto!!
INCF UNIDAD,1 ;Icremento unidad
MOVLW D'10' ;cargo 10 para resetear unidad si llega a 10
SUBWF UNIDAD,0
BTFSS STATUS,Z
GOTO FININT ;NO ES 10, muestro unidad
CLRF UNIDAD ;Si reseteo
INCF DECENA,1 ;Incremento decena
MOVLW D'10' ;cargo 10 para resetar decena si llega a 10
SUBWF DECENA,0
BTFSS STATUS,Z
GOTO FININT
CLRF DECENA ;Reseteo
INCF CENTENA,1 ;Incremento Centena
MOVLW D'10' ;cargo 10 para resetar si llega a 10
SUBWF CENTENA,0
BTFSS STATUS,Z
GOTO FININT
CLRF CENTENA ;Reseteo
INCF MILLAR,1 ;Incremento Millar
MOVLW D'10' ;Cargo 10 para resetar si Millar llega a 10
SUBWF MILLAR,0
BTFSS STATUS,Z
GOTO FININT
CLRF MILLAR ;RESETEO
GOTO FININT
DESCUENTA
ESPERA2 BTFSC PORTB,7 ;¿Sigue pasando POR EL SENSOR?
GOTO ESPERA2 ;sigue pasando SENSOR ¡SI SE QUEDA COLGADO SE DETIENE EL DISPLAY!
MOVLW D'0' ;Comienzo de rutina de NO RESTAR SI TODO ES 0
SUBWF MILLAR,0
BTFSS STATUS,Z
GOTO RESTA
MOVLW D'0'
SUBWF CENTENA,0
BTFSS STATUS,Z
GOTO RESTA
MOVLW D'0'
SUBWF DECENA,0
BTFSS STATUS,Z
GOTO RESTA
MOVLW D'0'
SUBWF UNIDAD,0
BTFSS STATUS,Z
GOTO RESTA
GOTO FININT ; Es todo 0, no resta.
RESTA DECF UNIDAD,1 ;
MOVLW 0XFF
SUBWF UNIDAD,0 ;¿LE RESTO 1 A 0?
BTFSS STATUS,Z
GOTO FININT ;NO, ACTUALIZA DISPLAY
MOVLW 0X09 ;SI, RESETEA UNIDAD
MOVWF UNIDAD
DECF DECENA,1
MOVLW 0XFF
SUBWF DECENA,0
BTFSS STATUS,Z ;¿LE RESTE 1 A 0?
GOTO FININT ;NO, ACTUALIZA DISPLAY
MOVLW 0X09 ;SI, RESETEA DECENA
MOVWF DECENA
DECF CENTENA,1
MOVLW 0XFF
SUBWF CENTENA,0
BTFSS STATUS,Z ;¿LE RESTE 1 A 0?
GOTO FININT ;NO, ACTUALIZO DISPLAY
MOVLW 0X09
MOVWF CENTENA ;RESETEO CENTENA
DECF MILLAR,1
BTFSS STATUS,Z ;¿MILLAR VALE 0?
GOTO FININT ;NO, ACTUALIZO DISPLAY
MOVLW 0X00
MOVWF MILLAR ;PONGO EN CERO MILLAR
GOTO FININT ;SI, actualizo display.
FININT BCF INTCON,RBIF
SWAPF STATUS_TEMP,W ; Invertimos lo nibles de STATUS_Temp.-
MOVWF STATUS
SWAPF W_TEMP,1 ; Invertimos los nibles y lo guardamos en el mismo registro.-
SWAPF W_TEMP,W ; Invertimos los nibles nuevamente y lo guardamos en W.-
RETFIE
;
;antirrebote
;
ANTIRE MOVLW 0XFF ;Carga contador
MOVWF CONTADOR3 ;Inicia contador 3
REP1 MOVLW 0XFF
MOVWF CONTADOR4 ;Inicia contador 4
REP2 DECFSZ CONTADOR4,1 ;decrementa contador 4 hasta que vale 0
GOTO REP2 ;vuelve a decrementar.
DECFSZ CONTADOR3,1 ;decrementa con3 y vuelve a cargar cont2
GOTO REP1 ;cuando termina de decremtar 1 sale del ciclo
RETURN
END
-
Hola,
me gustaría sugerirte varias cosas, pero voy a enfocarme en las dos más importantes.
Primero: El guardado de los registros W y STATUS, dentro de la interrupción, debería hacerse ni bien se ingresa al vector de interrupción y restaurarse justo antes de salir. Así como lo estás haciendo, podés tener problemas, además de que de agregar otras interrupciones, vas a tener el código de guardado y restaurado repetido en cada interrupción si continuás poniendolos allí en cada interrupción. Algo MUY importante, es que los registros W_TEMP, STATUS_TEMP, etc. DEBEN asignarse a posiciones de memoria dentro del rango [0x70~0x7F] debido a que dicho rango es especial, ya que se encuentra compartido entre todos los bancos. Si bien pareciese que no es relevante, te invito a que te fijes lo que sucediese si lo dejás así, y por algún motivo al momento de producirse la interrupción, el banco actual de trabajo fuese el 1. Se guardarían en las posiciones 0xA5 y 0xA6 en lugar de las 0x25 y 0x26.
Segundo: Los simuladores suelen discrepar con el hardware real. Si bien no analice en profundidad el código, veo la ausencia de algo imprescindible para lograr salir de una interrupción por cambio del puertob, que es realizar una lectura sobre el mísmo para que el registro comparador interno (que es el que se usa para comparar el valor actual del puerto y detectar un cambio) se actualice y no siga interrumpiendo eternamente. Hacer un MOVF PORTB,F luego de la etiqueta INTEXT debería bastar. Recuerda sacar el guardado y restaurado de W y STATUS donde te recomiendo, caso contrario el MOVF PORTB,F te va a afectar el valor real del flag STATUS,Z.
Saludos.
-
Gracias BrunoF, no sabía lo de las interrupciones, ya me estoy guardando la info.
El equipo no funcionaba porque estaba usado transistores mosfet para el multiplexado y estos tienen una capacidad en el gate que alenta el tiempo de respuesta.
Lo solucione poniendo 4 BC337.
Muchas gracias. :-/