estos son mis archivos en asm,donde simulo una entrada por el canal RA0, Y lo visualizo en un LCD
RB -> LCD DATA
; RA0 -> ENTRADA AL CONVERSOR A/D
; RA1 -> LCD RS
; RA2 -> LCD RW
; RA3 -> LCD E
List P=16F876A
Include "P16F876A.INC"
LCD_VAR equ 0x23
DELAY_VAR equ 0x25
DIGITAL equ 0x2A
DIVIDENDO equ 0x2B
DIVISOR equ 0x2C
COCIENTE equ 0x2D
RESIDUO equ 0x2E
DIV_CONTA equ 0x2F
W_TEMP equ 0x30
STATUS_TEMP equ 0x31
PCLATH_TEMP equ 0x32
UNIDADES equ 0x33
DECIMOS equ 0x34
#Define BANCO_H bsf STATUS,RP1
#Define BANCO_L bcf STATUS,RP1
#Define BANCO1 bsf STATUS,RP0
#Define BANCO0 bcf STATUS,RP0
errorlevel -302
#Define PAG0 clrf PCLATH
#Define PAG1 bsf PCLATH,0
#Define PAG2 bsf PCLATH,1
#Define LCD_DATA PORTB
#Define LCD_CTRL PORTA
__config (_CP_OFF & _DEBUG_OFF & _WRT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_ON & _PWRTE_ON & _WDT_OFF & _XT_OSC)
;++++++++++++++++++++++++++++
org 0x0000
goto INICIO
org 0x0005
;************************************************************************************************
; PROGRAMA PRINCIPAL
;************************************************************************************************
INICIO BANCO_L
BANCO1
movlw 0x0E
movwf ADCON1
movlw B"000001"
movwf TRISA
movlw B"11010111"
movwf OPTION_REG
BANCO0
movlw 0x41
movwf ADCON0
call LCD_UP
call LCD_INI
call LCD_CLEAR
movlw MENS_CONV
PAG1
call LCD_MENSAJE ;Visualiza "Mueva El Potenciometro"
PAG0
movlw .2
call DELAY_S
call LCD_CLEAR
movlw 0x40
call LCD_SETDDADDRESS
movlw MENS_VOLT
PAG1
call LCD_MENSAJE ;Visualiza "VOLTAJE RA0: 0,0"
PAG0
CONVIERTE bsf ADCON0,2
movlw .30
call DELAY_US
btfsc ADCON0,2
goto $-1
movf ADRESH,W
movwf DIGITAL
call BINTOASCII
movlw 0x4D
call LCD_SETDDADDRESS ;Reposiciona cursor del LCD
movf UNIDADES,0
call LCD_WRITEDATO
movlw ","
call LCD_WRITEDATO
movf DECIMOS,0
call LCD_WRITEDATO
goto CONVIERTE
;
;-------------------------------------------------------------------------
BINTOASCII movf DIGITAL,0
movwf DIVIDENDO
movlw .51
movwf DIVISOR
call DIV
movf COCIENTE,0
PAG2
call LCD_TABNUM
PAG0
movwf UNIDADES
movf RESIDUO,0
movwf DIVIDENDO
movlw .5
movwf DIVISOR
call DIV
movf RESIDUO,0
sublw .2
btfsc STATUS,C
goto $+9
movlw .9
xorwf COCIENTE,0
btfss STATUS,Z
goto $+4
clrf COCIENTE
incf UNIDADES,1
goto $+2
incf COCIENTE,1
movf COCIENTE,0
PAG2
call LCD_TABNUM
PAG0
movwf DECIMOS
return
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; SUBRUTINAS INTERNAS DEL ADC
;************************************************************************************************
;DIV: Divide el número DIVIDENDO entre DIVISOR, dando como resultados los números COCIENTE y
; RESIDUO.
DIV movf DIVIDENDO,0
movwf RESIDUO
clrf COCIENTE
clrf DIV_CONTA
incf DIV_CONTA,1
ROTAMAS bcf STATUS,C
rlf DIVISOR,1
btfsc STATUS,C
goto DIV_ATAJO
incf DIV_CONTA,1
movf DIVISOR,0
subwf RESIDUO,0
btfsc STATUS,C ;¿Se rotó demasiado?
goto ROTAMAS ;No, todoavía no se pasa
DESROTAR bcf STATUS,C
rlf COCIENTE,1
decf DIV_CONTA,1
bcf STATUS,C
DIV_ATAJO rrf DIVISOR,1
movf DIVISOR,0
subwf RESIDUO,0
btfss STATUS,C
goto DIV_TERMINA
movwf RESIDUO
bsf COCIENTE,0
DIV_TERMINA decfsz DIV_CONTA,0
goto DESROTAR
return
;
;************************************************************************************************
; TABLAS
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
org 0x100
MENS_CONV equ $
dt "Mueva El Potenciometro",0x00
MENS_VOLT equ $
dt "VOLTAJE RA0: 0,0",0x00
;
;-------------------------------------------------------------------------
org 0x200
Include "LCD8.INC"
org 0x300
Include "DELAY.INC"
END
a qui estan los archivos por incluir:
RETARDOS DE TIEMPO
;************************************************************************************************
;****************************************************************************************
; DELAY.INC
;
; ;
; Se tendrá las siguientes rutinas:
; - DELAY_US
; - DELAY_MS
; - DELAY_S
;Estas rutinas controlan los tiempos de retardo en microsegundos,
;milisegundos y en segundos. La cantidad microsegundos, de milisegundos
;o segundos toma del acumulador.
;NOTA: ESTOS TIEMPOS RESULTAN DEL USO DE UN RELOJ DE 4MHz (ciclo de
;instrucción de 1MHz).
;Guarda el registro OPTION en uno temporalal entrar para cargarlo al salir.
;DELAY_VAR EQU dir_inicio_del_bloque
; BLOQUE DE ETIQUETAS
CBLOCK DELAY_VAR ;Inicio de las variables. La primera dirección libre disponible
DELAY_TEMP_1
DELAY_TEMP_2
OPTION_TEMP
ENDC
;RUTINA DELAY_uS: Se trata de un rutina que implementa un retardo
;o temporización en uS. Utiliza la variable DELAY_TEMP_1 que se va
;decrementando hasta alcanzar el tiempo del acumulador dado en uS.
DELAY_US movwf DELAY_TEMP_1
bcf STATUS,C
rrf DELAY_TEMP_1,1
bcf STATUS,C
rrf DELAY_TEMP_1,1
DELAY_U1 nop
decfsz DELAY_TEMP_1,F
goto DELAY_U1
return
;RUTINA DELAY_uS: Esta rutina implementa un retardo o temporización
;en uS. Utiliza la variable DELAY_TEMP_1 que se va decrementando
;hasta alcanzar el tiempo del acumulador dado en mS.
DELAY_MS movwf DELAY_TEMP_1
BANCO1
movf OPTION_REG,W
movwf OPTION_TEMP
movlw B"11010001"
movwf OPTION_REG
BANCO0
DELAY_M1 clrwdt
clrf TMR0
bcf INTCON,T0IF
DELAY_M2 btfss INTCON,T0IF
goto DELAY_M2
decfsz DELAY_TEMP_1,F
goto DELAY_M1
BANCO1
movf OPTION_TEMP,W
movwf OPTION_REG
BANCO0
return
;RUTINA DELAY_S: Se trata de un rutina que implementa un retardo
;o temporización en S. Utiliza las variables DELAY_TEMP_1 y DELAY_TEMP_2
;que se van decrementando hasta alcanzar el tiempo del acumulador dado en S.
DELAY_S movwf DELAY_TEMP_1
BANCO1
movf OPTION_REG,W
movwf OPTION_TEMP
movlw B"11010011"
movwf OPTION_REG
BANCO0
DELAY_1 clrf DELAY_TEMP_2
DELAY_2 clrwdt
bcf INTCON,T0IF
clrf TMR0
DELAY_3 btfss INTCON,T0IF
goto DELAY_3
decfsz DELAY_TEMP_2,F
goto DELAY_2
decfsz DELAY_TEMP_1,F
goto DELAY_1
BANCO1
movf OPTION_TEMP,W
movwf OPTION_REG
BANCO0
return
LCD HITACHI HD44780A 2 X 16 o 1 X 16 8 bits de datos
;************************************************************************************************
;****************************************************************************************
; LCD8.INC
;
; ;
;Presenta un conjuntos de rutinas que permiten realizar las tareas de control del mòdulo
;de visualización LCD. Con la llamada a LCD_UP se configura para su uso y con la rutina LCD_INI
;se inicializa el LCD. Y la rutina MENSAJE visualiza un mensaje dado en una tabla.
;Las demás rutinas son las de principal uso de control. NOTA: Definir con "Define" los puertos
;LCD_DATA y LCD_CTRL, y en caso de tener cuatro bancos poner RP1 a 0 antes de LCD_UP si es necesario.
;
;Este fichero se debe incluir en los futuros programas fuente mediante la directiva INCLUDE.
;
;LCD_UP: Configura los puertos A y B, y el INTCON para el uso del LCD.
;
;LCD_INI: Inicializa el LCD. Espera 15ms (riso a 4.5V), configura # de bits de datos y # de
; lineas activas.
;
;LCD_MENSAJE: Esta rutina saca al LCD el mensaje cuyo inicio esta indicado en el acumulador. Se
; aconseja para cada mensaje el siguiente formato:
; MENS equ $ ó MENS equ $
; retlw "O" dt "OK",0x00
; retlw "K"
; retlw 0x00
; Y debe hacer "movlw MENS" antes de la llamada "call MENSAJE"
;
;LCD_CLEAR: Borra el display y retorna el cursor a la posicion 0.
;
;LCD_HOME: Retorna el cursor a la posicion 0.
;
;LCD_ENTRYMODE: Configura el modo de ingreso al display.
; El modo de funcionamiento deseado deberá cargarse en los 2 bits menores de W:
; x x x x x x b1 b0
; b0 : 0 = no desplazamiento del display 1 = desplazamiento
; b1 : 0 = autodecremento del cursor 1 = autoincremento
; b2-7 : sin importancia
;
;LCD_DISPCURSCONT: Enciende o apaga el display, cursor y parpadeo.
; El modo de control deseado deberá cargarse en los 3 bits menores de W:
; x x x x x b2 b1 b0
; b0 : 0 = no parpadeo del cursor 1 = parpadeo
; b1 : 0 = apagar cursor 1 = encender cursor
; b2 : 0 = apagar display 1 = encender display (los datos siguen en DDRAM)
; b3-7 : sin importancia
;
;LCD_DISPCURSSHIFT: Mueve el cursor o el display.
; El modo de control deseado deberá cargarse en los 2 bits terceros de W:
; x x x x b3 b2 x x
; b2 : 0 = mueve al a izquierda 1 = a la derecha
; b3 : 0 = mueve cursor 1 = mueve display
; b0,1,4-7 : sin importancia
;
;LCD_SETCGADDRESS: Fija la dirección de la CGRAM. La dirección de la CGRAM puede ser
; leída/escrita después de este comando
; La dirección deseada deberá estar en el registro W:
; x x b5 b4 b3 b2 b1 b0
; b0-5 : dirección de la CGRAM
; b6-7 : sin importancia
;
;LCD_SETDDADDRESS: Fija la dirección de la DDRAM. La dirección de la DDRAM puede ser
; leída/escrita después de este comando
; La dirección deseada deberá estar en el registro W:
; x b6 b5 b4 b3 b2 b1 b0
; b0-6 : dirección de la DDRAM
; b7 : sin importancia
;
;LCD_READAC: Obtiene en W el valor de AC.
;
;LCD_WRITEDATO: Escritura de datos de W en la DDRAM o CGRAM
; W = DATO
; LCD_DATA <== W
;
;LCD_READDATO: Lectura de datos de la DDRAM o CGRAM y lo pasa a W
; LCD_DATA = DATO
; W <== LCD_DATA
;
;LCD_TABNUM: Convierte el número HEXADECIMAL que este en W a su equivalente ASCII.
; OjO: No olvidar chequear el PCLATH por tratarse de asignación al PC por istrucción.
;
#define ENABLE bsf LCD_CTRL,3 ;Activa E
#define DISABLE bcf LCD_CTRL,3 ;Desactiva
#define LEER bsf LCD_CTRL,2 ;Pone LCD en Modo RD
#define ESCRIBIR bcf LCD_CTRL,2 ;Pone LCD en Modo WR
#define DATO bsf LCD_CTRL,1 ;Desactiva RS (modo comando)
#define COMANDO bcf LCD_CTRL,1 ;Activa RS (modo dato)
cblock LCD_VAR
LCD_TEMP1 ;Registro temporal de posicion de la tabla
LCD_TEMP2 ;Registro temporal del caracter ASCII
endc
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; SUBRUTINAS DEL LCD
;************************************************************************************************
LCD_UP BANCO1
clrf LCD_DATA ;RB <0-7> salidas digitales
movlw B"11110001"
andwf LCD_CTRL,F ;RA0=RS RA1=R/W RA2=E salidas digitales
BANCO0
bcf INTCON,GIE ;Desactivar interrupciones
COMANDO ;RS=0
ESCRIBIR ;R/W=0
DISABLE ;E=0
return
;
;-------------------------------------------------------------------------
LCD_INI movlw 0x0F
call DELAY_MS ;Espera un poco más de 15ms
movlw B"00111000" ;Datos de 8 bits, 2 lineas y caracteres de 5x7
call LCD_COMAND
movlw 0x05
call DELAY_MS ;5ms > 4.1ms.(Especificacion de Fabricante)
movlw B"00111000" ;Datos de 8 bits, 2 lineas y caracteres de 5x8
call LCD_COMAND
movlw .110
call DELAY_US ;110us > 100us.(Especificacion de Fabricante)
movlw B"00111000" ;Datos de 8 bits, 2 lineas y caracteres de 5x8
call LCD_COMAND
movlw B"00001000" ;b3 y b2 puedn ser cambiados para otra configuración
call LCD_FUNCIONSET ;después de este punto no podran ser cambiados N ni F
movlw B"00000100" ;Cursor apagado y Display prendido
goto LCD_DISPCURSCONT
;
;-------------------------------------------------------------------------
LCD_MENSAJE movwf LCD_TEMP1 ;Salva posicion de la tabla
M_E_N_S movf LCD_TEMP1,0 ;Recupera posicion de la tabla
call LCD_TABLA ;Busca caracter de salida
movwf LCD_TEMP2 ;Guarda el caracter
movf LCD_TEMP2,1
btfsc STATUS,Z ;¿Hay más caracteres?
return ;No, fue el último
call LCD_WRITEDATO ;Visualiza en el LCD el caracter
incf LCD_TEMP1,1 ;Siguiente caracter
goto M_E_N_S ;Repite con siguiente caracter
LCD_TABLA movwf PCL ;Desplazamiento sobre la tabla
;
;-------------------------------------------------------------------------
LCD_CLEAR movlw B"00000001" ;Borra LCD y cursor a Home
goto LCD_COMAND
;
;-------------------------------------------------------------------------
LCD_HOME movlw B"00000010" ;Cursor a Home
goto LCD_COMAND
;
;-------------------------------------------------------------------------
LCD_ENTRYMODE andlw 0x03 ;Nos quedamos con b1-b0
iorlw 0x04 ;Incorporamos el bit de función
goto LCD_COMAND
;
;-------------------------------------------------------------------------
LCD_DISPCURSCONT andlw 0x07 ;Nos quedamos con b2-b1-b0
iorlw 0x08 ;Incorporamos el bit de función
goto LCD_COMAND
;
;-------------------------------------------------------------------------
LCD_DISPCURSSHIFT andlw 0x0C ;Nos quedamos con b3-b2
iorlw 0x10 ;Incorporamos el bit de función
goto LCD_COMAND
;
;-------------------------------------------------------------------------
LCD_SETCGADDRESS andlw 0x3F ;Nos quedamos con b5-b4-b3-b2-b1-b0
iorlw 0x40 ;Incorporamos el bit de función
goto LCD_COMAND
;
;-------------------------------------------------------------------------
LCD_SETDDADDRESS iorlw 0x80 ;Incorporamos el bit de función
goto LCD_COMAND
;
;-------------------------------------------------------------------------
LCD_READAC call LCD_BUSY
LEER
BANCO1
comf LCD_DATA,1 ;Puerto B como entrada
BANCO0
ENABLE
nop
movf LCD_DATA,0
andlw 0x7F ;Valor de la dirección de la DDRAM o CGRAM
DISABLE
BANCO1
clrf LCD_DATA
BANCO0
ESCRIBIR
return
;
;-------------------------------------------------------------------------
LCD_WRITEDATO movwf LCD_DATA ;Valor a escribir en la DDRAM o CGRAM
call LCD_BUSY
DATO
goto LCD_E ;Genera pulso de E
;
;-------------------------------------------------------------------------
LCD_READDATO call LCD_BUSY
DATO
LEER
BANCO1
comf LCD_DATA,1 ;Puerto B como entrada
BANCO0
ENABLE
nop
movf LCD_DATA,0 ;Valor leido de la DDRAM o CGRAM
DISABLE
BANCO1
clrf LCD_DATA
BANCO0
ESCRIBIR
COMANDO
return
;
;-------------------------------------------------------------------------
LCD_TABNUM addwf PCL,1
dt "0123456789ABCDEF"
;
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; SUBRUTINAS INTERNAS DEL LCD
;************************************************************************************************
;LCD_BUSY: Lectura del Flag Busy y la direccion.
LCD_BUSY LEER
BANCO1
comf LCD_DATA,1 ;Puerto B como entrada
BANCO0
ENABLE
nop
btfsc LCD_DATA,7 ;Chequea bit de Busy
goto $-1
DISABLE
BANCO1
clrf LCD_DATA ;Puerto B como salida
BANCO0
ESCRIBIR
return
;
;-------------------------------------------------------------------------
;LCD_E: Pulso de Enable
LCD_E ENABLE
nop
DISABLE ;Desactiva E
COMANDO
return
;
;-------------------------------------------------------------------------
;LCD_COMAND: Escritura de comandos del LCD
; W = Codigo de comando para el LCD
; W ==> LCD_DATA
LCD_COMAND movwf LCD_DATA ;Codigo de comando.
call LCD_BUSY
goto LCD_E ;Genera pulso de E
;
;-------------------------------------------------------------------------
;LCD_FUNCIONSET: Configura ela fuente del caracter y número de lineas. No se cambia DL
; El modo de control deseado deberá cargarse en los 2 bits terceros de W:
; x x x x b3 b2 x x
; b2 : 0 = caracter de 5x7 1 = de 5x10
; b3 : 0 = display de 1 linea 1 = de 2 lineas
; b0,1,4-7 : sin importancia
LCD_FUNCIONSET andlw 0x0C ;Nos quedamos con b3-b2 (DL no se cambia)
iorlw 0x30 ;Incorporamos el bit de función y 8 bits
goto LCD_COMAND