TODOPIC
Microcontroladores PIC => Almacén del Assembler => Mensaje iniciado por: rosalva40 en 20 de Abril de 2015, 23:56:48
-
Hola, tengo que hacer un ejercicio que es el siguiente. Tengo que mediante un pulsador incrementar la salida en decimal de 2 display conectados ambos a la salida de los pines del puerto B, Cada display se prendera y apagara desde el RC0 y RC1, y el pulsador esta conectado al RA0, en teoria deberia contar los pulsos de 0 a 99. Para prender y apagar los dos display lo hago con una interrupción en timer0 , configurando todo para que lo haga cada 0,04 segundos aproximadamente, asi el ojo no va a detectar cuando
se apaga, sino que lo va a ver siempre prendido. El codigo es este:
list P=16F877A ;Comando que indica el Pic usado
#include "p16F877A.inc" ;Etiquetas genéricas para el Pic16F887
; CONFIG
; __config 0xFFFD
__CONFIG _FOSC_XT & _WDTE_OFF & _PWRTE_OFF & _BOREN_ON & _LVP_ON & _CPD_OFF & _WRT_OFF & _CP_OFF
W_TEMP EQU 0X21
STATUS_TEMP EQU 0X22
ContUNI EQU 0x23
ContDEC EQU 0x24
ContTMR EQU 0x25
BOOL EQU 0x26
; -------
ORG 0x00
GOTO EMPEZAR
ORG 0x04
GOTO INTERRUPCION
ORG 0x05
; ------------- Configuracion ---------------
EMPEZAR
BSF STATUS, RP0 ; Banco 1
BCF STATUS, RP1
CLRF TRISB ; Puerto B como salida
CLRF TRISC ; Puerto C como salida
BSF TRISA,1
MOVLW B'00000111' ; ------ Configuramos el option REG con disivor 1:256
MOVWF OPTION_REG
MOVLW B'00100000' ; ------ Habilito Interrupcione por TMR0
MOVWF INTCON
BCF STATUS, RP0 ; Banco 0
CLRF PORTA
CLRF PORTB
CLRF PORTC
MOVLW D'1'
MOVWF ContTMR
MOVLW D'10'
MOVWF ContUNI
MOVWF ContDEC
MOVLW D'96'
MOVWF TMR0
BCF BOOL,0
BSF INTCON, GIE
;--------------------------------------
INICIO
BTFSS PORTA, 0
GOTO INICIO
VOLVER
BTFSC PORTA,0
GOTO VOLVER
DECFSZ ContUNI, F
GOTO INICIO
GOTO ReiCU
TABLA
ADDWF PCL,F
RETLW B'0000000'
RETLW B'1110011'
RETLW B'1111111'
RETLW B'1110000'
RETLW B'1011111'
RETLW B'1011011'
RETLW B'0110011'
RETLW B'1111001'
RETLW B'1101101'
RETLW B'0110000'
RETLW B'1111110'
INTERRUPCION
MOVWF W_TEMP
SWAPF STATUS,W
MOVWF STATUS_TEMP
DECFSZ ContTMR,F
GOTO RETORNA
BTFSS BOOL,0
GOTO LED1
GOTO LED2
RETORNA
SWAPF STATUS_TEMP,W
MOVWF STATUS
SWAPF W_TEMP,F
SWAPF W_TEMP,W
CLRF TMR0
MOVLW D'96'
MOVWF TMR0
BCF INTCON,T0IF
RETFIE
LED1
COMF BOOL,F
MOVF ContUNI,W
CALL TABLA
MOVWF PORTB
BSF PORTC,0
BCF PORTC,1
MOVLW D'1'
MOVWF ContTMR
GOTO RETORNA
LED2
COMF BOOL,F
MOVF ContDEC,W
CALL TABLA
MOVWF PORTB
BSF PORTC,1
BCF PORTC,0
MOVLW D'1'
MOVWF ContTMR
GOTO RETORNA
ReiCU
MOVLW D'10'
MOVWF ContUNI
DECFSZ ContDEC,W
GOTO INICIO
GOTO ReiCD
ReiCD
MOVLW D'10'
MOVWF ContUNI
GOTO INICIO
END
y esta es la simulacion en Proteus:
(http://i.imgur.com/LBXzpBU.png)
Haciendo el debug desde el MPlab, va a incrementando el display a medida que toco el pulsador , parece que todo anda bien, el problema es que cuando lo simulo en Proteus y toco el pulsador no me aumenta en uno el display, se queda siempre en 0, y no me doy cuenta que puede haber mal, alguno sabe que puede ser?.
saludos.
-
Hola rosalva40, te diría que el problema puede estar en que no desactivas los convertidores analógicos/digital.
El puerto A de ese micro dispone de convertidores A/D que debes de configurar correctamente para que los pines del portA funcionen como digitales, de lo contrario y por defecto de fábrica funcionan como analógicos y no aceptarán el funcionamiento digital que tu pretendes.
Un saludo.
Atte. CARLOS.
-
Agrego a lo de Chaly. Hay otros problemas. Error que encontre:
RETORNA
SWAPF STATUS_TEMP,W
MOVWF STATUS
SWAPF W_TEMP,F
SWAPF W_TEMP,W
CLRF TMR0
MOVLW D'96'
MOVWF TMR0
BCF INTCON,T0IF
RETFIE
Ahi hay uno, si vas a recupera W y STATUS hacelo antes del RETFIE (al ultimo), es decir todas las instrucciones de recargar el valor del timer mas la limpieza del flag se debe hacer antes de recuperar el status y W.
Despues creo que tambien tendrias este problema en ReiCU:
El cual deberia ser
Sugerencias:
- Tambien tenes un GOTO demas en ReiCU pero no habria problemas es una instruccion mas. El GOTO que digo es GOTO ReiCD, ya que este saltaria y seguiria ejecutando ReiCD
- En ves de usar una variable completa como BOOL (8 bits) para saber cual display es el que esta encendido o un solo bit de este registro, podrias preguntar directamente por el bit que maneja al catodo, Es decir esto:
por
- Supongo que :
Pusiste un 1 para el debug (y si es necesario lo cambiarias), ya que con 1 entraria a la interrupcion y el DECFSZ que tenes siempre saltaria (1 entrada a la interrupcion = cambio de display)
Sino tendrias ese registro sin sentido y esas intrucciones tambien ya que como dije siempre saltaria y ejecutaria el cambio del display. Si en algun momento pensas que lo vas a cambiar entonces lo dejas.
- El error que dice Chaly se arregla poniendolo a todos como digitales es decir:
BANKSEL ADCON1 ;Banco 1
MOVLW 0x06
MOVWF ADCON1
-
Gracias muchachos por las respuestas, ahora si anda bien ((:-))
Pusiste un 1 para el debug (y si es necesario lo cambiarias), ya que con 1 entraria a la interrupcion y el DECFSZ que tenes siempre saltaria (1 entrada a la interrupcion = cambio de display)
Sino tendrias ese registro sin sentido y esas intrucciones tambien ya que como dije siempre saltaria y ejecutaria el cambio del display. Si en algun momento pensas que lo vas a cambiar entonces lo dejas.
Efectivamente deje en 1 ese contador, para el debug y aparte porque no se si estan bien los 0,04 segundos que use para prender y apagar los display ((256-96)*10^-6 * 256) = 0,04 . Porque en el Proteus veo como se prende y se apaga, que si bien lo hace muy rapido , no los veo todo el tiempo como si estuvieran encendidos que esa era mi idea en principio. A esos 0,04 segundos los saque haciendo: si el ojo solo puede ver 25 FPS , dividi 1/25 , para saber cuantos segundos son por fotograma y me da 0,04. pero como dije antes sigo viendo el apagado y prendido.
Otra dua, siempre se deben configurar las entradas de todos los puertos como digital?, osea en caso de usarlo como quiero yo (que activa o desactiva con 0 y 1) , porque antes hice otros programas y nunca los habia configurado como digital y funcionan iguall, solo una vez que use la interrupcion en rb0.
-
Al reset comienzan como analogicos aquellos que obviamente tengan entrada analogica. No toodos los puertos lo tienen y tampoco todos los pines. Depende del PIC en cuestion.
Es tu deber configurar el ADCON1 para seleccionar que entradas van a ser digitales y cuales analogicas.
Si observas el diagrama del puerto A (en el datasheet) si estan como analogicas las entradas, el pin de entrada se encuentra desconectado de lo que leerias desde el PORTx, lo cual imagino que leerias siempre 0
Solo utilizaras entradas analogicas cuando utilizas el ADC
Con respecto al multiplexado no te confies, es muy distinto en un dispositivo fisico que en una simulacion, ademas como ya tenes el codigo solo bastaria cambiar lo que se carga en TMR0 o ese contador.
Y finalmente si los usas como salida a esos tengo el presentimiento que te va a funcionar mal, ya que el micro trabaja con el principio de leer-modificar-escribir , si esta como analogico no tendria entrada desde el pin la parte digital por lo tanto el PORTx seria 0, al escribir un solo bit no habria problema pero si cambias primero el PORTA.1 y luego el PORTA.2 ahi si creo que existiria problemas y solo activaria el PORTA.2 desactivando el 1. Esto ultimo es una suposicion ya que jamas lo probe.