# Programa de conversión A/D con Pic 16f877/A



## canales (Feb 22, 2007)

Saludos a todos.

Vengo de nuevo a matar un poco más mi ignorancia acerca de los pic y assembler.

Bueno, sucede que quería hacer un programa que me hiciera la conversión de analógico a digital del pin RA0 del 16f877; en fin, lo hice siguiendo los pasos de la hoja de datos, pero no veo ningún resultado en ADRESH:ADRESL, los dos siempre están en cero. Bueno, tal vez estoy haciendo mal la simulación en MPLAB, porque no sé como hacer una simulación de una entrada analógica. Sin embargo, el MPLAB no me da ningún mensaje de error. Pero hay algo que no está funcionando bien con el programa que hice.

En dicho programa tengo una rutina llamada conversión, la cual e:

Conversión
		btfsc	adcon0,2
		goto Conversión
		call delay_2Tad
		goto Principal

Sucede que el bit 2 del registro adcon0 se pone en cero cuando estoy en la linea 'goto Conversión' y presiono F7 para el step into, pero aquí el programa no funciona a como debería. Al presionar F7 no se me ejecuta la instrucción 'goto Conversión', sino que el programa hace un salto a la linea numero 5 de la rutina Principal, y de ahí vuelve a comenzar el programa. Bueno, ese salto lo hace después de algunas evaluaciones de la instrucción btfsc, a como debería. La lógica de la secuencia es que al estar en la linea de 'goto Conversión' y al presionar F7, el programa debería hacer otra evaluación del bit 2 del registro adcon0 y luego saltar a la linea call delay_2Tad, pero no lo hace. Realmente no sé lo que esté mal. Aquí pongo todo el programa para que lo chequeen, y si hay algún comentario o sugerencia, se los agradeceré.



```
list p=16f877
processor "16f877.inc"

;***Comienzo a definir variables***

estado	equ	0x03
trisA	equ	0x85
trisB	equ	0x86
portA	equ	0x05
portB	equ	0x06
adresh	equ	0x1e
adresl	equ	0x9e
adcon0	equ	0x1f
adcon1	equ	0x9f

;***Configuración del módulo A/D
;y puertos de entrada y salida***

Inicio
		movlw	b'00100000'
		movwf	estado
		movlw	0x03	 	 ;Cargo W=b'00011' 
		movwf	trisA		 ;y lo paso a trisA.
		movlw	0xff	 	 ;Cargo W=b'11111111'
		movwf	trisB	 	 ;y lo paso a trisB.
	 	movlw	b'10000100'	 ;Cargo W=b'0100' y lo paso a adcon1
		movwf	adcon1	     ;para configurar las entradas analógicas.
		
Principal
		bcf		estado,5 	 ;Acceso al banco0.
		movlw	b'01000001'	 ;Selecciono el canal de entrada
		movwf	adcon0		 ;y el clk de conversión para el A/D.
		bcf		0ch,6		 ;Pongo a cero el bit ADIF de PIR1.
		bsf		0bh,7		 ;Activo los bit GIE
		bsf		0bh,6		 ;y PEIE del registro INTCON.
		bsf		estado,5	 ;Acceso al banco1.
		bsf		8ch,6		 ;Activo el bit ADIE del registro PIE1.
		bcf		estado,5	 ;Acceso al banco0.
		call	Espera
		bsf		adcon0,2
		
Conversión
		btfsc	adcon0,2
		goto Conversión
		call delay_2Tad
		goto Principal

Espera
		movlw	0x1f
		movwf	20h
		loop
			decfsz	20h,1
			goto loop
		return

delay_2Tad
		movlw	0x15
		movwf	20h
		loop1
			decfsz	20h,1
			goto loop1
		return
end
```


PD: El tirsB y el portB realmente no hacen ninguna función en el programa, ignorenlos.


----------



## carlosxyz (Feb 25, 2007)

no me atrevi a leer tu codigo, pero igual me tarde en programarlo, puede ser un registro mal progtramado etc, yo lo que hice fue probarlo directamente, y lo hice mediante una tableta electronica, hice las conexiones y en el pin de conversion coloque un potenciometro, y puse los registros de conversion que los despleagara en el puerto B del 16f88. en realidad es lo mismo para todos los micros, lo que pasa es que hay que saber leerlos.


----------



## Jairo (Feb 25, 2007)

hola

no lei todo tu programa, pero si esta saltando a la direccion 5 a lo mejor es que se esta generando una interrupcion en ese momento, o activaste la interrupcion por conversor a/d, una forma fás facil es acerla en pic basic, es tro lenguaje de programacion parecido al C, es bastatnte facil aprender, y para la conversion solo utilizas un comando que ADCIN y luego los parametros como cual canal, entre otyros , eso es facilmente reconocible en la ayuda

ah otra cosa porque no lo simulas en Proteus, ahi si se puede simularla conversion conectando un potenciometro le cargas el .hex de tu programa y listo, fnciona a la perfeccion..

Jairo


----------



## canales (Feb 26, 2007)

Hola a todos.

Agradezco los comentarios y sugerencias de Carlosxyz y Jairo. 
Ya me dí cuenta de la razón de ese salto a la línea 5 de la rutina Principal. Lo que pasa es que la conversión A/D, al ser completada, genera una interrupción; y cada vez que se genera una interrupción el pic hace que el programa vaya a la dirección 0x04, la cual es la linea 5 de la rutina Principal. 

Esta es la modificación que le hice al programa:


```
********************************************************************************

list p=16f877
processor "16f877.inc"

;***Comienzo a definir variables***

status	equ	0x03
trisA	equ	0x85
trisB	equ	0x86
portA	equ	0x05
portB	equ	0x06
adresh	equ	0x1e
adresl	equ	0x9e
adcon0	equ	0x1f
adcon1	equ	0x9f

;***Configuración del módulo A/D
;y puertos de entrada y salida***

org	0x00
		goto	Inicio
org 0x04
		call 	delay_2Tad
		bcf		0ch,6
		retfie
	

Inicio	
		movlw	b'00100000'
		movwf	status
		movlw	0x03	 	 ;Cargo W=b'00011' 
		movwf	trisA		 ;y lo paso a trisA.
		movlw	0xff	 	 ;Cargo W=b'11111111'
		movwf	trisB	 	 ;y lo paso a trisB.
	 	movlw	b'10000100'	 ;Cargo W=b'0100' y lo paso a adcon1
		movwf	adcon1	     ;para configurar las entradas analógicas.
	
Principal
		bcf		status,5 	 ;Acceso al banco0.
		movlw	b'01000001'	 ;Selecciono el canal de entrada
		movwf	adcon0		 ;y el clk de conversión para el A/D.
		bcf		0ch,6		 ;Pongo a cero el bit ADIF de PIR1.
		bsf		0bh,7		 ;Activo los bit GIE
		bsf		0bh,6		 ;y PEIE del registro INTCON.
		bsf		status,5	 ;Acceso al banco1.
		bsf		8ch,6		 ;Activo el bit ADIE del registro PIE1.
		bcf		status,5	 ;Acceso al banco0.
		call	Espera
		bsf		adcon0,2
		
Conversion
		btfsc	adcon0,2
		goto	Conversion
		goto 	Principal

Espera
		movlw	0x1f
		movwf	20h
		loop
			decfsz	20h,1
			goto loop
		return

delay_2Tad
		movlw	0x15
		movwf	20h
		loop1
			decfsz	20h,1
			goto loop1
		return
end
		
********************************************************************************
```
Buen día.


----------



## JuantoHdez (Mar 22, 2007)

Hola amigos soy nuevo en este foro, saben tengo un problema estoy construyendo un termometro digital, el material que adquiri para esto es un pic 16f877a y un lm35, de lcd tengo una de 16x2, el problema es que quiero usar lenguaje c para hacer esto, ya antes lo habia hecho lo de imprimir con una lcd pero con un 16f84, pero en este 16f877a simplemente no puedo lo he intentado al menos con los puertos b,c,d y pss nada que sale aqui pongo el codigo que estoy usando para este fin espero alguien sepa que me esta fallando y me puedan ayudar, solo quiero mostrar el mensaje en lcd el conversor analogico ya funciona solo necesito saber como imprimir,  saludos...


```
#include <16f877.h>
#use delay (clock=40000000) //Modo del oscilador
#fuses XT,NOWDT,NOPROTECT,BROWNOUT,NOLVP,PUT 
#include <lcd.c>
void main()
{ 
  lcd_putc("inicializando...");
  delay_ms(2000);
  lcd_putc("Temperatura : ");
  delay_ms(2000);
}
```


----------



## PunkistaN (Sep 20, 2007)

JuantoHdez, debes de tener en cuenta q las direcciones de memoria de un PIC16F84 son muy diferentes a las del 16F877A, si observas el data sheet de cada uno te das cuenta que el PIC16F84 empieza en 0xC, y el del PIC16F877A en 0x20..... observa eso (a mi me paso)

espero te sirva


----------



## ghost_007 (Nov 23, 2007)

tome el ejercicio de hacer oscilar un led de una pagina pero no me acuerdo cual era la pagina (funciona) luego trate de regular la frecuancia de ocilacion de un led con un potenciometo de 100k (la pata del medio a ra0 y una pata a negativo y la otra a vcc) pero no me funciono T_T

aki dejo el codigo para ke lo vean.


```
LIST p=16F877

status equ 03h
trisa equ 85h
porta equ 05h
trisb equ 86h
portb equ 06h
intcon equ 0bh
pir1 equ 0ch
pie1 equ 8ch
adresh equ 1eh
adresl equ 9eh
adcon0 equ 1fh
adcon1 equ 9fh
CUENTA1 equ 20h ;Las variables que usemos siempre a
CUENTA2 equ 21h ;partir de la direccion 20h
cuenta3 equ 22h
cuenta equ 23h

#define banco0 bcf status,5
#define banco1 bsf status,5

F EQU 1
w EQU 0


ORG 00h
goto inicio
org 04h
call delay_2Tad
bcf pir1,6
retfie

inicio banco0
bsf intcon,7
bsf intcon,6
bsf pir1,6
banco1
bsf pie1,6
bsf adcon1,7
banco0
bsf adcon0,2


Conversion btfsc adcon0,2
goto Conversion
movf adresl,0
movwf CUENTA2




movlw 0ffH ;Pone a "1" RB0 (enciende)
movwf portb
CALL DELAY ;Llama a la subrutina de retardo
movlw 00H ;Cuando vuelve del retardo pone
movwf portb ;a "0" RB0 (apaga)
CALL DELAY ;llama a la subrutina de retardo
GOTO inicio ;cuando vuelve del retardo
;ejecuta el GOTO


;= DELAY: Subrutina de retardo
;= Modifica los siguientes registros:
;= CUENTA1
;= CUENTA2
;= ACUMULADOR
;= STATUS


DELAY MOVLW 0FFH ;Carga el acumulador con el valor
;10H (16 en decimal)
MOVWF CUENTA1 ;Mueve el contenido del acumulador
;a CUENTA1
ACA1 MOVLW 100H ;Carga el acumulador con el valor FFH
MOVWF CUENTA2 ;Mueve el contenido del acumulador
;a CUENTA2
ACA DECFSZ CUENTA2,F ;Decrementa CUENTA2, guarda el resultado
;en f, y si es cero se salta la siguiente
;instrucción
GOTO ACA ;vuelve a decrementar mientras
;CUENTA2 no sea cero
DECFSZ CUENTA1,F ;Se decrementa CUENTA1 cada vez que
;CUENTA2 llega a cero
GOTO ACA1 ;mientras CUENTA1 no llegue a cero recarga
;CUENTA2 y repite el proceso
RETURN ;retorna al programa principal


;= FIN DE LA SUBRUTINA DELAY

espera movlw 0x1f
movwf cuenta3
loop decfsz cuenta3,1
goto loop
return

delay_2Tad movlw 0x15
movwf cuenta3
loop1 decfsz cuenta3,1
goto loop1
return

END ;Fin del programa
```

trate de acomodarlo lo mejor ke pude


----------



## ivan_ambriz (Jul 17, 2008)

Que tal, trabajo en el bien conocido termómetro digital con el LM35. Yo programo en Pic Basic Pro. El problema es que el lm35 marca .270 V y me muestra 22 grados en el LCD. Dejo el programa:


```
'****************************************************************
'*  Name    : SENSOR DE TEMPERATURA                             *
'*  Author  : [Ing. Iván Alejandro Rodríguez Ambríz]            *
'*  Notice  : Copyright (c) 2007 [select VIEW...EDITOR OPTIONS] *
'*          : All Rights Reserved                               *
'*  Date    : 17/07/2008                                        *
'*  Version : 1.0                                               *
'*  Notes   :                                                   *
'*          :                                                   *
'****************************************************************
DEFINE ADC_BITS 8         'Activa el ADC de 8 bits
TRISA = 255                     ' Fija todos los pines del puerto A como entradas
ADCON1 = %00001110              ' Config. PORTA. 6bits de menor peso y AN0 entrada analógica, 'el resto son entradas digitales
ADCON0=  %10000001            'Fosc/32,ch0 y ADC en marcha

MUL VAR BYTE

define osc 4 
DEFINE LCD_DREG PORTB                ' LCD Data port
DEFINE LCD_DBIT 0                          ' starting Data bit (0 or 4) if 4-bit bus
DEFINE LCD_RSREG PORTD              ' LCD Register Select port
DEFINE LCD_RSBIT 7                        ' LCD Register Select bit
DEFINE LCD_EREG PORTD                ' LCD Enable port
DEFINE LCD_EBIT 6                          ' LCD Enable bit
DEFINE LCD_BITS 8                          ' LCD bus size (4 or 8 bits
DEFINE LCD_LINES 2                        ' Number of lines on LCD
DEFINE LCD_COMMANDUS 2000
DEFINE LCD_DATAUS 50

ANALOGICO var BYTE
 

LCDOUT  $FE,1   
PAUSE   200

LCDOUT "IVAN AMBRIZ CO"
LCDOUT $FE,$C0,"PIC 16F877A"
PAUSE 300

INICIO:          
       ADCIN 0, analogico                'Lee el CH0 y lo asigna a analogico
       MUL=ANALOGICO*2              'Deduje la multiplicación a prueba y error, pero no se porque 'la conversion directa me da la mitad del valor real
     
      LCDOUT  $FE,1,"TEMPERATURA:", DEC MUL
           
       LCDOUT $FE,$C0,"'C: "
       
       pause 100

goto inicio 


'**********************************************************************
```

Lo que no me queda claro es, por ejemplo si mi entrada analógica es 270 mV, cómo se me muestra en el display? que es el caso y me da 11, con la multiplicacion 22. 

Adjunto la simulación en PROTEUS, ahi si da los 28 grados correspondientes

Gracias.
Gracias por su ayuda.


----------



## darwin2010 (Dic 26, 2008)

hola, amigos soy nuevo en esto y tengo una pregunta muy relacionada con el conversor anologico digital del pic 16f877a, lo q pasa esque estoy realizando un trabajo sobre un termometro digital. hice un codigo en lenguaje ensamblador y pues si me realiza la conversion pero tengo dos pregunta he incovenientes
-el primer inconveniente es que si yo quiero justificarlo a la derecha colocando un 1 en el bit adfm del registro adcon1, al hacer la simulacion en el isis, no me realiza la conversion analogica digital y en la mayoria de los bits me aparecen como ceros
-el segundo incoveniente es que si yo quiero hacer la conversion analogica digital cada 10ms aprox por ejemplo utilizando el lm35, no me la realiza inclusive tomando los 10 bits, este es mi codigo


```
list p=16f877A
		#include P16f877A.inc
		org 0x05

inicio
		bcf STATUS,RP0
		bcf STATUS,RP1
		movlw 0x41
		movwf ADCON0
		bsf STATUS,RP0
		bcf STATUS,RP1
		clrf TRISA
		clrf TRISB
		clrf TRISC
		movlw 0x07
		movwf OPTION_REG
		movlw 0x0E
		movwf ADCON1
		bsf TRISA,0
		bcf STATUS,RP0
		bcf STATUS,RP1
		clrf PORTC
		clrf PORTB
bucle
		btfss INTCON,2
		goto bucle
		bcf INTCON,2
		bsf ADCON0,2
espera
		btfsc ADCON0,2
		goto espera
		movf ADRESH,W
		;movf ADRESH,W
		movwf PORTB
		movf ADRESL,W
		movwf PORTC
		goto bucle
     	END
```
muchas gracias por su atensión y su ayuda


----------



## fofo almarales (Dic 27, 2008)

Hola darwin, no vi detalladamente tu programa ya que trabajas con sistema hex a diferencia de mi que trabajo en sistema binario cuando trabajo directamente con registros de proposito especifico. Uno de tus problemas segun lo que vi puede deberse al tiempo de adquisicion necesario para la conversion. Luego de encender el conversor a/d debes hacer un retardo de unos 20 uS recomendablemente. Aunque tu programa parece hacerlo ya que hay muchas instrucciones luego del encendido del adc, pero aqui te paso la rutina que siempre utilizo con el lm35 para que compares. La he utilizado en 3 ocasiones, llevadas a campo y ha resultado. 
Ahora te doy detalles de como lo hice. Primero trabajo con justificacion a la izquierda (utilizando el adresh), ya que asi no tengo problemas con los desbordes del adresl. ademas de eso, la referencia esta a 5 voltios por lo que dividi el resultado de la conversion entre 2 con un rrf por la sensibilidad del lm35.

confi	bsf	status,5
	movlw	b'10000101'
 	movwf	adcon1
	bcf	status,5

conv_temp	movlw	b'11000001' ; Canal RA0, Oscilador interno, ADC Encendido
	movwf	adcon0
	movlw	.35		; Espera de aprox. 20uSeg
	movwf	adc_cont
	decfsz	adc_cont,1
	goto	$-1
	bsf	adcon0,2		; Inicio de conversion
	btfss	pir1,adif
	goto	$-1
	bcf	pir1,adif
	movf	adresh,0		; Final de conversion
	movwf	adresh_r		; Guarda los valores en centena,decena y unidad
	rrf	adresh_r,w
	movwf	portc
	return


PD: No estoy conectandome muy seguido. Si tienes alguna duda pasame un mensaje privado con la direccion del post y te respondo aqui en el foro. Saludos


----------



## EINNER C (Jun 26, 2009)

Hola compañeros, soy nuevo en este foro y es por eso que quiero ingresar aportando algo.

He estado trabajando en la realización de un termómetro digital con visualización en lcd, ya he avanzado un poco en el tema y quiero compartirlo para ver en que me pueden colaborar para pulirlo mejor.

Yo programo en CCS y la simulación la hago en Proteus 7.5 sP3

el código es el siguiente, 

```
// EINNER CRUZ //
// QUETAME, COLOMBIA//

#include <16F877.h>
#device *=16
#device adc=10
#fuses NOWDT,XT, NOPUT, PROTECT, NODEBUG, BROWNOUT, LVP, CPD, NOWRT
#use delay(clock=4000000)
#include <lcd.c>
#define hard_inc !input(PIN_B1)
#define harw_decr !input(PIN_B2)
#define enter !input(PIN_B3)

INT N1, N2, VAR1, VAR2, VAR3, VAR4, TEMP, entrar=0;


void harwd(void)
   {
    lcd_putc("\f     CONFIG  \n  TEMP ESTABLE");
    delay_ms(500);
    lcd_putc("\f   VMIN   VMAX  ");

    while(enter)
      {if(hard_inc)  VAR1++;
       if(harw_decr)  VAR1--;
       printf(lcd_putc,"\n  %d °C_  %d °C ",VAR1,VAR2);
       delay_ms(150);
      }
       delay_ms(150);

    while(enter)
      {if(hard_inc)  VAR2++;
       if(harw_decr)  VAR2--;
       printf(lcd_putc,"\n  %d °C  %d °C_ ",VAR1,VAR2);
       delay_ms(150);
      }
       delay_ms(150);

    lcd_putc("\f AL_VMIN AL_VMAX  ");
    printf(lcd_putc,"\n  %d °C   %d °C ",VAR3,VAR4);

    while(enter)
      {if(hard_inc)  VAR3++;
       if(harw_decr)  VAR3--;
       printf(lcd_putc,"\n %d °C_   %d °C ",VAR3,VAR4);
       delay_ms(150);
      }
       delay_ms(150);

    while(enter)
      {if(hard_inc)  VAR4++;
       if(harw_decr)  VAR4--;
       printf(lcd_putc,"\n %d °C   %d °C_ ",VAR3,VAR4);
       delay_ms(150);
      }
       delay_ms(150);

    lcd_putc("\f   FIN CONFIG  \n  TEMP ESTABLE");
    delay_ms(2000);
   }

void main(void)
   {setup_adc_ports(RA0_ANALOG);
   setup_adc(ADC_CLOCK_INTERNAL);
   setup_counters(RTCC_INTERNAL,RTCC_DIV_1);
   set_adc_channel(0);
   lcd_init();
   

   VAR1=20;
   VAR2=30;
   VAR3=15;
   VAR4=35;
   output_low(PIN_C0);
   output_low(PIN_C1);
   output_low(PIN_C2);


   while(1)
      {
      printf(lcd_putc,"\f  TEMP AMBIENTE ");
      TEMP=(int)read_adc()/2;
      if (TEMP>25)
      TEMP--;
      if (TEMP>65)
      TEMP--;
      printf(lcd_putc,"\n      %d °C ",TEMP);
      delay_ms(300);
      if(VAR1<TEMP<VAR2)
      {output_low(PIN_C0);
      output_low(PIN_C1);
      output_low(PIN_C2);}
      if(TEMP<VAR1)
      {output_high(PIN_C1);}
      if(TEMP<VAR3)
      {output_high(PIN_C2);
      delay_ms(400);}

      if(TEMP>VAR2)
      {output_high(PIN_C0);}
     
      if(harw_decr)
      harwd();
      }

   }
```


El programa realiza el muestreo de la temperatura y lo muestra en una lcd de 2x16, y a ciertas temperaturas que están definidas por defecto al inicio del programa prende o apaga calefactores o ventiladores según sea lo necesario, ademas tiene la opción de modificar esos rangos de temperatura con pulsadores, con el pin harw_decr(rb2) se ingresa al menú de configuración y allí se puede realizar el cambio. 

Cualquier duda o aporte es bien recibida.

Espero que con el aporte de todos los interesados logremos adquirir muchos mas conocimientos sobre el tema.

por ultimo, quería plantearles una duda, como ven ya he trabajado con el ADC del pic pero la verdad no se cual es el tiempo de conversión de este, si alguien sabe se lo agradezco.

Hasta luego.


----------



## cristiancrm (Jul 14, 2009)

Hola amigos, como estan? 

Tengo ganas de armar un medidor de carga de baterias de 12v para autos, el tema es que quiero hacerlo con el PIC16F84A y no se como programar el conversor A/D que tiene para poder realizar este proyectito. La idea simplemente es verificar el nivel de tensión que tiene la bateria que alimenta al circuito del pic, si el nivel de bateria es muy bajo (lo suficiente para no accionar a un par de reles de 12v), automaticamente haga una conmutación a una bateria de backup y que en ese momento accione el circuito de carga para la bateria que se descargo. 
Bueno, si alguien tiene alguna información, se lo voy a agradecer! no pretendo que me pasen el circircuito y el programa, simplemente que me expliquen como funciona el conversor y veo si puedo programarlo.

Muchas gracias!
Cristian .


----------



## gulafranco (Dic 14, 2009)

hola disculpen, he realizado un medidor de temperatura con el conversor del micro que muestra en display, pero la muestra varia muy rapidamente entre valores aleatorios, y nose porq es, alguno sabe? le colocan otro hardware al conversor? si alguien tiene una solucion agradeceria q me ayude. gracias


----------



## Chico3001 (Dic 18, 2009)

Posiblemente tienes un falso contacto en alguno de los pines.... o estas usando cables muy largos y se esta metiendo ruido electrico....


----------



## osac99 (Dic 18, 2009)

El problema esta en el tiempo de muestreo que tienes, baja este tiempo y listo. No te va a dar ningun fallo en la medida ya que la temperatura no cambia bruscamente.


----------



## carlosandres (Feb 22, 2010)

fofo almarales dijo:


> Hola darwin, no vi detalladamente tu programa ya que trabajas con sistema hex a diferencia de mi que trabajo en sistema binario cuando trabajo directamente con registros de proposito especifico. Uno de tus problemas segun lo que vi puede deberse al tiempo de adquisicion necesario para la conversion. Luego de encender el conversor a/d debes hacer un retardo de unos 20 uS recomendablemente. Aunque tu programa parece hacerlo ya que hay muchas instrucciones luego del encendido del adc, pero aqui te paso la rutina que siempre utilizo con el lm35 para que compares. La he utilizado en 3 ocasiones, llevadas a campo y ha resultado.
> Ahora te doy detalles de como lo hice. Primero trabajo con justificacion a la izquierda (utilizando el adresh), ya que asi no tengo problemas con los desbordes del adresl. ademas de eso, la referencia esta a 5 voltios por lo que dividi el resultado de la conversion entre 2 con un rrf por la sensibilidad del lm35.
> 
> 
> ...



hola yo tengo un problema con el ADC del 77A. Al haber configurado todo cual como lo dice el datasheet al leer los valores el los registros ADRESH y ADRESL usando la justificacion a la izquierda veo que solo puedo los 8 bits mas significativos que carga ADRESH pero no los 2 bis menos significativos del ADRESHL, y si justifico a la derecha puedo ver los 2 bits mas significativos del ADRESH mas los 8 restantes no me los muestra el ADRESHL.

Quisiera que me ayudara para poder seguir con mi proyecto ya que este ADC va incluido en el.
aca le dejo mi codigo para ver si quizas usted me pueda corrregir.


```
List    p=16f877A
        Include <P16f877A.inc>
        radix hex


reg1    equ 21h
reg2    equ 22h
bajos    equ 23h
altos    equ 24h
H        equ 0x1e
L        equ 0x1e

        org 0x00
        goto    inicio
        org 0x04
        call retard
        bcf  PIR1,6         ; ADIF = 0
        retfie
        

    
inicio    bsf    STATUS,5    ; entro al banco 1
        bcf STATUS,6
        movlw b'00000001' ; RA0 entrada el resto salida 
        clrf TRISB          ; salida
        clrf TRISC          ; Salida
        clrf TRISD          ; salida
        movlw b'100'      ; RE0, RE1 salidas, RE2 entrada
        movwf TRISE
empieza    movlw b'01001110' ;justifico hacia la izquierda
        movwf ADCON1
        bcf STATUS,5       ;voy al banco 0
        bcf STATUS,6
        movlw b'11000001'; activo el reloj interno del pic
        movwf ADCON0     ; RA0 entrada analogica y activar el modulo de conversion.
        bcf PIR1,6         ; ADIF = 0
        bsf INTCON,6     ; PEIE = 1
        bsf INTCON,7     ; GIE = 1
        bsf STATUS,5     ;         banco 1
        bcf STATUS,6
        bsf PIE1,6         ; ADIE = 1
        

        call retardo      ; tiempo para adquisición
        bcf STATUS,5     ;banco 0
        bcf STATUS,6
        clrf PORTB
        clrf PORTC         ; salida de datos
        clrf PORTD
        clrf PORTE
ini_ADC    bsf    ADCON0,2     ; comienza la conversión
        btfsc ADCON0,2     ; termino la conversión?
        goto $-1             ; No

        bsf    STATUS,5     ; Banco 1
        movf L,0     ; paso los 2 bits mas significativos a W
        movwf bajos
                 ; W a reg3 
        bcf STATUS,5     ; Banco 0
        movf H,0     ; cargo los 7 bits mas significativos a W
        movwf altos         ; W areg4
        movwf PORTB
        movf bajos,0
        movwf PORTE
        call retardo
        goto ini_ADC

retardo movlw 09h          ; .. 40 microseg
        movwf reg1
otravez decfsz reg1,1
        goto otravez
        return

retard    movlw 08h          ; .. 40 microseg
        movwf reg2
repite  decfsz reg2,1
        goto repite
        return

        END
```


----------



## elegaba (May 13, 2010)

saludos a todos
quisiera saber cual es el voltaje minimo de entrada en el puertoa y en los demas puertos..
sucede que debo digitalizar uan señal proveniente de un antena que trabaja a una frecuencia de 1GHz y no se como conectar esa señal al pic para digitalizarla, me podrian colaborar con eso?....si no esta claro lo que quiero hacer diganmelo


----------



## andyjair (Ago 5, 2010)

Hola que tal a todos espero que alguien me pueda ayudar con lo que estoy haciendo...para comenzar utilizo un lenguaje BASIC del PIC SIMULAOR IDE...
Mi problema es el siguiente:::

Tengo un pwm de 25Khz, lo estoy variando con el puertos RA0

Lo que estoy haciendo es tomar una señal de referencia de 0 a 5volts con un potenciometro.. lo meto al convertidor A/D.. pero obtengo un valor de 10 bits.. como le hago para introducir ese valor en el pwm.....

Lo que hago es copiar del registro ADRESL en CCPR1L y los otros 2 bit que estan en ADRESH los copio al CCP1CON  pero al variar el potenciometro me despliega tres veces el pwm

Dicho de otra manera:
comienzo a girar el potenciometro y comienza el pulso desde cero hasta un valor maximo.. al seguir variando el potenciometro, el pulso comienza nuevamente desde cero y va hasta su valor maximo.. asi lo hace hasta 4 veces hasta que el potenciometro llega hasta el final...

yo quiero que lo haga solo una vez.... T_T

aki esta el programa:
--------------------------------------------------------------
Dim conversion As Word


ADCON0 = %10000000  'RA0 entrada analogica,clock A/D Fosc/8
ADCON1 = %10001110  'RA0 analogico ,RA1:RA7 E/S digitales
'6 bits d mas peso ADRESH  a '0'

PR2 = 39
CCP1CON = %00001100  'CCP1 a modulo PWM

pwm:
WaitUs 50
Adcin 0, conversion
CCPR1L = ADRESL  '8 bits LSB del Ciclo de Trabajo

CCP1CON.5 = ADRESH.0  '2 bits menos significativos
CCP1CON.4 = ADRESH.1  'del Ciclo de Trabajo

TRISC.2 = 0

T2CON = 0x04  'prescaler 1:1 y ativacion del TMR2
WaitUs 50
Goto pwm
End


----------



## potri1974 (Sep 1, 2010)

Hola, me interesa mucho tu código. Necesito algo parecido. Estoy intentando hacer un termómetro con un LM35 pero aprovechando los 10 bits de resolución. Me interesa tener el resultado en formato tal que tenga Unidad, Decena y Centena para sacarlo por a 3 displays de 7 segmentos. Creo tu código va por ahí.
Te agradecería que me pudieras ayudar.


----------



## osac99 (Sep 2, 2010)

Que usas para programar el PIC???


----------



## potri1974 (Sep 3, 2010)

Directamente programo en ensamblador.


----------



## osac99 (Sep 3, 2010)

hola alli te pongo el codigo para pasar de un numero de 8 bits a decimal.
el numero decimal se almacena en tres registros: HSD, MSD y LSD.
el goto validar sale con el valor del decimal en los tres registros antes mencionados.

			clrf HSD
			clrf MSD
			movf DATO,w  ;valor a transformar
			movwf LSD
rest 		        movlw d'10'
			subwf LSD,W
			btfss STATUS,C
			goto validar
			movwf LSD
			incf MSD
			movlw d'10'
			subwf MSD,0
			btfss STATUS,Z
			goto rest	    	
			clrf MSD
			incf HSD
			goto rest


----------



## fernandopos (Feb 17, 2011)

EINNER come ta va, estoy incursionando en los micros pic y encontre tu post podes ayudarme a ver como influyen las variables N1 , N2 y entrar, en el proyecto que utiliza el 16f877 para controlar la temperatura?

Otra preg. como controlas cual es la variable que se debe cambiar? si bien entiendo que con los valores de hard_inc y hardw_decr pero como diferencias VAR1, VAR2, VAR3, VAR4.

Saludos.


----------



## EINNER C (Feb 17, 2011)

hola fernandopos

gracias por ves el proyecto y me parece bn que te interese esto de los pic

en cuanto a tu duda, quiero pedir disculpas por no habr quitado las variables N1, N2, entrar, ya que no las uso, las tenia alli por que estaba implementado control desde el pc, que se realizara lo mismo que con los pulsadores pero de una forma grafica mas amigable,,,,,,   en cuanto a lo de las otras variables, puedes ver que la configuracion se realiza en una secuencia, luego de entrar al menu de configuracion empiezas con var1 que indica la temperatura inferior minima, sigue var2 (temp superior maxima), var3 temp muy muy baja y var4 temp muy muy alta, y como aprecias en el main se trabaja en base a estas para prender o apagar dispositivos que controlaran la temperatura

cualquier duda o sugerencia es bienvenida,, 

nota: termine lo de la comunicacion con el pc, espero pronto subirlo, no he tenido mucho tiempo de volver a retomar estos temas,,,,,,,


----------



## fernandopos (Feb 17, 2011)

Gracias por contestar. Efectivamente Einner luego de estudiar al detalle el codigo imagine eso que comentas.
Me interesa la comunicacion con el pc que comentas, cuando tengas si puedes postear para ir anexando conocimientos.
Me interesa mucho este tema de los microcontroladores.

Saludos cordiales.


----------



## 0rland0 (Mar 6, 2011)

Hola, como estan? Alguien sabra como hacer la conversion digital/analogico con ese pic? Recuerdo que cuando vi la materia de microcontroladores el profesor dijo que aunque el pic no tenga ese modulo, se le puede "manipular" para que lo haga


----------



## noerestu (Mar 6, 2011)

0rland0 dijo:


> Hola, como estan? Alguien sabra como hacer la conversion digital/analogico con ese pic? Recuerdo que cuando vi la materia de microcontroladores el profesor dijo que aunque el pic no tenga ese modulo, se le puede "manipular" para que lo haga



Oye.. yo estoy en eso ahorita mismo... la unica manera de hacer una conevercion DIGIAL/ANALOGICA que consegui es con un chip externo, ya sea de comunicacion serial SPI como el TLC5615, o el DAC0800 o DAC0808 de comunicacion paralela..


----------



## 0rland0 (Mar 6, 2011)

noerestu dijo:


> Oye.. yo estoy en eso ahorita mismo... la unica manera de hacer una conevercion DIGIAL/ANALOGICA que consegui es con un chip externo, ya sea de comunicacion serial SPI como el TLC5615, o el DAC0800 o DAC0808 de comunicacion paralela..



Encontre esto,

http://www.todopic.com.ar/foros/index.php?topic=21395.0

y de alli te mandan a http://electronicdesign.com/article...-a-output-using-two-pins-on-a-pic-micro3.aspx


----------



## santiago26 (Mar 30, 2011)

EINNER C dijo:


> hola fernandopos
> 
> gracias por ves el proyecto y me parece bn que te interese esto de los pic
> 
> ...



Hola, disculpa tengo una duda.. cuando doy play para simular en el proteus me salta que hay un error en el codigo.  me podrias dar una mano por favor? gracias.


----------



## EINNER C (Mar 30, 2011)

hola santiago26

a cual codigo te refieres, subelo y vere que puedo hacer, si te refieres a ejemplo que he subido, dime cual es el error ya que debe ser de configuracion en tu proteus,,,

saludos


----------



## camilon96 (Abr 16, 2011)

me   podrian  ayudar como puedo realizar el programa de un conversor analogo digital en mplab para el pic18f4550 de antemano muchas gracias


----------



## parotin (Ago 18, 2011)

Hola a todos. Soy nuevo en el foro. He intentado no preguntar y aprender de los posts que la gente ha enviado anteriormente. Con ello (y otras cosas, claro) he conseguido hacer funcionar el ADC de mi pic16f690 ( Naguk10, esto te interesa), pero ahora me encuentro con un escollo que no soy capaz de superar.

El tema es el siguiente:

Tengo conectados dos potenciometros entre VDD y GND con los que puedo hacer variar la tensi'on en los pines correspondientes a AN2 y AN3 (RA2 y RA4, respectivamente). Soy capaz de leer la tensi'on de cada uno de ellos por separado y pasar la parte alta de ADRESH a los 4 bits de menor peso del puerto C (donde tengo sendos leds conectados).
Si leo solo un canal, todo va de lujo, los leds van mostrando la secuencia en biario del 0 al 16, lo cual es maravilloso jeje. Esto con cualquiera de los dos canales por separado. 
Ahora bien, cuando quiero leer los dos canales de manera secuencial, solo me lee el segundo (o eso creo). En el codigo adjunto podeis ver lo que hago. El tema es que cuando quiero poner en los leds el resultado del primer canal muestreado, me sale siempre el segundo!! cuando los cambio de orden en el codigo, pasa lo mismo.

El codigo en ASM: 


```
#include <p16F690.inc>
     __config (_INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _BOR_OFF & _IESO_OFF & _FCMEN_OFF)



     cblock 0x20
Sensor
Comandament
Delay
Delay1              ; Assign an address to label Delay1
Delay2
Delay11
Delay22
Delay111
Delay222
Display             ; define a variable to hold the diplay
resultat
     endc
          
     org 0
Start:
     bsf       STATUS,RP0     ; select Register Page 1
     movlw     0x1F
     movwf     TRISA          ; part baixa port A entrada, part alta, sortida
     clrf      TRISC          ; Make PortC all output
     movlw     0x10           ; A2D Clock Fosc/8
     movwf     ADCON1
     bcf       STATUS,RP0     ; back to Register Page 0
     bsf       STATUS,RP1     ; address Register Page 2
     movlw     0xFF          
     movwf     ANSEL
     bcf       STATUS,RP0     ; address Register Page 0
     bcf       STATUS,RP1
    
	
MainLoop:

	; Conversio canal del sensor


	 movlw	0x09
  	 movwf  ADCON0			  ; configure A2D for Channel 2 (RA2)
	 nop                      ; wait 10uS for A2D amp to settle and capacitor to charge.
     nop                      ; wait 1uS
     nop                      ; wait 1uS
     nop                      ; wait 1uS
	 nop                      ; wait 1uS
     nop                      ; wait 1uS
	 nop                      ; wait 1uS
     nop                      ; wait 1uS
     nop                      ; wait 1uS
     nop                      ; wait 1uS
     bsf       ADCON0,1     ; start conversion
     btfss     ADCON0,1      ; this bit will change to zero when the conversion is complete
     goto      $-1

	
	movf	ADRESH,w
	movwf	Sensor
	swapf	ADRESH,w
	movwf	PORTC

 		; Conversio canal del comandament

 	 movlw	0x0D
  	 movwf  ADCON0            ; configure A2D for Channel 3 (RA4), Left justified, and turn on the A2D modul
	 nop                      ; wait 10uS for A2D amp to settle and capacitor to charge.
     nop                      ; wait 1uS
	 nop                      ; wait 1uS
	 nop                      ; wait 1uS
     nop                      ; wait 1uS
	 nop                      ; wait 1uS
	 nop                      ; wait 1uS
     nop                      ; wait 1uS
     nop                      ; wait 1uS
     nop                      ; wait 1uS
     bsf       ADCON0,1     ; start conversion
     btfss     ADCON0,1      ; this bit will change to zero when the conversion is complete
     goto      $-1

	movf	ADRESH,w
	movwf	Comandament
	;swapf	ADRESH,w
	;movwf	PORTC  

	
	
	;subwf	Comandament,w	;restam comandament menys sensor, el resultat queda a w. si surt negatiu, el bit carry sera 0
	;btfss	STATUS,C
	;goto	MainLoop
	
	movlw	0xFF
	movwf	Delay2
	
	

		

	
	;movf	Delay2,w
	;sublw	0xFF
	;movwf	Delay1
	;movwf	Delay11
	



;Parpadeig






   	bsf PORTA,5 


OndelayLoop:

	movlw	0x01
	movwf	Delay11
	;movwf	Delay22
On:
	 decfsz    Delay11,f            
     goto      On   


	 decfsz    Delay111,f            
     goto      OndelayLoop
	 

     decfsz    Delay1,f            ; The outer loop takes and additional 3 instructions per lap * 256 loops
     goto      OndelayLoop         ; (768+3) * 256 = 197376 instructions / 1M instructions per second = 0.197 sec.
                                  ; call it a two-tenths of a second.
    
	 
     bcf PORTA,5 

OffDelayLoop:

	movlw	0x01
	;movwf	Delay11
	movwf	Delay22

Off:

	 decfsz    Delay22,f
     goto      Off


	 
	 decfsz    Delay222,f            
     goto      OffDelayLoop



	 decfsz    Delay2,f
     goto      OffDelayLoop

	 

	 
     goto      MainLoop
     end
```


Ha quedado un poco descolocado, pero supongo que se puede ver igual. Lo del parpadeo es para controlar una resistencia mediante un optoacoplador y un triac mediante pulsos.
Los comentarios en ingles son de partes de codigo de micrichip.
Por favor, alguien puede ayudarme?


----------



## MarSteVic (Sep 6, 2011)

Gracias por tu aporte, me gustaria que me hisieras un proteus, porque desea utilizar tu codigo y botar la temperatura en un LCD, se como utilizar el LCD pero no se como realizar la comversion analogico digital desde el P16f877A, CONSIFDERANDO QUE LOGRE MEDIANTE UN AMPLIFICADOR OPERACIONAL QUE LA ENTRADA AL PIC ESTE ENTRE LOS 0 Y 5V, YA QUE EL LM35 BOTA EN mV.


----------



## parotin (Sep 7, 2011)

Hola MarSteVic,

Lo siento pero nunca he utilizado proteus, no lo tengo instalado. La verdad es que yo trabajo bastante "a pelo", no simulo circuitos ni nada de todo eso, simplemente dibujo el layout con PCBWizart, lo imprimo y lo pruebo (supongo que de momento hago cosas muy sencillas). 
Si quieres te cuento a que pines de mi pic va conectada cada cosa, pero eso también se puede deducir del código que adjunté y acaso con ayuda del datasheet de mi pic.
Si te refieres a la configuración que tienes que llevar a cabo para utilizar el A/D del 16f877A, tienes que mirartelo en el DataSheet. El truco está en que hay algunos registros (o posiciones de memória) en los que tiene que haber una serie de 1s y 0s según quieras utilizar un canal, otro, y de que manera (es como lo del TRIS para configurar un puerto como entrada o como salida para encender un led por ejemplo). Busca la sección adecuada en el datasheet (A/D modules, o algo así). Con esa información y un poquito que sepas de programación en ASM (y por supuesto en otros lenguajes de nivel superior con los que puedas operar bit a bit), lo harás funcionar fácilmente.
Si a pesar de todo crees que te puedo ayudar de alguna manera, hazmelo saber.

A mí también me gustaria aprender a utilizar una pantalla LCD. me puedes orientar? algún manual que hayas visto o utilizado? algún ejemplo que esté por ahí colgado??

Gracias por tu comentario acerca de mi aportación, es un placer si te sirve de algo

Ah, se me olvidaba. Yo no puse ninguna etapa de adaptación entre el LM35 y el PIC. Simplemente le puse la tensión de referencia del conversor a 1 volt. Las temperaturas que este sistema controla están siempre por encima de 0 y por debajo de 100 ºC, por tanto, como el LM35 te da 10mv por ºC, puedo cubrir todo el rango de entrada con una buena resolución. Igual puedes hacer lo mismo y te ahorras algo


----------



## Krizz (Mar 5, 2012)

una pregunta si algien me puede ayudar 
Necesito crear un programa con el pic 16f877a y el lm35 dond el pic reconozca la variacion del voltaje que emite el lm35 i la transforme en una salida diguital para encender un led
el proyecto es un termometro que te de la lectura en leds de colores asi x ejemplo: 35° se enciende un led verde; 36° se enciende un led naranja
y asiii entoncs algien sabe kuantas entradas analogicas necesitaria i cuantas salidas digitales tiene este pic xfavor


----------



## mecatronix89 (Mar 5, 2012)

Krizz dijo:


> una pregunta si algien me puede ayudar
> Necesito crear un programa con el pic 16f877a y el lm35 dond el pic reconozca la variacion del voltaje que emite el lm35 i la transforme en una salida diguital para encender un led
> el proyecto es un termometro que te de la lectura en leds de colores asi x ejemplo: 35° se enciende un led verde; 36° se enciende un led naranja
> y asiii entoncs algien sabe kuantas entradas analogicas necesitaria i cuantas salidas digitales tiene este pic xfavor



Hola que tal, solo necesitas 1 ADC y pues 2 Digitales 1/0 para los leds... ya que con la lectura del ADC pues creas reglas dentro del pic, donde diga:
ejem.

if adc == 123;
       {output_b0(0x01);}

siendo que 123 sería por ejemplo 35° solo que no se que valor tenga realmente jeje... y así condicionar el efecto con la variacion del sensor...


----------



## Krizz (Mar 5, 2012)

ahh... asi es entoncs jajaja
i asta kuantas salidas digitales tengo con ese pic?
la verdad no he trabajo con este pic i nose como programarlo mui bn el programa q uso es microcode y para cargar la programacion uso el PICKIT2 pero nose si soolo cargar la programacion puesto que kuando trabajaba con el 16f628A cambiaba la configuracion a  2154 para cargarle la programacion derepente conoces si ay que realizar algun cambio antes de cargarle la programacion?


----------



## EINNER C (Mar 6, 2012)

Krizz dijo:


> ahh... asi es entoncs jajaja
> i asta kuantas salidas digitales tengo con ese pic?
> la verdad no he trabajo con este pic i nose como programarlo mui bn el programa q uso es microcode y para cargar la programacion uso el PICKIT2 pero nose si soolo cargar la programacion puesto que kuando trabajaba con el 16f628A cambiaba la configuracion a 2154 para cargarle la programacion derepente conoces si ay que realizar algun cambio antes de cargarle la programacion?


 

Hola Kriss

Este PIC tienen 40 pines, 4 de los cuales son de alimentacion, 2 mas para el oscilador y el resto los podes configurar como entradas o salidas digitales, el de master clear tambn solo que tienes que configurarlo en los fuses.

saludos


----------



## josera1978 (Abr 27, 2012)

parotin dijo:


> Hola a todos. Soy nuevo en el foro. He intentado no preguntar y aprender de los posts que la gente ha enviado anteriormente. Con ello (y otras cosas, claro) he conseguido hacer funcionar el ADC de mi pic16f690 ( Naguk10, esto te interesa), pero ahora me encuentro con un escollo que no soy capaz de superar.
> 
> El tema es el siguiente:
> 
> ...





Oye segun yo solo tienes un registro en donde se guarda la conversion.... si quieres hacer esto guarda la primera onversion en una variable temporal..... el registro un donde se guarda la conversion se queda con la conversion del ultimo canal que se leyo.....


----------



## jmpl (Oct 18, 2013)

Saludos amigos.
Tengo ya bastante tiempo trabajando para poder aprender a utilizar el conversor de este pic, decidí colocar un potenciometro en Rao para visualizar los valores en binario por medio de una lcd. He realizado esta rutina muchas veces siguiendo los pasos del datasheep y leyendo en varias paginas de interne, al momento de probar esta rutina en proteus 8 el valor del adc aparece como 00000, al momento de hacerlo en fisico el valor del adc se pone loco y aumenta y disminuye sin yo mover el potenciometro entre valores de 350 y 260, cuando quito el cable que me conecta el ra0 con el pin variable del potenciometro estos valores siguen apareciendo, creo que no deberia. no se si alguien me puede pasar un ejemplo para ver como hacen la conversion y guiarme.

anexo el diagrama y el codigo para ver si alguien me puede ayudar, he intentado de todo, ya no se que podra ser 

agradezco a quien pueda ayudarme






```
;******************************************************************************************************************************************
;             PRACTICA PARA EL ADC, UTILIZO UN POTENCIOMETRO EN RA0 Y EL VALOR EN BINARIO LO VISUALIZO EN LA LCD
;
;
;
;******************************************************************************************************************************************
      INCLUDE   <P16F877A.INC>
      LIST P=16F877A
        __CONFIG _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF & _BOREN_ON & _LVP_OFF   

;REDIFINICION DE NOMBRE

#DEFINE  PUERTO_A	PORTA                         
#DEFINE  PUERTO_B  	PORTB
#DEFINE  PUERTO_C  	PORTC
#DEFINE	 LCD_RS	   	PORTC,7
#DEFINE	 LCD_RW	   	PORTC,6
#DEFINE	 LCD_E	   	PORTC,5
#DEFINE	 LCD_PUERTO	PORTB 



		        CBLOCK	H'20'             ;BLOQUE DE VARIABLES O REGISTROS 
			CONT1	
			CONT2
			CONT3
			

			BINARIO_B		
			BINARIO_A			
			DECENAMIL			
			UNIDADMIL		
			CENTENA			
			DECENA	
			UNIDAD	

                        ENDC


  		    	ORG	H'00'
			GOTO        	COMIENZO

			ORG     H'100'
COMIENZO	                CALL	PUERTO 		        ;LLAMDA A PUERTO. 
				CALL	CONFIG_LCD		;LLAMO A CONFIGURACION DE LCD
				CALL    RETARDO3		;ESPERA DE 3 SEGUNDOS
				CALL	VISUALIZAR_LCD		;VISUALIZO EN LA L1 "ING. MECATRONICA"
CICLO				CALL	CONFIG_ADC		;CONFIGURACION DE ADCON 0
				CALL	ADC			;CONFIGURO 
				CALL	VALOR_ADC
				GOTO	CICLO
				
							


 








 
			
								
;*****************************************************************************************************************************************
;          	BLOQUE DE RUTINAS 			BLOQUE DE RUTINAS
;*****************************************************************************************************************************************
PUERTO				BSF 	STATUS,RP0
               			BCF    	STATUS,RP1        
 				MOVLW  	B'111111'
				MOVWF	TRISA
	        		MOVLW  	B'00000000'
				MOVWF	TRISB
				MOVLW	B'00000000'
	          		MOVWF	TRISC
	        		MOVLW	B'00000000' 
	        		MOVWF	TRISD
	        		MOVLW	B'111' 
	        		MOVWF	TRISE
	        		CLRF    OPTION_REG
				NOP
				MOVLW  	B'10000000'  	          
				MOVWF 	ADCON1     	;1PARA ADRSH=2 Y ADRESL=8,0 OSCILADO/8,TODOS ANALOGICOS
 	        		BCF     PIE1,ADIE 	;DESABILITO LA INTERRUPCION DE CONVERSIOB
	        		BCF 	STATUS,RP0	;VUELVO AL BANCO 0
				MOVLW   B'00000000' 
	       			MOVWF   INTCON
	        		RETURN

;******************************************************************************************************************************************
;RUTINA PARA LA CONFIGURACION DE LAS OPERACIONES DE LA LCD

CONFIG_LCD			MOVLW	0X01		;EQUIVALENTE A BORRAR LA LCD
				CALL	CONTROL_LCD	;LLAMO LA HABILITACION DE CONTROL
				MOVLW	0X02		;EQUIVALENTE A RETORDAR EL CURSOR AL INICIO
				CALL	CONTROL_LCD	;LLAMO LA HABILITACION DE CONTROL
				MOVLW	0X06		;CONFIGURA EL MODO DE ENTRADA COMO EL INCREMENTO DEL CURSOR Y MODO NORMAL(AQUIPUEDOACTIVAR DESZPLAZAMIENTO)
				CALL	CONTROL_LCD	;LLAMO LA HABILITACION DE CONTROL
				MOVLW	0X0F		;COFIG DISPLAY CONTROL: DISPALY=ON,CURSOR=ON,PARPADEO DEL CURSOR=ON
				CALL	CONTROL_LCD	;LLAMO LA HABILITACION DE CONTROL
				MOVLW	0X38		;FUNCTION SET:BUS DE 8 BIT,LCD DE 2 LINEAS,CARACTER DE 5X7 PUNTOS
				CALL	CONTROL_LCD	;LLAMO LA HABILITACION DE CONTROL
				MOVLW	0X01		;EQUIVALENTE A BORRAR LA LCD
				CALL	CONTROL_LCD	;LLAMO LA HABILITACION DE CONTROL
				RETURN

;******************************************************************************************************************************************
;RUTINIA DE HABILATACION DE CONTROL Y DATOS PARA LA CONFIGURACION DEL LCD

CONTROL_LCD			MOVWF	LCD_PUERTO	;MUEVO EL VALOR DE W QUE POSEE EL CONTROL AL PUERTO PARA CONFIGURARLO
				BCF	LCD_RW		;COLOCO RW=0 PARA ACTIVAR LA ESCRITURA
				BCF	LCD_RS		;COLOCO RS=0 PARA ACTIVAR EL CONTROL
SALTOX				BSF	LCD_E		;COLOCO	E=0 PARA DAR EL PULSO
				NOP
				NOP			
				BCF	LCD_E		;PARA DAR POR TERMINADO EL PULSO
				BCF	LCD_RW		;PARA LIMPIARLO
				BCF	LCD_RS		;PARA LIMPIARLO
				GOTO	RETARDO1	;VOY AL RETARDO DE 5m SEGUNDOS PARA LA ESPERA DE LA LCD 
DATO_LCD			MOVWF	LCD_PUERTO	;MUEVO EL VALOR DE W QUE POSEE EL DATO A VISUALIZAR EN LA LCD
				BCF	LCD_RW		;COLOCO RW=0 PARA LA ESCRITURA
				BSF	LCD_RS		;COLOCO	RS=1 PARA ACTIVAR EL MODO DE DATOS
				GOTO	SALTOX		;ME VOY A SALTOX PARA DAR EL PULSO DE ACTIVACION Y LIMPIAR LOS REGISTROS

;******************************************************************************************************************************************
VISUALIZAR_LCD			CALL	BORRAR_LCD	;BORRO LA LCD POR SI TENGO ALGO EN ELLA
				MOVLW	'I'		;SEGMENTO 1 LINEA 1
				CALL	DATO_LCD	;LLAMO LA HABILITACION DE DATOS	
				MOVLW	'N'		;SEGMENTO 2 LINEA 1
				CALL	DATO_LCD	;LLAMO LA HABILITACION DE DATOS	
				MOVLW	'G'		;SEGMENTO 3 LINEA 1
				CALL	DATO_LCD	;LLAMO LA HABILITACION DE DATOS	
				MOVLW	'.'		;SEGMENTO 4 LINEA 1
				CALL	DATO_LCD	;LLAMO LA HABILITACION DE DATOS
				MOVLW	' '		;SEGMENTO 5 LINEA 1
				CALL	DATO_LCD	;LLAMO LA HABILITACION DE DATOS
				MOVLW	'M'		;SEGMENTO 6 LINEA 1
				CALL	DATO_LCD	;LLAMO LA HABILITACION DE DATOS
				MOVLW	'E'		;SEGMENTO 7 LINEA 1
				CALL	DATO_LCD	;LLAMO LA HABILITACION DE DATOS
				MOVLW	'C'		;SEGMENTO 8 LINEA 1
				CALL	DATO_LCD	;LLAMO LA HABILITACION DE DATOS
				MOVLW	'A'		;SEGMENTO 9 LINEA 1
				CALL	DATO_LCD	;LLAMO LA HABILITACION DE DATOS
				MOVLW	'T'		;SEGMENTO 10 LINEA 1
				CALL	DATO_LCD	;LLAMO LA HABILITACION DE DATOS
				MOVLW	'R'		;SEGMENTO 11 LINEA 1
				CALL	DATO_LCD	;LLAMO LA HABILITACION DE DATOS
				MOVLW	'O'		;SEGMENTO 12 LINEA 1
				CALL	DATO_LCD	;LLAMO LA HABILITACION DE DATOS
				MOVLW	'N'		;SEGMENTO 13 LINEA 1
				CALL	DATO_LCD	;LLAMO LA HABILITACION DE DATOS
				MOVLW	'I'		;SEGMENTO 14 LINEA 1
				CALL	DATO_LCD	;LLAMO LA HABILITACION DE DATOS
				MOVLW	'C'		;SEGMENTO 15 LINEA 1
				CALL	DATO_LCD	;LLAMO LA HABILITACION DE DATOS
				MOVLW	'A'		;SEGMENTO 16 LINEA 1
				CALL	DATO_LCD	;LLAMO LA HABILITACION DE DATOS
			
				MOVLW	0XC0		;LO UTILIZO PARA MOVERME A LA LINEA 2
				CALL	CONTROL_LCD	;HABILITACION DE CONTROL
				MOVLW	'A'		;SEGMENTO 1 LINEA 2
				CALL	DATO_LCD	;LLAMO LA HABILITACION DE DATOS	
				MOVLW	'D'		;SEGMENTO 2 LINEA 2
				CALL	DATO_LCD	;LLAMO LA HABILITACION DE DATOS	
				MOVLW	'C'		;SEGMENTO 3 LINEA 2
				CALL	DATO_LCD	;LLAMO LA HABILITACION DE DATOS	
				MOVLW	'='		;SEGMENTO 4 LINEA 2
				CALL	DATO_LCD	;LLAMO LA HABILITACION DE DATOS
				MOVLW	' '		;SEGMENTO 5 LINEA 2
				CALL	DATO_LCD	;LLAMO LA HABILITAION DE DATOS
				RETURN

;******************************************************************************************************************************************
;RUTINA PARA BORRAR LA LCD
BORRAR_LCD			MOVLW	0X01		;EQUIVALENTE AL CONTROL BORRAR LCD
				GOTO	CONTROL_LCD	;LLAMO LA HABILITACION DE CONTROL	
;******************************************************************************************************************************************
;RUTINA PARA REGRESAR EL CURSOR AL INICIO
REGRESAR_LCD			MOVLW	0X02		;EQUIVALENTE A RETORDAR EL CURSOR AL INICIO
				GOTO	CONTROL_LCD	;LLAMO LA HABILITACION DE CONTROL
;******************************************************************************************************************************************
CONFIG_ADC			MOVWF	B'01000001'
				MOVWF	ADCON0		;CONFIGURO OSCILADO/8,CANAL 0, GO, ENCIENDO
				GOTO	RETARDO5	;ESPERA EL TIEMPO DE ADQUISICION 25uS
				
;******************************************************************************************************************************************
ADC				BSF	ADCON0,GO	;INICIA EL PROCESO
				CALL	RETARDO5	;ESPERA DE ADQUISICION
REPETIR				BTFSC	ADCON0,2	;CHEQUEO SI LA CONVERSION TERMINO
				GOTO	REPETIR
				MOVFW	ADRESH		;MUEVO LOS 2 BITS MAS SIGNIFICATIVOS A W
				MOVWF	BINARIO_B	;CARGO LOS 2 BITS MAS SIGNIFICATVIOS A 	BINARIO_B
				BANKSEL	ADRESL		;ME MUEVO AL BANCO 1 DONDE ESTA EL ADRESL
				MOVFW	ADRESL		;CARGO EN W EL VALOR DE ADRESL
				BANKSEL	BINARIO_A	;ME MUEVO AL BANCO 0 DONDE ESTA BINARIO_A
				MOVWF	BINARIO_A	;CARGO EL BINARIO_A CON EL VALOR DE 2 QUE VIENE DEL ADRESL
				GOTO	BIN_BCD		;VOY A LA SUBRUTINA BIN_BCD, YA QUE TENGO LOS VALORES DELCONVERTIDOR
				
;****************************************************************************************************************************************
BIN_BCD 			SWAPF 	BINARIO_B,W
				ANDLW 	0X0F
				ADDLW 	0XF0
				MOVWF 	UNIDADMIL
				ADDWF 	UNIDADMIL,F
				ADDLW 	0XE2
				MOVWF 	CENTENA
				ADDLW 	0X32
				MOVWF 	UNIDAD
				MOVF 	BINARIO_B,W
				ANDLW 	0X0F
				ADDWF 	CENTENA,F
				ADDWF 	CENTENA,F
				ADDWF 	UNIDAD,F
				ADDLW 	0XE9
				MOVWF 	DECENA
				ADDWF 	DECENA,F
				ADDWF 	DECENA,F
				SWAPF 	BINARIO_A,W
				ANDLW 	0X0F
				ADDWF 	DECENA,F
				ADDWF 	UNIDAD,F
				RLF 	DECENA,F
				RLF 	UNIDAD,F
				COMF 	UNIDAD,F
				RLF 	UNIDAD,F
				MOVF 	BINARIO_A,W
				ANDLW 	0X0F
				ADDWF 	UNIDAD,F
				RLF 	UNIDADMIL,F
				MOVLW 	0X07
				MOVWF 	DECENAMIL
				MOVLW 	0X0A
LB1				ADDWF 	UNIDAD,F
				DECF 	DECENA,F
				BTFSS	STATUS,C
				GOTO 	LB1
LB2				ADDWF 	DECENA,F
				DECF 	CENTENA,F
				BTFSS 	STATUS,C
				GOTO 	LB2
LB3				ADDWF 	CENTENA,F
				DECF 	UNIDADMIL,F
				BTFSS 	STATUS,C
				GOTO 	LB3
LB4				ADDWF 	UNIDADMIL,F
				DECF 	DECENAMIL,F
				BTFSS 	STATUS,C
				GOTO 	LB4
				RETURN

;****************************************************************************************************************************************
VALOR_ADC			MOVLW	0X30
				ADDWF   DECENAMIL,W
				CALL	DATO_LCD
				MOVLW	0X30
				ADDWF   UNIDADMIL,W
				CALL	DATO_LCD
				MOVLW	0X30
				ADDWF   CENTENA,W
				CALL	DATO_LCD
				MOVLW	0X30
				ADDWF   DECENA,W
				CALL	DATO_LCD
				MOVLW	0X30
				ADDWF   UNIDAD,W
				CALL	DATO_LCD
				MOVLW	0X0C		;COFIG DISPLAY CONTROL: DISPALY=ON,CURSOR=OFF,PARPADEO DEL CURSOR=OFF
				CALL	CONTROL_LCD
				MOVLW	B'11000101'	;POSICIONO EL CURSOR EN LA SEGUNDA FILA POSICION 5 
				GOTO	CONTROL_LCD
;******************************************************************************************************************************************
RETARDO1		   	MOVLW 	.41		;RETARDO DE 5MILISEGUNDOS
				MOVWF 	CONT1
				MOVlW	.41
				MOVWF	CONT2
DEMORA1				DECFSZ 	CONT1,F 
				GOTO 	DEMORA1	
				DECFSZ 	CONT2,F
				GOTO	DEMORA1
				RETURN
;****************************************************************************************************************************************
RETARDO2		  	MOVLW 	.183		;RETARDO DE 1 SEGUNDOS
				MOVWF 	CONT1
				MOVlW	.183
				MOVWF	CONT2
				MOVLW 	.11
				MOVWF 	CONT3
DEMORA2				DECFSZ 	CONT1,F 
				GOTO 	DEMORA2	
				DECFSZ 	CONT2,F
				GOTO	DEMORA2
				DECFSZ 	CONT3,F
				GOTO	DEMORA2
				RETURN
;****************************************************************************************************************************************
RETARDO3		   	CLRF	CONT1		;RETARDO DE 3 SEGUNDOS PARA MOSTRAR EL NUMERO
				CLRF	CONT2
				MOVLW 	.16
				MOVWF 	CONT3
DEMORA3				DECFSZ 	CONT1,F 
				GOTO 	DEMORA3	
				DECFSZ 	CONT2,F
				GOTO	DEMORA3
				DECFSZ 	CONT3,F
				GOTO	DEMORA3
				RETURN
;****************************************************************************************************************************************
RETARDO4			MOVLW 	.18		;RETARDO DE 1MILISEGUNDOS
				MOVWF 	CONT1
				MOVlW	.18
				MOVWF	CONT2
DEMORA4				DECFSZ 	CONT1,F 
				GOTO 	DEMORA4	
				DECFSZ 	CONT2,F
				GOTO	DEMORA4
				RETURN
;****************************************************************************************************************************************
RETARDO5			MOVLW 	.8		;RETARDO DE 25u SEGUNDOS
				MOVWF 	CONT1
DEMORA5				DECFSZ 	CONT1,F 
				GOTO 	DEMORA5	
				RETURN
;****************************************************************************************************************************************
 END
```


----------



## D@rkbytes (Oct 19, 2013)

jmpl dijo:


> Saludos amigos.
> Tengo ya bastante tiempo trabajando para poder aprender a utilizar el conversor de este pic, decidí colocar un potenciometro en Rao para visualizar los valores en binario por medio de una lcd. He realizado esta rutina muchas veces siguiendo los pasos del datasheep y leyendo en varias paginas de interne, al momento de probar esta rutina en proteus 8 el valor del adc aparece como 00000, al momento de hacerlo en fisico el valor del adc se pone loco y aumenta y disminuye sin yo mover el potenciometro entre valores de 350 y 260, cuando quito el cable que me conecta el ra0 con el pin variable del potenciometro estos valores siguen apareciendo, creo que no deberia. no se si alguien me puede pasar un ejemplo para ver como hacen la conversion y guiarme.
> 
> anexo el diagrama y el codigo para ver si alguien me puede ayudar, he intentado de todo, ya no se que podra ser
> ...


Tienes varios errores en tu programa, sobre todo en la configuración del ADC y en la adquisición de datos.
Te adjunto el código corregido y funcionando físicamente, también incluyendo la simulación.
Las partes de código que estaban mal las comenté y lo que añadí al código lo podrás notar porque está escrito con minúsculas.
De esa forma podrás notar que es lo que estabas haciendo mal y que fue lo que modifiqué para que funcionara.

También realicé algunas mejoras al programa en la parte de los mensajes para la pantalla.

Saludos.


----------



## jmpl (Oct 19, 2013)

Gracias por la ayuda tenia tiempo con esa rutina y nada que me daba. gracias gracias, agradecido, voy a revisarla y cualquier cosa te aviso.


----------



## jmpl (Oct 21, 2013)

Disculpa una pregunta que es eso al comienzo del programa que dice errorlevel. -302?
y me puedes explicar un poquito como funciona la instrucción retlw si no es mucha molestia todavía no logro entenderla muy bien. Ahh y otro cosita, estoy intentando de cambiar los pines donde estas conectado los , RS, RW y E de la pantalla, porque donde los tenia necesito esos pines para hacer una comunicación serial, y los quise colocar los 3 en el puerto E , esto se puede?, por que los configure como digitales y salida, y la pantalla no enciende, ( si no vera la posibilidad de ponerlos en otro pines). Gracias por toda la ayuda que me has brindado.GRACIAS.


----------



## D@rkbytes (Oct 21, 2013)

jmpl dijo:


> Disculpa una pregunta que es eso al comienzo del programa que dice errorlevel. -302?


Describiré sin muchos detalles, ya que hay mucha información sobre esto.
*
ERRORLEVEL:* Activa o desactiva los mensajes que manda el compilador.
Estos mensajes se guardan en el archivo *.err y también se muestran en la ventana *Output/ Build
*En este caso, al poner ERRORLEVEL -302 ya no se muestran los mensajes que dicen...
Register in operand not in bank 0.  Ensure that bank bits are correct.
Con + se activan y con - se desactivan. Los códigos de error y advertencias se encuentran en la ayuda de MPASM.


jmpl dijo:


> ¿me puedes explicar un poquito como funciona la instrucción retlw si no  es mucha molestia? todavía no logro entenderla muy bien.


*RETLW:* W retorna con el valor cargado en la línea que asigna PCL
Por ejemplo:
ADDWF PCL,F  --> Se va sumando el puntero.
PCL = 1 -->> RETLW = "H"  --> W retorna con la letra H
PCL = 2 -->> RETLW = "O"  --> W retorna con la letra O
PCL = 3 -->> RETLW = "L"  --> W retorna con la letra L
PCL = 4 -->> RETLW = "A"  --> W retorna con la letra A


jmpl dijo:


> estoy intentando de cambiar los pines donde estas conectado los ,  RS, RW y E de la pantalla, porque donde los tenia necesito esos pines  para hacer una comunicación serial, y los quise colocar los 3 en el  puerto E , esto se puede?, por que los configure como digitales y  salida, y la pantalla no enciende


Si se puede, y si no te funciona debes buscar una rutina más elaborada para controlar la pantalla, pues la que estás usando no tiene los tiempos correctos en la configuración.
Busca aquí en el foro, existen algunas que funcionan bien, y lo puedes hacer con 4 bits.

*Fe de erratas:*
En la rutina CONFIG_ADC puse lo siguiente...
    movlw    b'00000111'
    movwf    OPTION_REG        ; Desactivar los comparadores analógicos.

Lo correcto debe ser...
movlw b'10000000'
    movwf OPTION_REG        ; Limpiar el registro OPTION_REG  y sin resistores pull-up

Suerte.


----------



## jmpl (Oct 21, 2013)

Gracias nuevamente despejaste mis dudas, eternamente agradecido, decide no colocarlos en el puerto E los coloque en otros pines del C y me funciona perfectamente, cuidado de no ser los Tx y Rx. Buscare esas rutinas para aprender mas. Ahora voy con la comunicación serial y un reloj en tiempo real con TMR 1 . Gracias amigo tal vez te ladillo un poquito cuando este ahogado con lo que me viene jajaja. Gracias amigo.


----------



## tom135 (Nov 6, 2013)

Hola a todos! Tengo un inconveniente y agradeciera su ayuda.
Ya he hecho el código del conversor, pero antes de mandarlo al LCD quiero que la salida se aprecie en leds y al momento de simularlo en proteus para el voltaje máximo (5v) se prenden casi todos los LEDs menos uno (RD0)
O si no cuando el voltaje es mínimo (0v) todos los LEDs están apagados excepto uno (también RD0).
¿Quisiera saber si tienen idea de por qué ocurre eso? Gracias.


```
////////////////////CODIGO//////////////////////////

#include <htc.h>
#ifndef _XTAL_FREQ
    #define _XTAL_FREQ 10000000
#endif
#include "adc.h"
#include "lcd.h"

void MCU_init(){
    TRISA = 0XFF;
    PORTD = 0X00;
    TRISD = 0X00;
}

void conv_voltaje(){
    int vmax = 5; float v_lcd;
    __delay_us(20);
    adc_read(1);
    __delay_us(10);
    PORTD = ADRESH;
    //v_lcd = PORTD*vmax/255;
}

void main(){
    MCU_init();
    lcd_init();
    while(1){
        conv_voltaje();
    }
}

///////////////////////////////////////////////////////////
```

Les dejo el código por si es necesario. Uso HI-TECH


----------



## D@rkbytes (Nov 7, 2013)

tom135 dijo:


> Hola a todos! Tengo un inconveniente y agradeciera su ayuda.
> Ya he hecho el código del conversor, pero antes de mandarlo al LCD quiero que la salida se aprecie en leds y al momento de simularlo en proteus para el voltaje máximo (5v) se prenden casi todos los LEDs menos uno (RD0)
> O si no cuando el voltaje es mínimo (0v) todos los LEDs están apagados excepto uno (también RD0).
> ¿Quisiera saber si tienen idea de por qué ocurre eso? Gracias.


Adjunto un código trabajando el ADC a 8 Bits, también incluyo la simulación.

Se manda el valor leído al puerto C sobre unos LED's y también se muestra el valor en una pantalla LCD 16x2.

Nota:
La modificación al código para realizar una lectura de 10 bits no es complicada.

Suerte.


----------



## Lord Chango (Mar 5, 2018)

Hola a todos, perdón por revivir el tema pero no quería abrir uno nuevo para sólo hacer una consulta.

Estoy trabajando con el ADC del PIC16F887, de 10 bits de resolución. Con ésto, obtengo aproximada y teóricamente una lectura mínima de 0,1%.
Estaba pensando en alguna forma de mantener el error constante al ir variando las mediciones pero me parece que se me va en complejidad.

Por eso estaba pensando en, por ejemplo, en colocar un divisor resistivo al pin de +Vref  y cambiar la referencia segúna la medida se encuentre por encima (Vdd) o por debajo (Vdd/2) de la zona media de mediciones.

Es viable esto? Puede traer algún problema en las mediciones?

Saludos!


----------



## D@rkbytes (Mar 5, 2018)

Si colocas un divisor resistivo para modificar Vref, estará sujeto a los cambios en VDD.
Por eso es recomendable usar un regulador ajustable, por ejemplo un TL431.
Aún así, no creo que eso mejore el error, ya que eso es parte de conversor.
Lo que si lograrás cambiar será el rango del voltaje análogo a la entrada.
Que para 5 V será:  (5 / 1024) = 4.8 mV por paso. Y limitando el rango de entrada con Vref a 2.5 V estaría a la mitad. 2.4 mV por paso.


----------

