LCD_Visualizar en formato binario

Buenas tardes foristas,

Estoy estudiando como manejar un display lcd lm016l con el PIC16F84A, el asunto es que hay un ejercicio en el que se plantea ver un número en diferente notación y necesito verlo en formato binario, es decir con los caracteres 1's y 0's.

El programa es así: con un pulsador en RB0 incremento un contador y así mismo el LCD visualiza cada incremento del contador, inicialmente "0000". El número en binario debe contar con ocho bits, pero como hasta ahora empiezo, me decidí a hacer un conteo de un nibble, que va de "0000" hasta "1111" que son caracteres ascii y luego hacerlo para el byte, tomando un nibble a la vez.

Mi problema es que cada vez que pulso el contador se me enloquece, ya arreglé el retardo, y aunque parece suficiente hasta al grabar el micro me salta como loco, después del "0001", mi problema, no sé si sea el incremento del puntero, o que lo envío a sacar cada caracter del valor binario de las tablas DT, pero es algo que se me escapa, no sé si haya un método estándar para hacer esto, o si mi rutina es válida, o si no se debe hacer así, etc.

Este es el código que hice para visualizar cada incremento (la longitud del dato es de un nibble por ahora):




;
list p=16F84A ; list directive to define processor
#include <p16F84A.inc> ; processor specific variable definitions

__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC

;**********************************************************************************************************************************


CBLOCK 0x0c
contador
puntero

ENDC


;**********************************************************************************************************************************
ORG 0X000
GOTO INICIO

Mensajes_BIN

ADDWF PCL,1

;BIN_0000
; DT "0000"
BIN_0001
DT "0001"
BIN_0010
DT "0010"
BIN_0011
DT "0011"
BIN_0100
DT "0100"
BIN_0101
DT "0101"
BIN_0110
DT "0110"
BIN_0111
DT "0111"
BIN_1000
DT "1000"
BIN_1001
DT "1001"
BIN_1010
DT "1010"
BIN_1011
DT "1011"
BIN_1100
DT "1100"
BIN_1101
DT "1101"
BIN_1110
DT "1110"
BIN_1111
DT "1111"
FinMensajes_BIN
;**********************************************************************************************************************************
INICIO
call LCD_Inicializa

clrf contador ;este registro comienza en 0 ,es el puntero para acceder a los valores binarios del nibble

clrf puntero ;este registro comienza en 0, cuenta el # de caracteres del valor binario, que deben ser 4

movlw '0' ;el conteo esta iniciado desde "0000"
call LCD_Caracter
movlw '0'
call LCD_Caracter
movlw '0'
call LCD_Caracter
movlw '0'
call LCD_Caracter

Principal
btfss PORTB,0 ;si se oprime pulsador en RB0
goto Principal ;
suelta
btfsc PORTB,0 ;revisa que se halla soltado
goto suelta ;elimina rebote, 50ms
call Retardo_100ms

call LCD_Borra ;borra el caracter actual en lcd para visualizar otro valor, al que incrementó

incf contador,1 ;aumenta contador para que busque un nibble distinto cada vez

envia

movf contador,0 ;cargo el contador para que sea puntero de las tablas
addwf puntero,0 ;
call Mensajes_BIN ;acaben de escribir los 4 caracteres y si faltan, entonces que saque el que falta hasta que se vean

call LCD_Caracter ;los cuatro en lcd
incf puntero ;cuando sale un caracter, registra cada vez hasta que llegue al cuarto
prueba

movlw 0x04 ;puntero=4?

xorwf puntero,0 ;
btfss STATUS,Z ;
goto envia ;no, apunta al siguiente caracter
clrf puntero ;si, puntero se borra y esperamos pulso para volver a incrementar
goto Principal


include<LCD_4BIT.INC>
include<RETARDOS.INC>
end



Por favor si alguien reconoce algún error en mi código, dígame cuál es o cualquier sugerencia. De nuevo un montón de gracias por su ayuda.
 
Última edición:
Buenas tardes foristas,

Estoy estudiando como manejar un display lcd lm016l con el PIC16F84A, el asunto es que hay un ejercicio en el que se plantea ver un número en diferente notación y necesito verlo en formato binario, es decir con los caracteres 1's y 0's.

El programa es así: con un pulsador en RB0 incremento un contador y así mismo el LCD visualiza cada incremento del contador, inicialmente "0000". El número en binario debe contar con ocho bits, pero como hasta ahora empiezo, me decidí a hacer un conteo de un nibble, que va de "0000" hasta "1111" que son caracteres ascii y luego hacerlo para el byte, tomando un nibble a la vez.

Mi problema es que cada vez que pulso el contador se me enloquece, ya arreglé el retardo, y aunque parece suficiente hasta al grabar el micro me salta como loco, después del "0001", mi problema, no sé si sea el incremento del puntero, o que lo envío a sacar cada caracter del valor binario de las tablas DT, pero es algo que se me escapa, no sé si haya un método estándar para hacer esto, o si mi rutina es válida, o si no se debe hacer así, etc.

Este es el código que hice para visualizar cada incremento (la longitud del dato es de un nibble por ahora):




;
list p=16F84A ; list directive to define processor
#include <p16F84A.inc> ; processor specific variable definitions

__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC

;**********************************************************************************************************************************


CBLOCK 0x0c
contador
puntero

ENDC


;**********************************************************************************************************************************
ORG 0X000
GOTO INICIO

Mensajes_BIN

ADDWF PCL,1

;BIN_0000
; DT "0000"
BIN_0001
DT "0001"
BIN_0010
DT "0010"
BIN_0011
DT "0011"
BIN_0100
DT "0100"
BIN_0101
DT "0101"
BIN_0110
DT "0110"
BIN_0111
DT "0111"
BIN_1000
DT "1000"
BIN_1001
DT "1001"
BIN_1010
DT "1010"
BIN_1011
DT "1011"
BIN_1100
DT "1100"
BIN_1101
DT "1101"
BIN_1110
DT "1110"
BIN_1111
DT "1111"
FinMensajes_BIN
;**********************************************************************************************************************************
INICIO
call LCD_Inicializa

clrf contador ;este registro comienza en 0 ,es el puntero para acceder a los valores binarios del nibble

clrf puntero ;este registro comienza en 0, cuenta el # de caracteres del valor binario, que deben ser 4

movlw '0' ;el conteo esta iniciado desde "0000"
call LCD_Caracter
movlw '0'
call LCD_Caracter
movlw '0'
call LCD_Caracter
movlw '0'
call LCD_Caracter

Principal
btfss PORTB,0 ;si se oprime pulsador en RB0
goto Principal ;
suelta
btfsc PORTB,0 ;revisa que se halla soltado
goto suelta ;elimina rebote, 50ms
call Retardo_100ms

call LCD_Borra ;borra el caracter actual en lcd para visualizar otro valor, al que incrementó

incf contador,1 ;aumenta contador para que busque un nibble distinto cada vez

envia

movf contador,0 ;cargo el contador para que sea puntero de las tablas
addwf puntero,0 ;
call Mensajes_BIN ;acaben de escribir los 4 caracteres y si faltan, entonces que saque el que falta hasta que se vean

call LCD_Caracter ;los cuatro en lcd
incf puntero ;cuando sale un caracter, registra cada vez hasta que llegue al cuarto
prueba

movlw 0x04 ;puntero=4?

xorwf puntero,0 ;
btfss STATUS,Z ;
goto envia ;no, apunta al siguiente caracter
clrf puntero ;si, puntero se borra y esperamos pulso para volver a incrementar
goto Principal


include<LCD_4BIT.INC>
include<RETARDOS.INC>
end



Por favor si alguien reconoce algún error en mi código, dígame cuál es o cualquier sugerencia. De nuevo un montón de gracias por su ayuda.
Hola Amigo, pues te aconsejo colocar un antirebotes antes de ingresar el dato al PIC.
 
Oye, gracias, estoy tratando, pero eso del retardo ya lo implementé como suele hacerse al introducir pulsos por elementos mecánicos, los pulsadores.

El asunto es que aún no me cuenta bien, es decir, no rebota, ya veo, por ejemplo que me cuenta "0000", "0001", "0010" y siempre; no es aleatorio, pero el resto del ciclo es un desastre y de verdad me intriga qué pueda ser.

Es como si el (yo creo) registro puntero se incrementara como no debe después del segundo incremento
"0010" y no sé por qué , pues veo y según me parece, sólo va de 0 a 4 y reinicia, y sólo aumenta en función de el caracter obtenido.

Intenté direccionar sin el "puntero", pero queda mal y saca "0000"/"1111", ahora entonces el problema debe estar en ese bendito "puntero" algo debo hacer para garantizar que incremente lo que debe y cuando debe.

Lo que no sé es qué deja de hacer el código después del segundo incremento o qué cosa nueva pasa para que se me enloquezca y me direccione mal a los caracteres.
 
¿Lo has simulado en algún programa de simulación? Proteus es una buena herramienta en estos casos para ir "depurando" el programa poco a poco e ir aislando las posibles fallas. En cuanto a tu programa, la posición de la tabla "mensajes" se me hace sospechosa al inicio, trata de ponerla hasta el último de programa. Saludos
 
Saludos por que no utilizar una funcion donde imprimas el dato asi:
1.-Recorremos el dato el numero de veces necesarias a la izquierda para que quede en el MSB( el MSB para que se vea primero en la pantalla de izquierda a derecha ;)).
2.-Filtramos el dato con un 0x80 para que solo tome en cuenta el MSB.
3.-Tenemos un 0x80 o un 0x00 obligatoriamente solo nos queda recorrerlo a la posicion LSB (7 a la derecha) para poder usarlo en los pasos siguientes.
4.-Escribimos el dato (No se que funcion se use en los pics igual toma esa de write_LCD como la funcion de escritura donde le ponemos el dato que queremos ver en el LCD en ASCII) si como decia escribimos el dato que tenemos 1 o 0 si le sumamos 0x30 lo convertimos a su valor ASCII para poder visualizarlo.
5.-Repetir lo mismo hasta haber hecho lo mismo con los 8 bits.

Esto es sin un for, igual se optimiza con un for.
Código:
void imprime_binario(unsigned char dato)
{
	unsigned char dato_temp;
	
	dato_temp=dato&0x80;
	dato_temp=dato_temp>>7;
	write_LCD(dato_temp+0x30);
	dato_temp=dato<<1;
	dato_temp=dato_temp&0x80;
	dato_temp=dato_temp>>7;
	write_LCD(dato_temp+0x30);
	dato_temp=dato<<2;
	dato_temp=dato_temp&0x80;
	dato_temp=dato_temp>>7;
	write_LCD(dato_temp+0x30);
	dato_temp=dato<<3;
	dato_temp=dato_temp&0x80;
	dato_temp=dato_temp>>7;
	write_LCD(dato_temp+0x30);
	dato_temp=dato<<4;
	dato_temp=dato_temp&0x80;
	dato_temp=dato_temp>>7;
	write_LCD(dato_temp+0x30);
	dato_temp=dato<<5;
	dato_temp=dato_temp&0x80;
	dato_temp=dato_temp>>7;
	write_LCD(dato_temp+0x30);
	dato_temp=dato<<6;
	dato_temp=dato_temp&0x80;
	dato_temp=dato_temp>>7;
	write_LCD(dato_temp+0x30);
	dato_temp=dato<<7;
	dato_temp=dato_temp&0x80;
	dato_temp=dato_temp>>7;
	write_LCD(dato_temp+0x30);
	
		
}

aca esta ya con un for como quieras

Código:
void imprime_binario(unsigned char dato)
{
	unsigned char dato_temp, i;
	
	for(i=0; i<8; i++)
	{
	dato_temp=dato<<i;
	dato_temp=dato_temp&0x80;
	dato_temp=dato_temp>>7;
	write_LCD(dato_temp+0x30);
	}
		
		
}

Ahi me cuentas como funciono si existe algun bug o error aqui estamos para ayudarte ;)
 
Última edición:
Oye, gracias, estoy tratando, pero eso del retardo ya lo implementé como suele hacerse al introducir pulsos por elementos mecánicos, los pulsadores.

El asunto es que aún no me cuenta bien, es decir, no rebota, ya veo, por ejemplo que me cuenta "0000", "0001", "0010" y siempre; no es aleatorio, pero el resto del ciclo es un desastre y de verdad me intriga qué pueda ser.

Es como si el (yo creo) registro puntero se incrementara como no debe después del segundo incremento
"0010" y no sé por qué , pues veo y según me parece, sólo va de 0 a 4 y reinicia, y sólo aumenta en función de el caracter obtenido.

Intenté direccionar sin el "puntero", pero queda mal y saca "0000"/"1111", ahora entonces el problema debe estar en ese bendito "puntero" algo debo hacer para garantizar que incremente lo que debe y cuando debe.

Lo que no sé es qué deja de hacer el código después del segundo incremento o qué cosa nueva pasa para que se me enloquezca y me direccione mal a los caracteres.

Hola Amigo te consulto lo sig. En la tabla de asignaciones de binarios, no veo la instruccion RETLW. Ademas es necesario acudir a una tabla?, si bien podrias enviar el valor del registro CONTADOR, al display.-
 
Atrás
Arriba