TODOPIC
Microcontroladores PIC => Almacén del Assembler => Mensaje iniciado por: JuanjoPic en 17 de Febrero de 2016, 23:00:06
-
Hola a todos, bueno he creado un programa para testear voltaje (osea un voltimetro xd)....... bueno el programa me funciona "casi" bien si no fuera por que el pic me estrega exactamente la mitad del voltaje que debiera mostrar :(.
Tengo configurado al pic con voltaje de referencia el mismo con cual alimento el pic (5 volts).
-
Te tengo que pedir un par de cosas
- Programa, solo necesito la parte de configuracion, cuando lees del ADC y donde lo mostras ( Aunque imagino que hiciste un programa simple solo para el ADC )
- PIC que estas usando
-
Hola racias por comentar, el pic que utilizo es el 12f675. Este esta es la parte principal del programa (utilizo un oscilador de 4Mhz)
list p=12f675
INCLUDE "p12f675.INC"
__CONFIG _CP_OFF&_CPD_OFF&_MCLRE_OFF&_BODEN_OFF&_WDT_OFF&_PWRTE_ON&_HS_OSC
Dato_leido equ 20h
R_ContC equ 25h
R_ContA equ 26h ; Contadores para los retardos.
R_ContB equ 27h
BCD_Centenas equ 28h ; de la RAM de usuario. Se toma a continuación de
BCD_Decenas equ 29h ; la última asignada.
BCD_Unidades equ 30h
dato_nibble_bajo equ 35h
dato_nibble_alto equ 36h
I2C_ContadorBits equ 37h ; Cuenta los bits a transmitir o a recibir.
I2C_Dato equ 38h ; Dato a transmitir o recibido.
I2C_Flags equ 39h
PCF8574_Dato equ 40h ; Aquí guarda el resultado del dato leído o que
#DEFINE PCF8574_DIR_ESCRITURA b'01000000'
; se va a escribir.
#DEFINE SCL GPIO,0 ; Línea SCL del bus I2C.
#DEFINE SDA GPIO,2 ; Línea SDA del bus I2C.
#DEFINE I2C_UltimoByteLeer I2C_Flags,0
;.........................................................................
org 0 ;Vector de RESET
goto INICIO
org 5 ;Inicio del Programa
include <RETARDOS.INC>
include <LCD.INC>
include <Visualizar.INC>
include <BIN_BCD.INC>
INCLUDE <BUS_I2C.INC>
INCLUDE <PCF8574.INC> ; Subrutinas de control del módulo LCD.
;................... Configuración de puertos ................
CONFIGURACION_GENERAL:
clrf GPIO
bcf STATUS,RP0
movlw b'00000111'
movwf CMCON
bsf STATUS, RP0
movlw b'00010010'
movwf ANSEL
movlw b'00000010'
movwf TRISIO
bcf STATUS,RP0
;.......................................................................
INICIO:
call LCD_Inicializa ; Inicializo LCD
call Mensaje ; Envio la frase voltimetro
call Retardo ; Retardo de 65ms
call Borrar ; Borro el mensaje
bsf OPTION_REG,7
movlw b'0000101' ; derecha,Vdd,0,0,01=canal 1,0= aun no inicia AD, 1=AD operativo
movwf ADCON0
call Retardo
bsf ADCON0,1
call Retardo
PROGRAMA:
btfsc ADCON0,1 ; Termino la conversion A/D?
goto PROGRAMA
call Visualizar_datos_LCD
call Retardo
bcf PIR1,6
bsf ADCON0,1
goto PROGRAMA
end
-
No veo ningun problemas al menos ahi, Tal ves el problema este en Visualizar_datos_LCD
Como yo prefiero tener todas las configuraciones de los modulos en un solo lugar y tendria esto:
movlw b'0000101' ; derecha,Vdd,0,0,01=canal 1,0= aun no inicia AD, 1=AD operativo
movwf ADCON0
junto con la configuracion del ANSEL /TRISIO / etc.
Pero de todas formas esta bien y es solo cuestion de gusto, no veo ningun problema al menos hasta aca. Como decia tal ves el problema este en la rutina que dije al comienzo
-
De un inicio tenia puesto el:
movlw b'0000101' ; derecha,Vdd,0,0,01=canal 1,0= aun no inicia AD, 1=AD operativo
movwf ADCON0
con la configuración de los registros ANSEL y TRISIO .....pero simulando en proteus no me funcionaba .....lo cambie de posición y me funciona a medias (ya que solo muestra la mitad del voltaje :().
Subire la funcion Visualizar_datos_LCD por si le quieres hechar un ojo :-/
-
Para mi ahi debe estar el error. No veo nada mal de lo que tenes realizado. El ADC es muy simple, configurarlo y luego proceder poner GO en 1, esperar que se ponga en 0 y leer el resultado.
-
Esta es:
Visualizar_datos_LCD:
bsf STATUS, RP0
movf ADRESL,w
bcf STATUS,RP0
movf ADRESL,w
movwf Dato_leido
call LCD_Linea1 ; Se sitúa al principio de la primera línea.
movf Dato_leido,W ; Recupera el dato a visualizar y lo
call BIN_a_BCD ; pasa a BCD.
movf BCD_Centenas,W ; Visualiza las centenas que corresponden a las
addlw '0' ; le sumo el 0 en ASCII para trensformar numero en ASCII
call Enviar_datos_LCD ; unidades de voltios.
movlw b'00101110' ; Visualiza el punto decimal.
call Enviar_datos_LCD
movf BCD_Decenas,W ; Visualiza las decenas que corresponden a las
addlw '0'
call Enviar_datos_LCD ; décimas de voltios.
movf BCD_Unidades,W ; Visualiza las unidades que corresponden a las
addlw '0'
call Enviar_datos_LCD ; centésimas de voltios.
movlw 'V'
call Enviar_datos_LCD
return
Enviar_datos_LCD:
call construir_dato_R_escritura
return
Retardo:
bsf STATUS,RP0
movlw b'00000111'
movwf OPTION_REG
bcf STATUS,RP0
movlw d'0'
movwf TMR0
bcf INTCON,2
lopp_11:
btfss INTCON,2
goto lopp_11
return
-
Estas usando justificado izquierdo, que es lo que deberias usar si solo queres un valor de 0 a 255
bit 7 ADFM: A/D Result Formed Select bit
1 = Right justified
0 = Left justified
Por lo cual tu codigo es incorrecto
Deberias tomar ADRESH del banco 0, ponerlo en W y luego pasarlo por el BIN_a_BCD
( Quita las primeras 3 instrucciones, y cambia el ADRESL por ADRESH y listo)
-
Cambie el valor del bit7 del registro ADCON0 a 1 (bit 7 ADFM: A/D Result Formed Select bit1 = Right justified), asi los valores LSB estan todos en el el registro ADRESL y solo dos bits quedan en el ADRESH.(creo q es mas facil asi ya que despues tengo que enviar los 8 bits mas bajos)
Luego pido el valor del registro ADRESL accediendo al banko 1:
bsf STATUS, RP0
movf ADRESL,w
bcf STATUS,RP0
Vuelvo al banko 0 para seguir con el programa (ya que en ese banco están las dirección de memoria para las variables que utilizo).
Le cago el valor del registro de trabajo (w) a mi variable:
movwf Dato_leido
Al hacer eso y simular en proteus el valor se queda pegado en 192 :(
-
Por ahora proba con justificado izquierdo y el ADRESH nomas... explico el por que.
Justificado izquierdo, cada 4 ves que cambia el valor.
1020d = 1111 1111 00 = 0xFF0
1016d = 1111 1110 00 = 0xFE0
Y con solo ADRESH podes verlo.
Si usas justificado derecho:
768d = 11 0000 0000
512d = 10 0000 0000
256d = 01 0000 0000
0d = 00 0000 0000
Nunca vas a diferenciar todos, y si varias y queres ver una diferencia de 0 a 255 es la unica forma, sino cuando llegues al numero 256 ( ADC ), vas a volver a 0 si solo tomas el ADRESL. Si de todas formas queres hacerlo de esa forma, tene en cuenta lo que va a pasar.
Al hacer eso y simular en proteus el valor se queda pegado en 192
Tenes un error en tu codigo si pensas hacerlo con ADRESL
Visualizar_datos_LCD:
bsf STATUS, RP0
movf ADRESL,w
bcf STATUS,RP0
movf ADRESL,w <---- ESTO ES UN ERROR! ( Ya no estas mas en el banco1, borra esta instruccion )
movwf Dato_leido
-
esto le cambie al codigo:
- justifico a la izquierda (dejo el bit7 = 0 para el registro ADCON0).
- en la parte donde envio el valor del registro ADRESH deje esto:
Visualizar_datos_LCD:
movf ADRESH,w
movwf Dato_leido
(le he sacado la parte de entrar al banko y lo del ADRESL).
Ahora simulo en proteus y me sigue dando la mitad del voltaje :(.
PD: proteus me arroja un warning :shock: me dice esto:
adc conversion clock period (5e-07) is possibly invalid for divide clock frequency :(
-
Tal ves es por que estas usando un "reloj" de 20Mhz, para eliminar problemas de reloj, cambia la configuracion del ADC al RC que posee el ADC, es decir en el ADCON0 que quede asi:
00110010
el x11 es para Frc ( Reloj interno del ADC )
Por que si usas el clock principal tenes que cumplir ciertos valores..
Por ejemplo para 20Mhz si o si tenes que usar Fosc/32, tenes la tabla en el datasheet pagina 42
Pero el Frc siempre funciona :)
-
Leyendo el datasheet dice que recomienda usar el clock rc del A/D solo si la frecuencia de de trabajo del pic es menor a 1MHZ....y estoy usando un cristal de 4Mhz :? incluso usando el oscilador interno no se podria :( (o no ??).
De todos modos simule el cambio (el codigo que me dijiste se lo aplique al ANSEL no al ADCON0) y proteus me arrojo mas waring.
Realmente no se en que fallo para que me arroje la mitad del voltaje.
PD: como me entrega la mitad del valor le sume el mismo valor y tuve el valor entero :) .....pero el objetivo es que funcione el A/D bien y no engañarme yo mismo :( jajaja :(
-
Tenes razon, perdon, era el ANSEL.
La otra que queda es que este mal la rutina de BIN_a_BCD.. Si podes pasarla y descartamos eso.
-
; Un número binario natural de 8 bits es convertido a BCD. El resultado se guarda en tres
; posiciones de memorias llamadas: BCD_Centenas, BCD_Decenas y BCD_Unidades.
;
; El procedimiento utilizado es mediante restas de 10, tal como se explicó en el capítulo 9.
;
; Entrada: En el registro W el número binario natural a convertir.
; Salidas: En (BCD_Centenas), (BCD_Decenas) y (BCD_Unidades).
; En el registro W también las decenas (nibble alto) y unidades (nibble bajo).
; Subrutina "BIN_a_BCD" -----------------------------------------------------------------
CBLOCK ; En las subrutinas no se debe fijar la dirección
BCD_Centenas ; de la RAM de usuario. Se toma a continuación de
BCD_Decenas ; la última asignada.
BCD_Unidades
ENDC
;
BIN_a_BCD
clrf BCD_Centenas ; Carga los registros con el resultado inicial.
clrf BCD_Decenas ; En principio las centenas y decenas a cero.
movwf BCD_Unidades ; Se carga el número binario a convertir.
BCD_Resta10
movlw .10 ; A las unidades se les va restando 10 en cada
subwf BCD_Unidades,W ; pasada. (W)=(BCD_Unidades) -10.
btfss STATUS,C ; ¿C = 1?, ¿(W) positivo?, ¿(BCD_Unidades)>=10?
goto BIN_BCD_Fin ; No, es menor de 10. Se acabó.
BCD_IncrementaDecenas
movwf BCD_Unidades ; Recupera lo que queda por restar.
incf BCD_Decenas,F ; Incrementa las decenas y comprueba si ha llegado
movlw .10 ; a 10. Lo hace mediante una resta.
subwf BCD_Decenas,W ; (W)=(BCD_Decenas)-10).
btfss STATUS,C ; ¿C = 1?, ¿(W) positivo?, ¿(BCD_Decenas)>=10?
goto BCD_Resta10 ; No. Vuelve a dar otra pasada, restándole 10 a
BCD_IncrementaCentenas ; las unidades.
clrf BCD_Decenas ; Pone a cero las decenas
incf BCD_Centenas,F ; e incrementa las centenas.
goto BCD_Resta10 ; Otra pasada: Resta 10 al número a convertir.
BIN_BCD_Fin
swapf BCD_Decenas,W ; En el nibble alto de (W) también las decenas.
addwf BCD_Unidades,W ; En el nibble bajo de (W) las unidades.
return ; Vuelve al programa principal.
-
No creo que sea el problema ese programa el problema ya que le he cargo un valor conocido y lo envia perfecto
-
El codigo del BIN_a_BCD parece correcto. Realmente ya no tengo mas ideas para darte. Para mi esta todo correcto ademas estamos quitando todos los posibles problemas del medio como seria el reloj al seleccionar el Frc. Pero aun asi no se por que esta dandote la mitad de la tension.
Lo unico que me queda decirte es que te fijes con el multimetro si llegan los 5V al pin analogico.
Sino no veo como puede estar fallando.
-
Claro con un multimetro estoy corroborando el valor que debiera medir (lo estoy haciendo en proteus y en el protoboard).
Voy revisar el registro de los comparadores y desactivar (por las dudas) las resistencias pull-up quizas me afecten :(