Hola a todos.
Por motivos personales dejé el tema un poco colgado, pero ya conseguí hacerlo funcionar.
El problema para leer la entrada analógica era el procedimiento.
El programa que voy a poner sirve para leer la tensión en una batería y cuando baja por debajo de un valor,
se activa una salida que arrancar un cargador de baterias, en ese momento comenzamos a leer la intensidad entre el cargador y la batería
cuando se haya cargado la batería quitamos el cargador y volvemos a leer la tensión.
Todo ello se visualiza en una pantalla lcd.
; ****CONFIGURACIÓN DEL MICROCONTROLADOR****
List p=16F88 ;Tipo de procesador
include "P16F88.INC" ;Definiciones de registros internos
;*********************************ETIQUETADO REGISTROS********************************
Lcd_var equ 0x20 ;Variables (2) de las rutinas de manejo del LCD
Delay_Cont equ 0x21 ;Variable para la temporización
Temporal_1 equ 0x22 ;Variable temporal
Temporal_2 equ 0x23 ;Variable temporal
R_ContA equ 0x24 ; Contadores para los retardos.
R_ContB equ 0x25
R_ContC equ 0x26
LCD_Dato equ 0x27
LCD_GuardaDato equ 0x28
LCD_GuardaTRISB equ 0x29
LCD_Auxiliar1 equ 0x2A
LCD_Auxiliar2 equ 0x2B
LCD_CaracteresPorLinea equ 0x2C ; Número de caracteres por línea de la pantalla.
Lcd_Temp_1 equ 0x2D
Lcd_Temp_2 equ 0x2E
AN0H EQU 0x31
AN0L EQU 0X32
AN1H EQU 0x33
AN1L EQU 0X34
AN2H EQU 0x35
AN2L EQU 0X36
AN3H EQU 0x37
AN3L EQU 0X38
R1L EQU 0X39
R1H EQU 0X3A
R2L EQU 0X3B
R2H EQU 0X3C
R3L EQU 0X3D
R3H EQU 0X3E
R4L EQU 0X3F
R4H EQU 0X40
TEMPO1 EQU 0X41
CONTADOR EQU 0X42
CONT EQU 0X43
Temp0 EQU 0X44
Resto_b EQU 0X45
Resto_a EQU 0X46
MED3 EQU 0X47
MED2 EQU 0X48
MED1 EQU 0X49
Dividendo_c EQU 0X4A
Dividendo_b EQU 0X4B
Dividendo_a EQU 0X4C
Divisor_b EQU 0X4D
Divisor_a EQU 0X4E
Conversor_H EQU 0x4F
Conversor_L EQU 0x50
Conv_Media_H0 EQU 0x51
Conv_Media_L0 EQU 0x52
Cont_conv_mul EQU 0x53
Med_conv3 EQU 0x54
Med_conv2 EQU 0x55
Med_conv1 EQU 0x56
Cont_conv_div EQU 0x57
Conv_Media_H_P EQU 0x58
Med_conv1_P EQU 0x59
Med_conv2_P EQU 0x5A
P1L EQU 0x5B
P1H EQU 0x5C
Salida_Unidad EQU 0x5D
Salida_Coma EQU 0x5E
Med_conv1_M EQU 0x5F
Med_conv2_M EQU 0x60
cont_comp_0 EQU 0x61
cont_comp_1 EQU 0x62
Estado EQU 0x63
Conv_Media_H1 EQU 0x64
Conv_Media_L1 EQU 0x65
Conv_Media_H EQU 0x66
Conv_Media_L EQU 0x67
T1 EQU 0x68
T2 EQU 0x69
org 0x00 ;Vector de Reset
goto Inicio
org 0x05 ;Salva vector de interrupción
include "lcd_4bit_pb_1.inc" ;Incluye las rutinas de manejo del LCD
include "retardos.inc" ;Incluye las rutinas de manejo del LCD
;*********************************************************************************
;Delay_var: Esta rutina de propósito general realiza una temporización variable
;entre 50 mS y 12.8". Se emplea un preescaler de 256 y al TMR0 se le carga con 195.
;La velocidad de trabajo es de 4Mhz y por tanto el TMR0 se incrementa cada uS. De
;esta forma, el TMR0 debe contar 195 eventos que, con un preescaler de 256 hace una
;intervalo total de 50000 uS/50 mS (195 * 256). El valor 195 hay que expresarlo
;en Hex. (c3) y como el TMR0 es ascendente habrá que cargar su complemento (3C hex.)
;Dicho intervalo de 50 mS se repite tantes veces como indique la variable "Delay_cont",
;es por ello que el delay mínimo es de 50 mS ("Delay_cont=1) y el máxima de 12.8"
;(Delay_cont=255).
Delay_var: bcf INTCON,TMR0IF ;Desconecta el flag de rebosamiento
movlw 0x3c ;Complemento hex. de 195
movwf TMR0 ;carga el TMR0
Intervalo clrwdt ;Refrescar el WDT
btfss INTCON,TMR0IF ;Rebasamiento del TMR0 ??
goto Intervalo ;Todavía no
decfsz Delay_Cont,F ;Decrementa contador de intervalos
goto Delay_var ;Repite el intervalo de 50 mS
return
;*********************************INICIO***************************************
Inicio bsf STATUS,RP0
bcf STATUS,RP1
clrf AN0L
clrf AN0H
movlw B'00001111' ;Configuro el registro ANSEL para que RA0,RA1,RA2 y RA3 sean Analogicas (1) y los otros DIGITALES (0)
movwf ANSEL
movlw B'00000000' ;Todo PORTB lo configuro a SALIDA, todo ceros.
movwf PORTB
movlw b'00001111' ;Todo PORTA lo configuro como ENTRADAS, todo unos.
movwf PORTA
movlw B'10000000' ;Configuro ADCON1 para Justificacion Izq, divisor relog por 2 deshabilitado,tension de referencia AVDD y AVSS
movwf ADCON1
movlw b'00000111' ;movemos ese dato a W.
movwf OPTION_REG ;configuramos el divisor del temporizador.
bcf STATUS,5
call LCD_INI ;Secuencia de inicio del LCD
clrf PORTA
clrf PORTB
clrf AN0L
clrf AN0H
clrf AN1L
clrf AN1H
clrf AN2L
clrf AN2H
clrf AN3L
clrf AN3H
clrf R1H
clrf R1L
;*************************************************TEXTO INICIAL*********************************************************
movlw 0x00
call LCD_PosicionLinea1
movlw 'V'
call LCD_DATO
movlw 0x01
call LCD_PosicionLinea1
movlw 'e'
call LCD_DATO
movlw 0x02
call LCD_PosicionLinea1
movlw '='
call LCD_DATO
movlw 0x03
call LCD_PosicionLinea1
movlw '0'
call LCD_DATO
movlw 0x04
call LCD_PosicionLinea1
movlw '.'
call LCD_DATO
movlw 0x05
call LCD_PosicionLinea1
movlw '0'
call LCD_DATO
movlw 0x07
call LCD_PosicionLinea1
movlw 'I'
call LCD_DATO
movlw 0x08
call LCD_PosicionLinea1
movlw 'e'
call LCD_DATO
movlw 0x09
call LCD_PosicionLinea1
movlw '='
call LCD_DATO
movlw 0x0A
call LCD_PosicionLinea1
movlw '0'
call LCD_DATO
movlw 0x0B
call LCD_PosicionLinea1
movlw '.'
call LCD_DATO
movlw 0x0C
call LCD_PosicionLinea1
movlw '0'
call LCD_DATO
movlw 0x0E
call LCD_PosicionLinea1
movlw 'B'
call LCD_DATO
movlw 0x0F
call LCD_PosicionLinea1
movlw 'T'
call LCD_DATO
movlw 0x40
call LCD_PosicionLinea2
movlw 'V'
call LCD_DATO
movlw 0x41
call LCD_PosicionLinea2
movlw 'r'
call LCD_DATO
movlw 0x42
call LCD_PosicionLinea2
movlw '='
call LCD_DATO
movlw 0x43
call LCD_PosicionLinea2
movlw '0'
call LCD_DATO
movlw 0x44
call LCD_PosicionLinea2
movlw '.'
call LCD_DATO
movlw 0x45
call LCD_PosicionLinea2
movlw '0'
call LCD_DATO
movlw 0x47
call LCD_PosicionLinea2
movlw 'I'
call LCD_DATO
movlw 0x48
call LCD_PosicionLinea2
movlw 'r'
call LCD_DATO
movlw 0x49
call LCD_PosicionLinea2
movlw '='
call LCD_DATO
movlw 0x4A
call LCD_PosicionLinea2
movlw '0'
call LCD_DATO
movlw 0x4B
call LCD_PosicionLinea2
movlw '.'
call LCD_DATO
movlw 0x4C
call LCD_PosicionLinea2
movlw '0'
call LCD_DATO
movlw 0x4E
call LCD_PosicionLinea2
movlw 'O'
call LCD_DATO
movlw 0x4F
call LCD_PosicionLinea2
movlw 'k'
call LCD_DATO
;*******************************************************PRINCIPAL********************************************************************
LEER_EN_1 call mirar
btfss PORTB,0
goto c1
goto c2
c1 call COMP_0
goto LEER_EN_1
c2 call COMP_2
goto LEER_EN_1
;*************************************************mirar*********************************************************
mirar call CONV_AN0
movf AN0L,W
movwf Conv_Media_L
movf AN0H,W
movwf Conv_Media_H
call CONVERSOR
movlw 0x03
call LCD_PosicionLinea1
movlw 0x30
addwf Salida_Unidad,W
call LCD_DATO
movlw 0x05
call LCD_PosicionLinea1
movlw 0x30
addwf Salida_Coma,W
call LCD_DATO
call CONV_AN2
movf AN2L,W
movwf Conv_Media_L
movf AN2H,W
movwf Conv_Media_H
call CONVERSOR
movlw 0x43
call LCD_PosicionLinea2
movlw 0x30
addwf Salida_Unidad,W
call LCD_DATO
movlw 0x45
call LCD_PosicionLinea2
movlw 0x30
addwf Salida_Coma,W
call LCD_DATO
call CONV_AN1
movf AN1L,W
movwf Conv_Media_L
movf AN1H,W
movwf Conv_Media_H
call CONVERSOR
movlw 0x0A
call LCD_PosicionLinea1
movlw 0x30
addwf Salida_Unidad,W
call LCD_DATO
movlw 0x0C
call LCD_PosicionLinea1
movlw 0x30
addwf Salida_Coma,W
call LCD_DATO
call CONV_AN3
movf AN3L,W
movwf Conv_Media_L
movf AN3H,W
movwf Conv_Media_H
call CONVERSOR
movlw 0x4A
call LCD_PosicionLinea2
movlw 0x30
addwf Salida_Unidad,W
call LCD_DATO
movlw 0x4C
call LCD_PosicionLinea2
movlw 0x30
addwf Salida_Coma,W
call LCD_DATO
return
;*************************************************LEER ENTRADA ANALÓGICA AN0*********************************************************
CONV_AN0 clrf ADRESH
clrf ADRESL
movlw B'10000001' ;Configuro ADCON0 para Fosc/8, Selecciono canal 0 (RA0/AN0)y hago operativo el módulo convertidor con el último bit a 1
movwf ADCON0
bcf PIR1,ADIF
bsf PIE1,ADIE
bsf INTCON,PEIE
bsf INTCON,GIE
call Retardo_50ms
bsf ADCON0,2 ;Comienzo conversión
ESP_CONV_AN0 btfsc ADCON0,2 ;Espero a que finalice la conversión
goto ESP_CONV_AN0
movf ADRESH,W ;Conversión efectuada, salvo ADRESH en W
movwf AN0H
bsf STATUS,5
movf ADRESL,w ;Conversión efectuada, salvo ADRESL en W
bcf STATUS,5
movwf AN0L
bcf ADCON0,2
return
;*************************************************LEER ENTRADA ANALÓGICA AN1*********************************************************
CONV_AN1 clrf ADRESH
clrf ADRESL
movlw B'10001001' ;Configuro ADCON0 para Fosc/8, Selecciono canal 0 (RA0/AN0)y hago operativo el módulo convertidor con el último bit a 1
movwf ADCON0
bcf PIR1,ADIF
bsf PIE1,ADIE
bsf INTCON,PEIE
bsf INTCON,GIE
call Retardo_20ms
bsf ADCON0,2 ;Comienzo conversión
ESP_CONV_AN1 btfsc ADCON0,2 ;Espero a que finalice la conversión
goto ESP_CONV_AN1
movf ADRESH,W ;Conversión efectuada, salvo ADRESH en W
movwf AN1H
bsf STATUS,5
movf ADRESL,w ;Conversión efectuada, salvo ADRESL en W
bcf STATUS,5
movwf AN1L
bcf ADCON0,2
return
;*************************************************LEER ENTRADA ANALÓGICA AN2*********************************************************
CONV_AN2 clrf ADRESH
clrf ADRESL
movlw B'10010001' ;Configuro ADCON0 para Fosc/8, Selecciono canal 0 (RA0/AN0)y hago operativo el módulo convertidor con el último bit a 1
movwf ADCON0
bcf PIR1,ADIF
bsf PIE1,ADIE
bsf INTCON,PEIE
bsf INTCON,GIE
call Retardo_50ms
bsf ADCON0,2 ;Comienzo conversión
ESP_CONV_AN2
btfsc ADCON0,2 ;Espero a que finalice la conversión
goto ESP_CONV_AN2
movf ADRESH,W ;Conversión efectuada, salvo ADRESH en W
movwf AN2H
bsf STATUS,5
movf ADRESL,w ;Conversión efectuada, salvo ADRESL en W
bcf STATUS,5
movwf AN2L
bcf ADCON0,2
return
;*************************************************LEER ENTRADA ANALÓGICA AN3*********************************************************
CONV_AN3 clrf ADRESH
clrf ADRESL
movlw B'10011001' ;Configuro ADCON0 para Fosc/8, Selecciono canal 0 (RA0/AN0)y hago operativo el módulo convertidor con el último bit a 1
movwf ADCON0
bcf PIR1,ADIF
bsf PIE1,ADIE
bsf INTCON,PEIE
bsf INTCON,GIE
call Retardo_50ms
bsf ADCON0,2 ;Comienzo conversión
ESP_CONV_AN3
btfsc ADCON0,2 ;Espero a que finalice la conversión
goto ESP_CONV_AN3
movf ADRESH,W ;Conversión efectuada, salvo ADRESH en W
movwf AN3H
bsf STATUS,5
movf ADRESL,W ;Conversión efectuada, salvo ADRESL en W
bcf STATUS,5
movwf AN3L
bcf ADCON0,2
return
;*************************************************CONVERSIÓN DE HEX A VOLTIOS EN DECIMAL****************************************
CONVERSOR clrf Med_conv1
clrf Med_conv2
clrf Salida_Coma
clrf Salida_Unidad
clrf Med_conv1_P
clrf Med_conv2_P
clrf Med_conv1_M
clrf Med_conv2_M
clrf P1L
clrf P1H
movlw d'5'
movwf Cont_conv_mul
CONVERSOR_1 movf Conv_Media_L,w
addwf Med_conv1,1
btfsc STATUS,C
incf Med_conv2,1
movf Conv_Media_H,w
addwf Med_conv2,1
decfsz Cont_conv_mul,1
goto CONVERSOR_1
movf Med_conv1,W
movwf Med_conv1_P
movf Med_conv2,W
movwf Med_conv2_P
DIV_3FF_U movlw 0xFF ;Cargamos el dato de menos peso de Intensidad de referencia de la carga de la batería (AN3L).
subwf Med_conv1_P,W ;Restamos el valor Med_conv1_P - FF.
movwf P1L ;Almacena el resultado en P1L
movlw 0x03 ;Cargamos el dato de más peso de la Intensidad de referencia de la carga de la batería (AN3H).
btfss STATUS,C ;Hubo acarreo (CARRY = 0) anterior ??
addlw 1 ;Si, añade 1 al acumulador (sustraendo) AN3H.
subwf Med_conv2_P,W ;Restamos el valor AN1H (valor de Intensidad de la carga de la batería)- AN3L (valor de Intensidad de referencia de la carga de la batería).
movwf P1H ;Guarda el resultado
movf P1L,W
movwf Med_conv1_P
movf P1H,W
movwf Med_conv2_P
btfsc P1H,7 ;Comprobamos bit 7 de R1H
goto MUL_10 ;Si es 1, Intensidad de batería AN1 es menor que AN3.
incf Salida_Unidad,1 ;Si es 0, Intensidad de batería AN1 es mayor que AN3.
goto DIV_3FF_U
MUL_10 movlw d'9'
movwf Cont_conv_mul
movlw 0xFF
addwf Med_conv1_P,1
btfsc STATUS,C
incf Med_conv2_P,1
movlw 0x03
addwf Med_conv2_P,1
movf Med_conv1_P,W
movwf Med_conv1_M
movf Med_conv2_P,W
movwf Med_conv2_M
MUL_10_1 movf Med_conv1_P,w
addwf Med_conv1_M,1
btfsc STATUS,C
incf Med_conv2_M,1
movf Med_conv2_P,w
addwf Med_conv2_M,1
decfsz Cont_conv_mul,1
goto MUL_10_1
DIV_3FF_C movlw 0xFF ;Cargamos el dato de menos peso de Intensidad de referencia de la carga de la batería (AN3L).
subwf Med_conv1_M,W ;Restamos el valor Med_conv1_P - FF.
movwf P1L ;Almacena el resultado en R1L
movlw 0x03 ;Cargamos el dato de más peso de la Intensidad de referencia de la carga de la batería (AN3H).
btfss STATUS,C ;Hubo acarreo (CARRY = 0) anterior ??
addlw 1 ;Si, añade 1 al acumulador (sustraendo) AN3H.
subwf Med_conv2_M,W ;Restamos el valor AN1H (valor de Intensidad de la carga de la batería)- AN3L (valor de Intensidad de referencia de la carga de la batería).
movwf P1H ;Guarda el resultado
movf P1L,W
movwf Med_conv1_M
movf P1H,W
movwf Med_conv2_M
btfsc P1H,7 ;Comprobamos bit 7 de R1H
return ;Si es 1, Intensidad de batería AN1 es menor que AN3.
incf Salida_Coma,1 ;Si es 0, Intensidad de batería AN1 es mayor que AN3.
goto DIV_3FF_C
;*************************************************COMPARACIÓN AN0 CON AN2*********************************************************
COMP_0 movfw AN0L
movwf R1L
movfw AN0H
movwf R1H
movf AN2L,W
movwf T1
movf AN2H,W
movwf T2
comf T1,1
incf T1,1
btfsc STATUS,Z
decf T2,1
comf T2,1
movf T1,w
addwf R1L,1
btfsc STATUS,C
incf R1H,1
movf T2,w
addwf R1H,1
btfss R1H,7
return
call Retardo_2s
call Retardo_2s
call Retardo_2s
movfw AN0L
movwf R1L
movfw AN0H
movwf R1H
movf AN2L,W
movwf T1
movf AN2H,W
movwf T2
comf T1,1
incf T1,1
btfsc STATUS,Z
decf T2,1
comf T2,1
movf T1,w
addwf R1L,1
btfsc STATUS,C
incf R1H,1
movf T2,w
addwf R1H,1
btfss R1H,7
return
bsf PORTB,0
movlw 0x4E
call LCD_PosicionLinea2
movlw 'C'
call LCD_DATO
movlw 0x4F
call LCD_PosicionLinea2
movlw 'G'
call LCD_DATO
return
;*************************************************COMPARACIÓN AN1 CON AN3****************************************************
COMP_2 movfw AN1L
movwf R3L
movfw AN1H
movwf R3H
movf AN3L,W
movwf T1
movf AN3H,W
movwf T2
comf T1,1
incf T1,1
btfsc STATUS,Z
decf T2,1
comf T2,1
movf T1,w
addwf R3L,1
btfsc STATUS,C
incf R3H,1
movf T2,w
addwf R3H,1
btfss R3H,7
return
call Retardo_2s
call Retardo_2s
call Retardo_2s
movfw AN1L
movwf R3L
movfw AN1H
movwf R3H
movf AN3L,W
movwf T1
movf AN3H,W
movwf T2
comf T1,1
incf T1,1
btfsc STATUS,Z
decf T2,1
comf T2,1
movf T1,w
addwf R3L,1
btfsc STATUS,C
incf R3H,1
movf T2,w
addwf R3H,1
btfss R3H,7
return
bcf PORTB,0
movlw 0x4E
call LCD_PosicionLinea2
movlw 'O'
call LCD_DATO
movlw 0x4F
call LCD_PosicionLinea2
movlw 'k'
call LCD_DATO
return
end