BANKSEL INTCON
Movlw b'10100000'
Movwf INTCON
BTFSS PIR1,TXIF
RETURN;Aca me fijo si es de 0 a 9 asi le sumo 0x30 ('0') o si es una A a F asi le sumo una 'A' a DATO_A_ENVIAR
MOVF DATO_A_ENVIAR
SUBLW .9
BTFSC STATUS,C ; Si esta en 0 es negativo, es decir 9 - DATO_A_ENVIAR = negativo o 9 < DATO_A_ENVIAR , apartir de 10 se pondria C = 1
GOTO SUMO30
SUMOA ; el dato no es cero por lo tanto sumo A
MOVF DATO_A_ENVIAR
ADDLW .55 ; 'A' - 10
MOVWF DATO_A_ENVIAR
MOVWF TXREG ;Cargo el valor asi se envia
RETURN
SUMO30 ; el dato que llega es 0 entonces sumo 0x30 a dato a enviar
MOVF DATO_A_ENVIAR
ADDLW 0x30
MOVWF DATO_A_ENVIAR
MOVWF TXREG ;Cargo el valor asi se envia
RETURN
ENDOkey entiendo donde esta mal, la cuestión es que tengo que mandar el dato a los displays y también al tx por eso lo puse dos veces al MOV, esta mal o al código que me corregiste le cambio eso y ya esta?
Por lo que decis puede ocurrir por 2 cosas:
1- Por los bancosCitarBANKSEL INTCON
Movlw b'10100000'
Movwf INTCON
No se bien que banco tomara ya que INTCON es accesible de todos los bancos, por ende buscate otro registro que solo pertenesca al banco 0, o fijate en el proteus is cambia el banco a donde corresponde ( banco 0 )
2- Por malas instrucciones:
incf Var_C,0 es lo mismo que decir incf Var_C,W
Por lo tanto incrementa y guarda en W, no se salva el valor, deberias poner incf Var_C,F o incf Var_C,1, de esa forma el resultado se almacena en el registro
Por otra parte todos esos reviso podrias simplificarlo con una tabla
Carga_Duty:
MOVF Var_C,W
ADDWF PCL, F
GOTO rojo
GOTO Azul
GOTO verde
GOTO amarillo
........ etc
Y seguro que se puede hacer algo parecido con los colores.
EDIT: Ahora releo la pregunta, entendi otra cosa. Creo que con el codigo como te lo pase deberia andar bien. No se por que pense que me habias preguntado que le habia corregido a tu codigo.
CitarEDIT: Ahora releo la pregunta, entendi otra cosa. Creo que con el codigo como te lo pase deberia andar bien. No se por que pense que me habias preguntado que le habia corregido a tu codigo.
Bueno dale espero tu respuesta!
ENVIAR_DATO ;Aca me fijo si es de 0 a 9 asi le sumo 0x30 ('0') o si es una A a F asi le sumo una 'A' a DATO_A_ENVIAR
BTFSS TXSTA,TRMT ; Pregunto por si esta libre el USART para mandar otro dato
RETURN
MOVF DATO_A_ENVIAR
ANDLW 0x0F
SUBLW .9
BTFSC STATUS,C ; Si esta en 0 es negativo, es decir 9 - DATO_A_ENVIAR = negativo o 9 < DATO_A_ENVIAR , apartir de 10 se pondria C = 1
GOTO SUMO30
SUMOA ; el dato no es cero por lo tanto sumo A
MOVF DATO_A_ENVIAR
ADDLW .55 ; 'A' - 10
MOVWF TXREG ;Cargo el valor asi se envia
RETURN
SUMO30 ; el dato que llega es 0 entonces sumo 0x30 a dato a enviar
MOVF DATO_A_ENVIAR
ADDLW 0x30
MOVWF TXREG ;Cargo el valor asi se envia
RETURNdecf mi_variable
--> Salta a interrupcion
<-- Vuelve de la interrupcion
btfss status,z
Interrupcion
incf otra_variable
retfieInterrupcion
incf Var_I,f
goto Pregunto_duty
Interrupcion
; Guardo contexto, codigo en el datasheet
; Limpio flag de interrupcion
; Cargo valor en TMR0 de ser necesario
INCF Var_I,F
; Devuelvo el contexto
RETFIE ; retorna a donde ocurrio la interrupcion y activa nuevamente las interrupciones globales GIETOMAR_DATOS
MOVF PORTA ;supongo que esta en el porta el dato en el nibble bajo
ANDLW 0x0F
MOVWF DATO_A_ENVIAR
addlw .256-.10 ; C will be set if number was >= 10
BTFSC STATUS,C
addlw .6 ; ...adjust for 10..29
addlw -(.256-.10) ; Back to original value;paso a BCD
ANDLW 0x0F
MOVWF UNIDADES
SWAPF DATO_A_ENVIAR,W
ANDLW 0x0F
MOVWF DECENAS addlw .256-.10 ; C will be set if number was >= 10
BTFSC STATUS,C
addlw .6 ; ...adjust for 10..29
addlw -(.256-.10) ; Back to original value;paso a BCD TOMAR_DATOS
MOVF PORTA ;supongo que esta en el porta el dato en el nibble bajo
ANDLW 0x0F ; solo dejo pasar el nibble bajo
MOVWF DATO_A_ENVIAR ; lo guardo en DATO_A_ENVIAR asi las demas subrutinas pueden usar el valor original que se tomo
addlw .256-.10 ; Procedo a pasarlo a BCD
BTFSC STATUS,C
addlw .6
addlw -(.256-.10) ; Final del paso a BCD
MOVWF UNIDADES ; Utilizo al registro como un registro temporal. UNIDADES = decenas:unidades
SWAPF UNIDADES,W ; Cambio de lugar los nibbles W = unidades:decenas
ANDLW 0x0F ; Elimino las unidades en W, me quedan las decenas ... W = 0:decenas
MOVWF DECENAS ; Guardo las decenas
MOVF UNIDADES ; Vuelvo a cargar todo el resultado del BCD -> decenas:unidades
ANDLW 0x0F ; Elimino las decenas W = 0:unidades
MOVWF UNIDADES ; Guardo las unidades
org 0x00
NOP
NOP
GOTO CONFIGURACION
org 0x04
GOTO INTERRUPCION
CONFIGURACION ; Aca configuro todo (puertos, timers, inicializo todas las variables a 00 o el valor que tengan, cargo valor de timer y activo interrupciones al ultimo )
BANKSEL PORTA ; SELECT BANK OF PORTA
CLRF PORTA ; INITIALIZE PORTA BY
BANKSEL OSCCON
MOVLW 0X60 ;RELOJ INTERNO 4MHZ
MOVWF OSCCON
; BANKSEL ANSEL ; SELECT BANK OF ADCON1
; MOVLW 0X00 ; CONFIGURE ALL PINS
; MOVWF ANSEL ; AS DIGITAL INPUTS
; BANKSEL TRISA
; MOVLW 0X0F ; VALUE USED TO
; MOVWF TRISA ; SET RA<7:0> AS INPUTS
; BANKSEL TRISB
; CLRF TRISB
BANKSEL PORTA
CLRF INTCON
CALL TIMER
BANKSEL DISPLAY1
MOVLW .78
MOVWF CONTADOR_DISPLAYS
CLRF PORTB
MOVLW .0
MOVWF DISPLAY1
MOVLW .0
MOVWF DISPLAY2
CLRF FLAG
; BANKSEL OSCCON
; MOVLW 0X60 ;RELOJ INTERNO 4MHZ
; MOVWF OSCCON
BANKSEL PORTA ; BANK0
MOVLW B'11110000'
MOVWF PORTA
MOVLW B'00000011'
MOVWF PORTB
BANKSEL TRISA ; BANK1
MOVLW B'11110000'
MOVWF TRISA
MOVLW B'00100111'
MOVWF TRISB
MOVLW B'00000000'
MOVWF ANSEL ; PORTA INPUTS = DIGITAL NOT ANALOG
;
; BAUD RATE SETTINGS
;
; BAUD VALUES WITH BRGH = 0
; ((20000000/9600)/64)-1 = 32
; MOVLW D'207' ; 1200 BAUD @ 16 MHZ FOSC +0.16 ERR
; MOVLW D'103' ; 2400 BAUD @ 16 MHZ FOSC +0.16 ERR
; MOVLW D'25' ; 9600 BAUD @ 16 MHZ FOSC +0.16 ERR
; MOVLW D'12' ; 19200 BAUD @ 16 MHZ FOSC +0.16 ERR
; MOVLW D'255' ; 1200 BAUD @ 20 MHZ FOSC +1.73 ERR
; MOVLW D'129' ; 2400 BAUD @ 20 MHZ FOSC +0.16 ERR
; MOVLW D'32' ; 9600 BAUD @ 20 MHZ FOSC -1.36 ERR
; MOVLW D'15' ; 19200 BAUD @ 20 MHZ FOSC +1.73 ERR
; BAUD VALUES WITH BRGH = 1
; ((20000000/9600)/16)-1 = 32
MOVLW D'25' ; 9600 BAUD @ 20 MHZ FOSC +0.16 ERR
MOVWF SPBRG
MOVLW B'00100100' ; BRGH = 1
MOVWF TXSTA ; ENABLE ASYNC TRANSMISSION, SET BRGH
BANKSEL RCSTA ; BANK0
MOVLW B'10010000'
MOVWF RCSTA ; ENABLE ASYNC RECEPTION
MOVF RCREG,W
MOVF RCREG,W
MOVF RCREG,W ; FLUSH RECEIVE BUFFER
TIMER
BANKSEL OPTION_REG
MOVLW B'00000110'
MOVWF OPTION_REG
BCF INTCON,6 ;INT EXTERNAS
BSF INTCON,5 ;TMR0
BCF INTCON,4 ;INT RB0
BCF INTCON,3 ;INT RB4-RB7
BCF INTCON,1 ;BANDERA RB0
BCF INTCON,0 ;BANDERA RB4-RB7
BCF INTCON,2 ;BANDERA TMROIF
BSF INTCON,7 ;INT GENERAL
MOVLW D'217'
BANKSEL TMR0
MOVWF TMR0
RETURN
GOTO MAIN
;******COMIENZO DE INTERRUPCION********
INTERRUPCION
;guardo contexto
SWAPF STATUS, W ;Swap status to be saved into W
CLRF STATUS ;bank 0, regardless of current bank, Clears IRP,RP1,RP0
MOVWF STATUS_TEMP ;Save status to bank zero STATUS_TEMP register
MOVF PCLATH, W ;Only required if using page 1
MOVWF PCLATH_TEMP ;Save PCLATH into W
CLRF PCLATH ;Page zero, regardless of current page
CLRF PORTB
;--------------------------------------------------------------------------
BTFSC PIR1,RCIF ; Pregunto por si llego algo en la UART
GOTO int_uart
BTFSS INTCON,TMR0IF ; Pregunto si la interrupcion fue del timer
GOTO salir_int ; Aca podria seguir agregando por eso pregunte arriba, y puse el GOTO, sino no hacia flata pregunta si era lo unico 2 que estaba activo
DECF CONTADOR_DISPLAYS ;Implemento contador por si es muy corta la interrupcion y para hacerla mas larga ( es decir contar la cantidad de interrupciones )
BTFSS STATUS,Z
GOTO salir_int
BSF FLAG,1 ; mi flag al pasar X veces por aca habilitando que se muestre
MOVLW .217 ; Recargo mi temporizador
MOVWF TMR0
MOVLW .78 ; Recargo mi contador
MOVWF CONTADOR_DISPLAYS
BCF INTCON,TMR0IF
GOTO salir_int
int_uart
BSF FLAG,0 ; mi flag de que llego algo por la UART
MOVF RCREG ; Limpio el buffer de lectura
MOVF RCREG ; Limpio el buffer de lectura
MOVF RCREG ; Limpio el buffer de lectura, 3 por que es posible tener 2 en la FIFO + 1 en el shift register, al vaciar la FIFO se pone a 0 RCIF
salir_int
;devuelvo el contexto------------------------------------
BCF INTCON,TMR0IF
MOVLW .217
MOVWF TMR0
MOVF PCLATH_TEMP, W ;Restore PCLATH;
MOVWF PCLATH ;Move W into PCLATH
SWAPF STATUS_TEMP, W ;Swap STATUS_TEMP register into W
;(sets bank to original state)
MOVWF STATUS ;Move W into STATUS register
SWAPF W_TEMP, F ;Swap W_TEMP
SWAPF W_TEMP, W ;Swap W_TEMP into W
RETFIE
;******FIN DE INTERRUPCION********
;******COMIENZO DE PROGRAMA PRINCIPAL********
MAIN
CALL TOMAR_DATOS
CALL ENVIAR
CALL MOSTRAR_DISPLAYS
CALL ANIMACION
GOTO MAIN
MOSTRAR_DISPLAYS
BTFSC FLAG,2 ; Con este indico que display estoy mostrando, si esta en 1 significa que es mi 2do display
GOTO display2
display1
BTFSC FLAG,1 ; Espero hasta que pase el tiempo se ejecute la interrupcion y me habilite la flag sino sigo saliendo
RETURN
BCF PORTB,2 ;catodo2
MOVF DATO_DECENAS
MOVWF PORTB ; Aca supongo que todo lo demas que no es dato esta en 0
BSF PORTB,3 ;catodo1
BSF FLAG,2 ; Activo el flag para que pase al otro display ( 2 )
BCF FLAG,1 ; Desactivo el flag del timer
RETURN
display2
BTFSC FLAG,1
RETURN
BCF PORTB,3 ;catodo1
MOVF DATO_UNIDADES
MOVWF PORTB ; Aca supongo que todo lo demas que no es dato esta en 0
BSF PORTB,2 ;catodo2
BCF FLAG,2 ; Activo el flag para que pase al otro display ( 1 )
BCF FLAG,1 ; Desactivo el flag del timer
RETURN
TOMAR_DATOS
MOVF PORTA ;supongo que esta en el porta el dato en el nibble bajo
ANDLW 0x0F ; solo dejo pasar el nibble bajo
MOVWF DATO_A_ENVIAR ; lo guardo en DATO_A_ENVIAR asi las demas subrutinas pueden usar el valor original que se tomo
addlw .256-.10 ; Procedo a pasarlo a BCD
BTFSC STATUS,C
addlw .6
addlw -(.256-.10) ; Final del paso a BCD
MOVWF UNIDADES ; Utilizo al registro como un registro temporal. UNIDADES = decenas:unidades
SWAPF UNIDADES,W ; Cambio de lugar los nibbles W = unidades:decenas
ANDLW 0x0F ; Elimino las unidades en W, me quedan las decenas ... W = 0:decenas
MOVWF DECENAS ; Guardo las decenas
MOVF UNIDADES ; Vuelvo a cargar todo el resultado del BCD -> decenas:unidades
ANDLW 0x0F ; Elimino las decenas W = 0:unidades
MOVWF UNIDADES ; Guardo las unidades
ENVIAR
;ENVIAR_DATO ;Aca me fijo si es de 0 a 9 asi le sumo 0x30 ('0') o si es una A a F asi le sumo una 'A' a DATO_A_ENVIAR
BTFSS TXSTA,TRMT ; Pregunto por si esta libre el USART para mandar otro dato
RETURN
MOVF DATO_A_ENVIAR
ANDLW 0x0F
SUBLW .9
BTFSC STATUS,C ; Si esta en 0 es negativo, es decir 9 - DATO_A_ENVIAR = negativo o 9 < DATO_A_ENVIAR , apartir de 10 se pondria C = 1
GOTO SUMO30
SUMOA ; el dato no es cero por lo tanto sumo A
MOVF DATO_A_ENVIAR
ADDLW .55 ; 'A' - 10
MOVWF TXREG ;Cargo el valor asi se envia
RETURN
SUMO30 ; el dato que llega es 0 entonces sumo 0x30 a dato a enviar
MOVF DATO_A_ENVIAR
ADDLW 0x30
MOVWF TXREG ;Cargo el valor asi se envia
RETURN
ANIMACION
BTFSS FLAG,0
RETURN
;Aca parecido nomas que deberia contar un poco mas ya que el otro delay es mas corto o directamente aplicar la interrupcion a este.Y el otro no hacerle un "delay"
CLRF FLAG
MOVLW .0
MOVWF UNIDADES
MOVLW .0
MOVWF DECENAS
GOTO MULTI
MULTI
BTFSS CONTADOR_DISPLAYS,0
GOTO SALTO1
GOTO DISP1
SALTO1
BTFSS CONTADOR_DISPLAYS,1
GOTO DISP2
GOTO DISP2
DISP1
BANKSEL UNIDADES
MOVF UNIDADES,0
BANKSEL PORTB
MOVWF PORTB
MOVLW B'00000010'
MOVWF CONTADOR_DISPLAYS
BSF PORTB,7
RETURN
DISP2
BANKSEL DECENAS
MOVF DECENAS,0
BANKSEL PORTB
MOVWF PORTB
MOVLW B'00000001'
MOVWF CONTADOR_DISPLAYS
BSF PORTB,6
BCF FLAG,0
RETURN
ENDMULTI
BTFSS CONTADOR_DISPLAYS,0
GOTO SALTO1
GOTO DISP1
SALTO1
BTFSS CONTADOR_DISPLAYS,1
GOTO DISP2
GOTO DISP2MULTI
BTFSS CONTADOR_DISPLAYS,0
GOTO DISP2
GOTO DISP1No me fije si esta bien, solo vi ese detalle. Ahora que lo miro te eproximaste un poco mal al tema de los 0, no necesitas 2 variables ni nada por el estilo, es simplemente poner un 0 a la salida y activar/desactivar los catodos, sin necesidad de tratarlos como 2 displays (sino como 1 solo display). ya que los numeros son iguales.
Bueno cuando tengas un tiempito mira el programa entero y me decís, parece largo pero no es tanto. Y ya arregle la parte que me dijiste
La solucion mas simple a para saber si es el programa es mirar con un osciloscopio el pin de salida, si cumple o no cuando le pedis el 100% de duty. Fijate en eso y luego si ves que no cumple con ese duty observamos el programa.
A la salida del PIC tendrias 5V o 0V, luego las caidas de tension del led es fija ( ejemplo 2V ) y lo demas deberia caer sobre la resistencia de ese led. No se que estas midiendo vos si la caida de tension del diodo o desde el pin del PIC
Por el tema de conectarlo a la PC lo haces por el UART, tenes que configurar todos los registros ( los baudios, polaridad, etc etc ) y configuras para que cuando reciba un dato active una interrupcion. Luego desde la PC le envias caracteres ASCII. esto no complica mucho, ya que si te fijas los numeros solo se le suman 0x30 hexa...
Es decir si recibis un 0x38 en la PC se escribio 8
Luego haces lo que quieras con todo lo que recibis. Por ejemplo recibir 3 caracteres y eso guardarlo en rojo, luego 3 mas y en azul y asi. lo que llega queda en un registro llamado RCREG.
Con respecto a la parte fisica busca por internet PIC MAX232 y seguro que encontras los circuitos para eso.
Tal ves esto te sirva de ejemplo:
http://www.oz1bxm.dk/PIC/628uart.htm
No, vos recibis de a 1 byte.
Si vos de la PC mandas esto: "12"
recibirias 2 bytes, 0x31 y 0x32
Luego cuando recibas podes hacer que el primer numero vaya a Var_C o que ambos numeros los convertis en binario y alamacenas en Var_C
el unico problemita que tengo es que al enviar algo atraves de una tabla DT no envio todo completo Sad cuando lo hago "paso a paso" si funciona, y no entiendo porque! otra cosa, mi programa utiliza dos interrupciones las del periferico y el timer 0, lo que sucede es que se desborda el timer aunq no le cargo ningun valor, hasta donde entendido solo empieza a contar el timer cuando le cargo algo, pero a mi se me desborda antes de tiempo, les dejo mi configuracion inicial y el codigo de enviar datos
Citarel unico problemita que tengo es que al enviar algo atraves de una tabla DT no envio todo completo Sad cuando lo hago "paso a paso" si funciona, y no entiendo porque! otra cosa, mi programa utiliza dos interrupciones las del periferico y el timer 0, lo que sucede es que se desborda el timer aunq no le cargo ningun valor, hasta donde entendido solo empieza a contar el timer cuando le cargo algo, pero a mi se me desborda antes de tiempo, les dejo mi configuracion inicial y el codigo de enviar datos
Empecemos por el TIMER1 que es lo mas facil. No veo que estes activando su interrupcion. Lo unico que veo activo es la de recepcion del UART.
Los timer por ahi difieren.. Ejemplo, el timer0 no puede ser parado. esta continuamente contando, el Timer1 es uno de los pocos que se puede parar su marcha con el bit TMR1ON. El Timer 2 tampoco puede ser detenido.
Ninguno comienza a contar cuando le cargas un valor.
MMM, espera, tenia entendido que el timer0 empezaba a contar cuando le caragba un valor, ejemplo
movlw .100
movwf TMR0
despues de ese momento es que el empezaba a contar no antes... y si lo activo, en el registro OPTION_REG
Y a que te referis a que no recibis "todo completo" cual es el problema (o que te muestra en la salida)?
Tenes que tener cuidado que si tu tabla tiene mas de 256 caracteres con un solo apuntador no vas a poder hacerlo.
Tambien El addwf PCL,f modifica solo el registro PCL, lo cual si por ejemplo tu tabla comienza en la direccion: 0x150
Solo podrias ir con esa instruccion de 0x150 a 0x1FF , solo unos 176 caracteres. En cambio un CALL/GOTO son 10bits de direccionamiento dentro del mismo OPCODE.
Lo mas seguro es que no llegues al limite de los 256 caracteres pero que tu tabla este a la mitad. Por las dudas trata de poner tu tabla al comienzo del programa, o de ultima hace un ORG 0x200/0x300 para ubicar las tablas ( y si es que tu programa no es tan largo )
Si ya pasas a 0x400+ deberias de modificar el PCLATH antes de cada call a la tabla ( mas engorroso, proba la posibilidad de ponerlo al comienzo del programa y listo.
MMM, espera, tenia entendido que el timer0 empezaba a contar cuando le caragba un valor, ejemplo
movlw .100
movwf TMR0
despues de ese momento es que el empezaba a contar no antes... y si lo activo, en el registro OPTION_REG