TODOPIC
Microcontroladores PIC => Todo en microcontroladores PIC => Mensaje iniciado por: catk en 10 de Mayo de 2007, 11:03:02
-
Cordial saludo a todos, spy nuevo en este foro y espero poder aportar muchas cosas.
Hoy necesito una ayudita: Estoy intentado crear un conversor A/D con el PIC 16F870, creo que ya logre hacer la conversion pero ahora no se como hacer para que por ejemplo cuando reciba 3v por la entrada analoga me active el puerto RB0 (Por ejemplo), y cosas por este estilo es lo que necesito hacer, pero la verdad no lo he logrado, dejo el codigo en assembler que llevo hasta el momento.
p=16f870
include <p16f870.inc>
numero equ 0x26
org 0x000
goto Start
org 0x004
Interrupt
retfile
Start
bsf STATUS,RP0
clrf PORTB
bcf STATUS,RP1
movlw H'00'
movwf TRISC ;Configuro los puertos de salida
clrf ADCON1
bcf STATUS,RP0
movlw B'01000001'
movwf ADCON0
Main
call ad_portc
goto Main
ad_portc
bsf ADCON0,GO ;Espero que termine de leer datos
Wait
btfsc ADCON0,GO
goto Wait
movf ADRESH,W
movwf PORTC
end
Gracias por la ayuda que me puedan dar.
-
Hola catk
con una resta puedes comparar el dato obtenido del ADRES (dependiendo de la justificación)
3 volts con una +vref = 5 y -vref = gnd -> 3 * 1023 / 5 ~ 614 pasos almacenados
restas este literal a ADRES(H:L) y mediante los bits Z, C puedes averiguar si es igual
PD: tengo que repasar asm , jeje ya me acostumbré al C :?
-
Dependiendo de la precisión que necesites. Si necesitas una precisión del orden de los 20mV entonces el modo 8 bits te va a funcionar muy bien y simplemente sería comparar el ADRESH con una constante a determinar de acuerdo al voltaje que quieras comprobar.
-
la salida digital para 3000mv = 1001100110
adresl=01100110
adresH=10
si la justificacion es por la derecha
JUSTIFICACION LOS OCHO PRIMEROS BITS DE ADRESL Y DOS BITS ADREESH
si comparas estos resultados con una variable podras saber si hay 3 voltios en la entrada.
es solo un paso muy emparapetado de principios; que muy poco utlizan puesto que hay formas mas elegantes que hacer esta funcion.
tambien depende la presicion.
para el de maunix se necesitaria la justificacion a la izquierada,
saludos
-
Cordial saludo.
Gracias a todos y ahi voy avanzando....
Les cuento:
Conecte una pantalla LCD para al PIC para mirar que me esta entrando, pero no se que problema tengo con las decenas, o depronto el problema es general ya que los datos me estan pàsando por el LCD pero no veo concordancia alguna con lo que me esta entrando el codigo que llevo es:
; Febrero 6, 4:42 pm
list P=16F870
#include <P16F870.inc> ; Registros del PIC16F876A
;/////////////////////////////////////////////////////////////////////////////
__CONFIG _CP_OFF & _WDT_OFF & _XT_OSC & _PWRTE_ON & _LVP_OFF & _BODEN_OFF
;/////////////////////////////////////////////////////////////////////////////
; Constantes
;Bancos de memoria RAM (para utilizar banksel)
Banco0 equ 0x20
Banco1 equ 0xA0
Banco2 equ 0x120
Banco3 equ 0x1A0
estado equ 0x03
uni equ 0x21
dec equ 0x22
cen equ 0x23
ptob equ 0x06
buffer equ 0x28
#define CARRY estado,0
#define RPT0 estado,5
E_LCD equ 7 ;Bit del puerto C para control de E.
RW_LCD equ 6 ;Bit del puerto C para control de R/W.
RS_LCD equ 5 ;Bit del puerto C para control de RS.
LCD_Dat equ 0x06 ;Bus de datos del LCD = PORTB
LCD_Ins equ 0x07 ;Bus de Control del LCD = PORTC
;/////////////////////////////////////////////////////////////////////////////
TEMPB3 equ 0x21
TEMPB2 equ 0x22
TEMPB1 equ 0x23
;/////////////////////////////////////////////////////////////////////////////
Org 0x00
goto main
main
clrf INTCON
BANKSEL Banco1 ; Bank1 seleccionado
clrf TRISC
clrf TRISB ; PORTB = Salidas
clrf ADCON0
bcf STATUS, RP0
;movlw B'01000001'
;movwf ADCON0
movlw b'10000001'
movwf ADCON0
; Set ADCON1
;BANKSEL ADCON1
;movlw b'10000101'
;movwf ADCON1
BANKSEL Banco0 ; Bank0 seleccionado
clrf PORTC
clrf PORTB
call inicio
Leer
call ad_portc
goto Leer
ad_portc
bsf ADCON0,GO
Wait
btfsc ADCON0,GO
goto Wait
; bsf RPT0
movf ADRESH,W
;bcf RPT0
movwf buffer ;Guarda el dato obtenido de ADRESL en el buffer temporal
bcf CARRY ;Limpia el CARRY
btfsc ADRESH, 0 ;Mira el bit menos significativo de ADRESH (Bit 8)
bsf CARRY ;Si está en 1 pone en uno el carry
rrf buffer, 1 ;Hace desaparecer el bit 0 de ADRESL, mete el bit 0 de ADRESH por el 7 de ADRESL
movf buffer, 0 ;Dato digitalizado -> W
call DECIMAL ;Obtiene UNI, DEC y CEN con el agregado de 30h para la tabla ASCII
movf dec,0
call LCD_printchar
;call LCD_printchar
movf cen, 0 ;Coloca las decenas
call LCD_printchar
;call LCD_printchar
movf uni, 0 ;Coloca las unidades
call LCD_printchar
call DelaymS
call DelaymS
call BorrarDisplay_LCD
call DelaymS
call DelaymS
movf cen,0
movwf LCD_Dat
bcf LCD_Ins,RW_LCD
bsf LCD_Ins,RS_LCD
bsf LCD_Ins,E_LCD
bcf LCD_Ins,E_LCD
call DelaymS
call DelaymS
call DelaymS
call DelaymS
call DelaymS
call BorrarDisplay_LCD
; movlw "E"
; call LCD_printchar
; call DelaymS
; call DelaymS
return
DECIMAL movwf uni ;Convierte el dato presente en W en UNI, DEC y CEN
clrf dec
clrf cen
movlw d'100' ;Determina la cant. de centenas
CENTENA subwf uni, 1
btfss CARRY
goto CIEN
incf cen, 1
goto CENTENA
CIEN addwf uni, 1
movlw d'10' ;Determina la cant. de decenas
DECENA subwf uni, 1
btfss CARRY
goto DIEZ
incf dec, 1
goto DECENA
DIEZ addwf uni, 1 ;Uni queda con la cant. de unidades (sin decenas ni centenas)
movlw 0x30 ;Le suma 30h a los valores de UNI, DEC y CEN para que queden en ASCII
addwf uni, 1
movlw 0x30
addwf dec, 1
movlw 0x30
addwf cen, 1
return
inicio
call Configurar_LCD
call BorrarDisplay_LCD
call CursorOn_LCD
call InicioL1_LCD
;movlw .2
; call DelayS
; movlw "T"
; call LCD_printchar
; movlw "E"
; call LCD_printchar
; movlw "I"
;call LCD_printchar
;movlw "K"
;call LCD_printchar
;movlw "O"
;call LCD_printchar
;movlw " "
;call LCD_printchar
;movlw "S"
;call LCD_printchar
;;movlw "."
;call LCD_printchar
;movlw "A"
;call LCD_printchar
;fin
; nop
; goto fin
;/////////////////// Subrutinas ///////////////////
Configurar_LCD
movlw .10
call DelaymS
movlw 0x38
call LCD_Instruccion
movlw .1
call DelaymS
return
CursorOn_LCD
movlw 0x0F
call LCD_Instruccion
movlw .1
call DelaymS
return
CursorOff_LCD
movlw 0x0C
call LCD_Instruccion
movlw .1
call DelaymS
return
BorrarDisplay_LCD
movlw 0x01
call LCD_Instruccion
movlw .3
call DelaymS
return
InicioL1_LCD
movlw .128
bcf LCD_Ins,RW_LCD
bcf LCD_Ins,RS_LCD
bsf LCD_Ins,E_LCD
movwf LCD_Dat
bcf LCD_Ins,E_LCD
movlw .1
call DelaymS
return
InicioL2_LCD
movlw .168
bcf LCD_Ins,RW_LCD
bcf LCD_Ins,RS_LCD
bsf LCD_Ins,E_LCD
movwf LCD_Dat
bcf LCD_Ins,E_LCD
movlw .1
call DelaymS
return
LCD_printchar
bcf LCD_Ins,RW_LCD
bsf LCD_Ins,RS_LCD
bsf LCD_Ins,E_LCD
movwf LCD_Dat
bcf LCD_Ins,E_LCD
movlw 0x01
call DelaymS
return
LCD_Instruccion
bcf LCD_Ins,RW_LCD
bcf LCD_Ins,RS_LCD
bsf LCD_Ins,E_LCD
movwf LCD_Dat
bcf LCD_Ins,E_LCD
return
DelayS
movwf TEMPB3
movlw .250
call DelaymS
movlw .250
call DelaymS
movlw .250
call DelaymS
movlw .250
call DelaymS
decfsz TEMPB3,F
goto $-9
return
DelaymS
movwf TEMPB1
movlw .249
movwf TEMPB2
nop
decfsz TEMPB2,F
goto $-2
decfsz TEMPB1,F
goto $-6
retlw .0
end
Como ven antes de hacer de nuevo una lectura le meti delay para que el tiempo de refresco del LCD me permita leer, pero como les comento no ahi concordancia entre la entrada y lo que me muestra el LCD, aclarando como les comento que las decenas NO me esta mostrando nada.
Gracias de nuevo a todos
-
Amigo, te sugiero que vayamos atacando un problema por vez.
En la forma que lo expones, no sabemos si no anda el hardware del A/D , si no anda la rutina de HEX a BCD, o si no anda la rutina del display LCD o bien si no está mal cableado el LCD.
Más allá de eso, ¿qué quieres hacer con esta parte del código?
movwf buffer ;Guarda el dato obtenido de ADRESL en el buffer temporal
bcf CARRY ;Limpia el CARRY
btfsc ADRESH, 0 ;Mira el bit menos significativo de ADRESH (Bit 8)
bsf CARRY ;Si está en 1 pone en uno el carry
rrf buffer, 1 ;Hace desaparecer el bit 0 de ADRESL, mete el bit 0 de ADRESH por el 7 de ADRESL
movf buffer, 0 ;Dato digitalizado -> W
call DECIMAL ;Obtiene UNI, DEC y CEN con el agregado de 30h para la tabla ASCII
No veo porque guardas el contenido de ADRESH en buffer , además luego dices que verificas el bit menos significaivo (bit 8) y en realidad verificas el bit 0 (que sí es el menos significativo).
no veo el sentido a lo que haces y precisamente tal vez estés moviendo todo un lugar a la derecha! (que equivale a dividir por 2) y por eso nunca verás valores mayores a 2.5V
Saludos
-
Hola y gracias por tu respuesta.
Vale vamos por pasos, lo que quiero hacer en primera instancia es que el dato leido por analogo me lo muestre en el LCD,
Y con respecto a tu pregunta ahi tomo el valor de ADRESH para manupularlo osea ese valor lo paso a la subrutina DECIMAL que me separa en unidades, decenas y sentenas que luego envio al LCD (O por lo menos en teoria eso es lo que intento hacer).
Gracias por su ayuda.
-
amigo mira esto tal ves le sirva
http://www.todopic.com.ar/foros/index.php?topic=16963.new;topicseen#new
saludos
-
Hola microcon, te agradezco la ayuda que me estas dando.
Te cuento que mire tu codigo pero toy perdido. Me remito a mi codigo de nuevo para mirar lo siguiente:
ad_portc
bsf ADCON0,GO
Wait
btfsc ADCON0,GO
goto Wait
; bsf RPT0
movf ADRESH,W
;bcf RPT0
movwf buffer ;Guarda el dato obtenido de ADRESL en el buffer temporal
bcf CARRY ;Limpia el CARRY
btfsc ADRESH, 0 ;Mira el bit menos significativo de ADRESH (Bit 8)
bsf CARRY ;Si está en 1 pone en uno el carry
rrf buffer, 1 ;Hace desaparecer el bit 0 de ADRESL, mete el bit 0 de ADRESH por el 7 de ADRESL
movf buffer, 0 ;Dato digitalizado -> W
call DECIMAL ;Obtiene UNI, DEC y CEN con el agregado de 30h para la tabla ASCII
Aqui lo que hago es tomar la lectura por la entrada analoga, y pasarla a la rutina DECIMAL para separar unidades, decenas y centenas para luego imprimirlas en el LCD, que parte de este paso tengo mal????
Gracias por tu ayuda!
-
Ayudaaa :'(
Nada que me cuadra, intente hacer esto y nada:
Wait
btfsc ADCON0,GO
goto Wait
movf ADRESH,W
addwf 0x30,0 ;Le suma 30h a los valores recibidos por la entrada analoga para mostrarlo en el display
call LCD_printchar
movlw "D"
call LCD_printchar
call DelaymS
call DelaymS
call BorrarDisplay_LCD
Lo que intento hacer es que el dato RECIBIDO por ADRESH me lo saque por el LCD
-
Hola catk
una pregunta:
¿ya probaste solo la parte del CAD?
¿te funcionó?
como una sugerencia, deberias primero resolver si está bien lo del convertidor, puedes hacer que el resultado te lo envíe a un puerto y pegas varios led´s para confirmar
luego te pasas a la parte del LCD
-
Hola de nuevo.
Bueno en mi intento por probar intente correr este codigo y me funciona diria a medias. Me van encendiendo en serie los LEDS pero aumenta o disminuye la intensidad de los mismos, esta bien que hagan eso???
El codigo es:
__config _LVP_OFF & _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF & _BODEN_OFF
& _DEBUG_OFF
list p=16f877
include "p16f877.inc"
; Start at the reset vector
org 0x000
goto Start
org 0x004
Interrupt
retfie
Start
bsf STATUS,RP0 ;bank 1
bcf STATUS,RP1
movlw H'00'
movwf TRISC ;portc [7-0] outputs
clrf aDCON1 ;left justified, all inputs a/d
bcf STATUS,RP0 ;bank 0
movlw B'01000001' ;Fosc/8 [7-6], A/D ch0 [5-3], a/d on [0]
movwf aDCON0
Main
call ad_portc
goto Main
ad_portc
;wait for acquision time (20uS)
;(non-critical for this test)
bsf aDCON0,GO ;Start A/D conversion
Wait
btfsc aDCON0,GO ;Wait for conversion to complete
goto Wait
movf ADRESH,W ;Write A/D result to PORTC
movwf PORTC ;LEDs
return
end
Gracias a todos por la ayuda!
-
Tal vez te falten resistencias limitadoras entre los pines del PIC y los LEDS. Es sólo una suposición. No he mirado el código.
Saludos.