# Problema visualizando bcd en 7 segmentos con pic 16f877



## dragondgold (Jul 16, 2009)

hola hace unos dias aprendi a utilizar el pic 16f877 y he estado usando el conversor a/d y me dijeron q para ver el voltaje debería pasar el código binario a bcd... hasta ahi voy bien pero yo lo quiero visualizar en 7 segmentos y no lo puedo lograr... he visualizado numeros del 1 al 9 pero cuando quiero ver un 12 por ejemplo me muestra cualquier cosa se me ha ocurrido que al numero 25 por ejemplo hacer una rutina que le valla restando un numero y cuando sea 0 yo se q ese es el numeor y lo visualizo me entienden? pero seria un programa muy largo no hay otra manera? seria mejor verlo en un lcd? ayuda pls estoy desesperado!


----------



## jesus_lomor (Jul 16, 2009)

que tal.. bueno espero te siga lo siguiente.
puedes crear una subrutina encargada para la conversion de binario a bcd...
ahi te va el procedimiento...
selecciona el valor maximo que puede tomar tu numero binario. ejemplo. .255=0b11111111
vas a iniciualizar tres registros para guardar el valos de centenas, decenas y unidades...
empiezs por sacar las centenas..
1. restale 100 al valor a convertir, (255-100)=155 si el resultado de la resta es positivo, incvrementa en una unidad las centenas y vuelve a hacer la resta. si el resultado es negativo, entonces no incrementas las centenas.
2.al numero negativo obtenido de la ultima resta, le sumas 100 (-55+100=55)(para hacerlo positivo de nuevo). despues restale 10 (55-10=45) si el resultado es positivo aumenta en una unidad las decenas, y vuelve a hacer el proceso de restar 10 e incrementar; Ahora bien, si el resultado es negativo, no incrementes las decenas y pasa al siguiente punto.
3.al resultado negativo le sumas 10 (-5+10=5), y ese va a ser tu registro de unidades. 

despues de haber hecho la conversion... creas una tabla.. como si fuera una subrutina..
Tabla
        addwf pcl,1
        retlw 0b(cod7seg1)
        retlw 0b(cod7seg2)
        retlw 0b(cod7seg3)
        .
        .
        .
esta lo que hace es que cuando la llamas, el puntero de programa se posiciona en la linea de addwf, y apartir de ahi, el valor que tienes cargado en w, se le suma al contador de programa y estop produce un salto de linea a partir de esa posicion.. y con el retlw, es como un return solo que te regresa el valor binario que tienes especificado en el registro W, y ese deberia de ser el codigo 7 segmentos del numero correspondiente.

espero y te sirva la información, algoritmo y ademas sea el lenguaje que manejas.. saludos!


----------



## dragondgold (Jul 16, 2009)

gracias por la información yo ya tengo un programa q pasa de binario a bcd que saque de una nota de apliacion de microchip que convierte binario de 16 bits a bcd servira ese mismo programa para convertir 10 bits? y lo de la tabla no lo entendi porque aun no se si se puede visualizar por ejemplo el numero 22 o si debo multiplexar he ir mostrando un 2 en cada digito y si debo multiplexar debo dividir el resultyado bcd que me da el programa en 2 por ejemplo:

si en el registro bcd1 yo tengo el numero 22 debo dividirlo para saber que numeros tengo y mostrarlos haciendo lo que era mi idea ejemplo:
si tengo el numero 22 decremento 7 y no me da 0 por lo tanto el numero no es 7 entonces voy siguiendo con todos los numeros hasta llegar al 22 y cuando haga que reste 22 me va a dar 0 entonces yo se que tengo q mostrar en los 7 segmentos dos numeros 2 para ver un 22
pero seria un programa muy largo ya que tengo que hacer los numeros del 1 al 99 no? no hay otra forma? seria mas facil con un lcd?


----------



## jesus_lomor (Jul 17, 2009)

bueno... para diez bits, no hay problema, puedes usar el de 16 bits!
mira el programa convertidor de binario a bcd, lo que te va a hacer es apartir de un numero binario de 16 bits.. puede ser 0000 0000 0000 0001, o cualquier convinacion, te va a transformar eso en en digitos bcd.
en el caso de que tengas que convertir 10 bits, tu tendras el valor de 16bits como el que sigue:
0000 00xx xxxx xxxx, donde la x representa un 0 o un 1. cuando todos son 1, tu tienes un valor maximo de 1023. osea 4 registros bcd.. uno para las unidades, otro para las decenas, otro para las centenas, y otros para los millares.
por ejemplo
reg de millares: 0x20=1
reg de centenas: 0x21=0
reg de decenas: 0x22=2
reg de unidades: 0x23=3

esos ultimos registros son los que te deberia arrojar tu convertidor bin2bcd de 10 bits.
ahora... en una tabla como la que sigue

tabla ;recibe w
.....addwf pcl,1;hace un salto de w+1 lineas
     retlw (codigo 7segmentos para 0)
     retlw (codigo 7seg para 1)
     retlw (cod 7 seg para 2)
     .
     .
    .

bueno, lla tienes por separado el numero de millares, centenas decenas y unidades...
cuando quieras por ejemplo sacar el codigo bcd para el numero de millares, lo que haces es lo siguiente

movf 0x20,w  copias el valor del registro de millares a w
call tabla  llamas a la subrutina de la tabla
movwf portb reflejas el resultado de 7 seg arrjado por la tabla en el puerto b

los mismo tienes que haces para los registros 0x21 centenas, 0x22 decenas y 0x23 unidades..

ahora, si con la misma salida del puerto b, quieres que sean los datos para todos los 4 displays, tienes que controlar el encendido de cada display. osea el comun.

para esto, conecta por ejemplo, 1 salida de el puerto c para cada comun del display.
si tu display es catodo comun, por ejemplo, lo que tienes que hacer es mandarle un 0 ala salida del puerto c que esta conectada al catodo comun del display, y mandar el dato que debe de mostrar el display, si quiertes cambiar de display, solo mandale un 0 al display que desees, y pon en 1 el catodo comun del anterior para que no se encienda, y puedes rrefrescar la informaciónque se mostrara en ese display mediante el puertob.

espero no sea engorroso el tema.. saludos


----------



## dragondgold (Jul 17, 2009)

muchas gracias! ya entendi solucionaste mi problema ahora tengo una duda mas xd. cuando yo paso a bcd ese es directamente el voltaje que toma el conversor a/d o hay que hacerlo algo mas para q me muestre el voltaje?


----------



## dragondgold (Jul 17, 2009)

disculpame queria saber si no es mucha molestia que revisaras mi programa porque no anda muestra cualquier numero si yo tengo en 8 bits un 11111111 no deberia tener un 255 en bcd me gustaria que lo revisaras porque ya no se que hacerle no anda....


```
list			p=16F877A
			include			"P16F877A.INC"

;======================================================================================
;=							POSICIONES DE MEMORIA									  =
;======================================================================================
porta			equ				05						;defino los puertos
portb			equ				06
portc			equ				07
portd			equ				08
porte			equ				09
trisa			equ				85h						;configuracion de los puertos
trisb			equ				86h				
trisc			equ				87h
trisd			equ				88h
trise			equ				89h
DATOSH			equ				0x25
TIME			equ				0x20
BCD_UNIDADES	equ				0x22					;variables de salida para BCD
BCD_DECENAS		equ				0x23
BCD_CENTENAS	equ				0x24
;======================================================================================
;=							PROGRAMA PRINCIPAL										  =			
;======================================================================================
			org				0
			goto			INICIO
INICIO		clrf			porta					;limpia salidas
			clrf			portb
			clrf			portc
			clrf			portd
			clrf			porte
			bsf				STATUS,RP0				;banco 1
			bcf				STATUS,RP1
			movlw			b'00000110'				;puerto A en modo E/S digitales
			movwf			ADCON1					
			movlw			b'11111111'
			movwf			trisa
			clrf			portb
			clrf			portc
			clrf			portd
			clrf			porte
			movlw			b'00000101'				;justifico resultado a la izquierda
			movwf			ADCON1					;RA0 y RA1 entradas analogas y RA3 Vref+
			bcf				STATUS,RP0				;banco 0
			movlw			b'11000001'				;oscilador RC canal RA0/AN0 como entrada
			movwf			ADCON0					;y conversor activado
			nop
COMIENZA	clrf			DATOSH
			bsf				ADCON0,GO				;inicia conversion
ADC_WAIT	btfsc			ADCON0,2				;ha terminado la conversion?
			goto			ADC_WAIT				;NO, ESPERAR
			bcf				STATUS,RP0				;banco 0
			bcf				STATUS,RP1
			movf			ADRESH,W				;tomo el dato obtenido y lo muevo
			movwf			DATOSH					;a RAM
			call			DELAY					;delay para iniciar otra conversion
			call			BIN_a_BCD				;paso el resultado binario a BCD
			call			VISU					;visualizo en 7 segmentos
			call			DELAY					;delay
			goto			COMIENZA				;vuelve a hacer otra conversión
;======================================================================================
;=							RUTINAS													  =
;======================================================================================
DELAY		clrwdt
			movlw			.255
			movwf			TIME
			decfsz			TIME
			clrwdt
			return
;======================================================================================
BIN_a_BCD	clrf			BCD_CENTENAS
			clrf			BCD_DECENAS
			movf			DATOSH,W
			movwf			BCD_UNIDADES
BCD_RESTA10	movlw			.10
			subwf			BCD_UNIDADES,W
			btfss			STATUS,C
			goto			BIN_BCD_FIN
BCD_INCDE	movwf			BCD_UNIDADES
			incf			BCD_CENTENAS,F
			movlw			.10
			subwf			BCD_CENTENAS,W
			btfss			STATUS,C
			goto			BCD_RESTA10
BCD_INCCEN	clrf			BCD_DECENAS
			incf			BCD_CENTENAS,F
			goto			BCD_RESTA10
BIN_BCD_FIN	swapf			BCD_DECENAS,W
			addwf			BCD_UNIDADES,W
			clrwdt
			return
;======================================================================================
VISU		        clrf			portd
			clrf			portb
			movf			BCD_UNIDADES,W
			movwf			portb
			bsf				portd,0
			bcf				portd,0
			movf			BCD_DECENAS,W
			movwf			portb
			bsf				portd,1
			bcf				portd,1
			movf			BCD_CENTENAS,W
			movwf			portb
			bsf				portd,2
			bcf				portd,2
			clrwdt
			return
;======================================================================================
			end
```


----------



## jesus_lomor (Jul 17, 2009)

parece bien el codigo... mas tarde lo checare con detalle

el resultado que te va a arrojar el convertidor analogico digital no es el voltaje, si no, un numero entre 0 y 1023 (para 10 bits), o si justificas hacia la izquierda (cargar el resultado a adresh), puedes tomar solamente el resultado convertido en el adresh, que me parece que es lo que estas haciendo, y este entonces te arrojaria un resultado entre 0 y 255.
lo que tienes que hacer para sacar el voltaje es la siguiente operacion:

si usas 8 bits: (adresh)*Vref/255  esto significa que cuando el resultado de la conversion haya sido el maximo, osea 255, el voltaje sensado es Vref (sustituyendolo en la formula).

si usas un voltaje de referencia de 5 volts, solamente podiras multiplicar por dos la cantidad, o sumarsea asi misma.. es decir adresH*2=adresh+adresh, esto te dejaria un lijero error.. pero por ejemplo.. si obtuviste en adresh 255, esto significaria que tienes un voltaje de 5volts.
adresh*2=510 solo le afregarias el punto decimal, para que te quedara lo siguiente 5.10
si tu adresh=128
adresh*2=256 entonces tu mostrarias 2.56 volts, solamente la variacion seria 1.02 veces mas de lo que realmente tienes en la entrada del conversor.

No se que software estes usando, pero te recomiendo que uses el debugger(del mismo sw) para ver si realmente estas configurando todo como debe de ser.. si usas mblab, activa en el menu debbuger, select tool, mplab sim, este te añadira la barra de erramientas para simular el programa. en view, file registers estan todos los valores de la memoria del pic, y y ahi mismo pero en especial function register estan todos los registros de configuracion. saludos!
otra cosa.. no se si lo hagas o no, pero aqui en el foro no se puede apreciar, las etiquetas ponlas en una sola linea (labels), las instrucciones en otra linea distinta al de las etiquetas, y separadas por el tabulador, parece que eres ordenado al trabajar en la programacion y eso habla bien de ti como programador, saludos!


----------



## dragondgold (Jul 20, 2009)

gracias por tu ayuda me ha sido muy util lo que yo tenia pensado y me parece que tal vez seria mas preciso es que el pic me haga una regla de tres simples xd es decir:

255---------5v               es decir que si 255 es el máximo o sea 5v q es vref que voltaje es lo que me da el
200---------x                 conversor o sea deberia hacer 200 por 5 dividido 255 y me daria el voltaje es correcto?
lo que yo no se es como podria saber yo el numero porque ese ha sido siempre mi problema si el microcontrolador me da un binario y lo paso a bcd me da por ejemplo los tres numeros separados en tres registros 2 - 5 - 5 peor como hago yo para saber que eso es un 255 y no simplemente todos numeros separados sin tener que visualizarlos?


----------



## jesus_lomor (Jul 20, 2009)

para tu darte cuenta?.. pues tienes de 2... 
1)a partir de un puerto sobrante de 8 bits, sacar la información obtenida de la conversion mediante leds..ejem. 255=1111 1111
2)apartir de 12 salidas del pic...reflejar cada uno de los valores en bcd por ejemplo
2-5-5=0010-0101-0101 esto tambien lo deberias visualizar en leds...

en cuanto a lo que propones de la regla de tres, es buena la idea, solo que tienes que programar la division y multiplicacion.


----------



## dragondgold (Jul 21, 2009)

muchas gracias la verdad que sabes mucho y me esta sirviendo de mucho la información como hago para que el pic multiplique y divida porque no se hacer eso es muy complicado? porque no hay ninguna instruccion que dividad y multiplique o si?


----------



## jesus_lomor (Jul 21, 2009)

El pic 16f877 solamente trae integrada la suma y la resta, por tanto tienes que hacer por sw la multiplicacion y division.. la multiplicacion, cuando es por numeros enteros, es sencilla, ya que solamente tienes que sumar x veces el mismo numero, pero ocuparias 2 registros de 8 bits para almacenar el resultado de la multiplicacion. en cuanto a la division, pues lo haces similar a la conversion bin a bcd, para saber cuantas "veces cabe", el probblema aqui, es como manejar los decimales.
ejemplo si te dio adresh=255
adresh*5=1275=0x4fb=adresh+adresh+adresh+adresh+adresh
ahora se divide entre el numero de conversion maximo que es 255.

1275-255=1020... cupo 1 ves
1020-255=765... cupo 2 ves
765-255=510... cupo 3 ves
510-255=255... cupo 4 ves
255-255=0... cupo 5 ves

esto quiere decir que el resultado es 5 volts...
si a lo ultimo te hubiera quedado, por ejemplo
15-255=-240, aqui multiplicarias el 15 por 10, y apartir de ahi empezaria tu resultado del 5.x

tienes que analizar mas a fondo este tema de la division.. saludos!


----------



## dragondgold (Jul 21, 2009)

si eso parece la divicion es mas complicada no es mas facil dividir el numero binario y luego pasarlo a bcd? es lo mismo o hay otro metodo y te dejo asi no te jodo mas con preguntas...


----------



## jesus_lomor (Jul 21, 2009)

en el post ·11 precisamente la division  es entre numeros binarios, si te das cuenta, se esta manejando dirwectamente el adresh.y esto mismo, te permitira no recurrir a la conversion binario a bcd..
seria una conversion mas bien binario a voltaje...
igual puede ser un segundo subprograma..
el primero que te despliegue el valor de reg adresh en los displays 7 seg
y el segundo que te despliegue el valor de voltaje medido, con un max de 5 volts
saludos!


----------

