desktop

Problema con adc pic 16f716

Buenas tardes!!

Pasando al tema, estoy realizando un programa en CCS para obtener datos atreves de los puertos análogos del micro, pero tengo un problema al comparar los datos con una variable antes definida, creo que es error de sintaxis pero por mas que le muevo no puedo hacer que funcione y me veo en la necesidad de pedirles ayuda.

Explico mejor mi problema:

Código:
#include <16F716.h>
#Fuses XT, NOWDT
//#device ADC=10
#Use Delay(Clock=4 000 000)
#byte puerto_b = 06

long Dato1, Dato2, Dato3, Dato4, set, setb, sat, satb;


#separate
void x1(){
 set_adc_channel(0);   //lee canal 0
       delay_ms(10);
       Dato1=read_ADC();      
       delay_ms(20);
       
if(dato1>setb){
         output_high(pin_B0);  
                  output_low(pin_B1);
                  output_low(pin_B3);
                  }
       else{
       output_low(pin_B0);
         output_low(pin_B1);
                  output_low(pin_B3);
       } 
}

#separate
void mhr23(){

 set_adc_channel(0);  
       delay_ms(10);
       Dato1=read_ADC();      
       delay_ms(20);

 if(dato1<sat)
         output_high(pin_B0);  
       else{
       output_low(pin_B0);
       }
       if(dato1>satb)
         output_high(pin_B0);
}

#separate
void cto(){
 set_adc_channel(0);   //lee canal 0
       delay_ms(10);
       Dato1=read_ADC();      
       delay_ms(20);

 set_adc_channel(1);   //lee canal 1
       delay_ms(10);
       Dato2=read_ADC();      
       delay_ms(20);

 if(dato1<set)
         output_high(pin_B2);  
       else{
       output_low(pin_B2);
       }
       if(dato1>setb)
         output_high(pin_B2);
         
       ////////////////////////
         
       if(dato2<set)
         output_high(pin_B3);  
       Else{
       output_low(pin_B3);
       }
       if(dato2>setb)
         output_high(pin_B3);

}

#separate
Void main(){
dato5=0;
dato6=0;
dato7=0;
dato8=0;
   
   setup_ADC_ports( ALL_ANALOG );   ///declaras en pin AN0 como entrada Analog
   setup_ADC(ADC_Clock_Div_32);  ///Configuras la velocidad de muestreo
   sat=0xE1;
   satb=0xD5;
   set=0xE8;
   setb=0xEF;

   while(True){
     if (input(pin_b4)==0)
      {
      x1();
                      
   } 
   else if(input(pin_b5)==1){
   mhr23();
   }
   else {
    cto();
   }
  } 
 }


el problema esta en que la rutina de x1 y de cto si funcionan pero al comparar con otra variable por ejemplo paso de comparar set a sat y ya no funciona la rutina, solo la rutina x1 y cto, bueno espero me haya explicado bien y me puedan ayudar de antemano gracias!!.

PD: soy novato programando sorry por los horrores de código :D.
 
Última edición por un moderador:
Hola a todos. Me dirijo a ustedes luego de agotar mis ojos leyendo foros en inglés y manuales.
Estoy trabajando con un voltímetro con un PIC16F716 usando el ADC del PIC.
En proteus corre bien, pero a la hora de pasar el .hex al micro en un protoboard con un PICkit2, no hace ni pío.
Pensando que el código estaba mal, hice un código sencillo para encender un LED por el puerto B, pero al cargarlo al PIC tampoco funciona.

Este es el código en C de CCS:
Código:
#include <16F716.h>
#FUSES XT,NOWDT
#use delay(clock=4000000)
#BYTE portb=6       //puerto B en 06h
#BYTE porta=5       //puerto A en 05h 
#BYTE trisa=133     //TRISA en 85h
#BYTE trisb=134     //TRISB en 86h

void main()
{
trisb=0;

while(true) {
portb=255;
delay_ms(300);
portb=0;
delay_ms(300);

}
}
En el protoboard está todo cableado correctamente.
Como es solo un LED, estoy alimentando con los 5V del PICkit2
El cristal que uso es de 4Mhz y los capacitores de 22pF, una Resistencia de 10K entre MCLR y 5V y el LED con resistencia de 330 a RB0. No hace nada.

¿Alguien podría ayudarme a encontrar que es lo que anda mal?
De antemano, gracias.
 
no se si yo sea un mal prgramador pero jamas declaro los tris de los pic en CCS

yo hubiera dejado el codigo asi


#include <16F716.h>
#FUSES XT,NOWDT
#use delay(clock=4M)

void main()
{

while(true) {
output_b(255);
delay_ms(300);

output_b(0);
delay_ms(300);

}
}


el pic16f716 es un pic bastante facil de usar ami me gusta mucho por que es muy barato



respecto al ADC tambien es muy facil declararlo solo hay que seguir las instrucciones del CCS
lo que leas en el ADC lo puedes guardar en un registro de 8 bits que puede ser un CHAR
y lo puedes reflejar directamente en el puerto del pic
 
Última edición:
En el protoboard está todo cableado correctamente.
Como es solo un LED, estoy alimentando con los 5V del PICkit2
El cristal que uso es de 4Mhz y los capacitores de 22pF, una Resistencia de 10K entre MCLR y 5V y el LED con resistencia de 330 a RB0. No hace nada.
El código que pones debería funcionar sin problemas, y el código que puso papirrin haría lo mismo pero usando las instrucciones del PICC Compiler.
No sé si yo sea un mal programador, pero jamás declaro los TRIS de los PIC en CCS
No es necesario en algunos casos.
Lo que si es necesario, es darles un estado inicial a los pines configurados como salida.
Definir un puerto puede servir para realizar esto por ejemplo:
PHP:
void main (void)
{
   trisb = 0;
   portb = 0;

   while (true)
   {
      portb =~ portb;
      delay_ms(300);
   }
}
Que tendría el mismo efecto, pero con menos código.

¿Alguien podría ayudarme a encontrar que es lo que anda mal?
Prueba quitando los capacitores del cristal, porque algunos los tienen internos y los externos pueden bloquear la oscilación.
Si no consigues que funcione, prueba con otro cristal.
También asegúrate de que el pin 4 si tenga +5V al igual que el pin 14. Y obvio, el pin 5 a negativo.
 
Última edición:
Probé tu código, sigue pasando lo mismo, al menos ya se que el oscilador funciona bien (adjunto imagen osciloscopio entre GND y OSC1) La verdad no sé que puede ser si no es el oscilador.
 

Adjuntos

  • ScreenShotxd039.jpg
    ScreenShotxd039.jpg
    71.5 KB · Visitas: 9
Si el cristal es de 4MHz, debes obtener 2MHz en la salida, pin 15.
Ese PIC no tiene nada extraordinario para que no puedas lograr que funcione ese código.
Si dices que tienes todo bien conectado, entonces el PIC murió. :rolleyes:

¿Qué pasa con el puerto A?
¿Ya probaste ese puerto?
En PICC de CCS, y en la versión que tengo, (5.027) no es necesario establecer con setup_adc_ports() que los pines con ADC sean digitales para realizar una prueba del puerto A.
A menos que sí se especifique para usar el ADC.
ADCON1 será 0b00000111 (o sea: Digital I/O) si no se utiliza setup_adc_ports(parámetros);

Otra cosa que ha sucedido con PICC Compiler, es que ha tenido problemas con algunas definiciones.
Puedes probar actualizando la versión que estás usando actualmente.
 
Última edición:
Ahora funciona, cambie el cristal y el fuse para oscilador RC y funciona. Tambien noté (ahora que funciona) cierta holgura entre las resistencias y el proto que me apaga el led y no pasa nada, quizas eso esté pasando con el voltimetro, trataré de armar todo de nuevo y comentar. Probaré denuevo con cristal de 4mhz y uno de 27mhz

Funciona con XT y HS.
Consulta, en CCS 5.015 al usar el Project Wizard y establecer el oscilador no se donde configura los Fuses, genera un archivo .h pero en el tampoco se encuentra dicha configuración. ¿cómo lo hace? porque cargue un example code de un blink e igual funciona.
 
Última edición:
El fuse RC es precisamente para usar un oscilador externo RC (Resistencia y Capacitor)
Con un cristal no debería funcionar.

Yo no uso el wizard, establezco todas las configuraciones en el archivo main.
Pero es aquí:Tipo de PIC y oscilador.jpg
Y se genera el archivo *.h con lo siguiente:
Código:
#include <16F716.h>
#device ADC=16
#use delay(crystal=4MHz)
Agrega #device ADC=16
Y si no se va a usar el ADC, sale sobrando.
Así sucede con otros PIC, agrega cosas que no se van a usar.
Por eso es que prefiero editar mis opciones yo mismo.
 
Se está haciendo con #use delay(crystal=4MHz)
Cuando se usa este tipo de configuración, se le está diciendo al compilador que se usará un cristal de 4MHz.
Entonces el compilador sabrá que debe usar fuse XT (_XT_OSC en ensamblador.)
También quedan otros fuses por defecto: 16F716 Fuses con cristal 4MHz.jpg
Si te fijas, los fuses que se establecen son correctos para el funcionamiento.

Si no tienes muchos conocimientos, puedes usar el wizard para otras configuraciones más.
Y también puedes editarlo después de haber sido creado.
En la barra desplegable del lado izquierdo, "Files" das doble click sobre el archivo "main.h" y lo editas.
Por ejemplo así, de la forma habitual:
Código:
[B][COLOR=Red]#include[/COLOR] <[COLOR=SeaGreen]16[/COLOR]F716.h>
[COLOR=Red]#fuses[/COLOR]   XT
[COLOR=Red]#use[/COLOR]    delay(clock = [COLOR=SeaGreen]4000000[/COLOR])[/B]
De esta otra forma se obtendrá el mismo resultado en la configuración de fuses.

Y si lo deseas, puedes omitir el fuse BROWNOUT y BORV agregando lo siguiente:
#fuses XT, NOBROWNOUT, BORV25
Quedando la palabra de configuración de esta forma: 16F716 Fuses sin Brownout Reset.jpg
El fuse PUT o _PWRTE_ON es conveniente que esté habilitado, pues se logra que el PIC se mantenga en estado de reset durante unos 72ms cuando es alimentado y con esto esperar a que se estabilice la tensión.

Entonces, tú decides si usar el wizard o establecer por ti mismo la configuración del PIC.
 
OK gracias amigo veo entonces que el delay de ccs 5 no es el mismo de antaño. Entendido lo del Power on timer pero ¿donde ves ese cuadrito con los fuses que muestras?
 
Hola de nuevo, les cunto que tengo lista la pcb del voltimetro pero ahora em ocurre algo raro: al meter tension directo por RA1 al pic y mostrar el valor en el display funca todo bien, pero al meter la tensión por un divisor de tensión de 100k-10k, tomando la señal en el punto de union de las resisencias, de forma de medir lo que cae en la R de 10k marca siempre 0 y toda la tensión cae en la R de 100k como si la impedancia de entrada del pic fuese muy baja, alguien podría decirme que sucede en este caso?
 
Al meter tensión directo por RA1 al pic y mostrar el valor en el display funca todo bien, pero al meter la tensión por un divisor de tensión de 100k-10k, tomando la señal en el punto de unión de las resistencias, de forma de medir lo que cae en la R de 10k marca siempre 0
¿Cual es el voltaje máximo que quieres medir?
 
Probe con 10k y 1k y sigue pasando lo mismo.
Deseo medir el voltaje de una fuente 0-30v así cuando hayan 30V en la entrada en la R menor habrán 30/11 V
 
No, así no está bien tu divisor.
Estudia sobre el divisor de tensión y determina que resistencias debes usar para obtener el voltaje que necesites conforme a la tensión de referencia del PIC.

Y aparte algo debe tener tu programa, es mejor que lo adjuntes para revisarlo.
 
Si la tension de referencia del pic está ajustada a 0V:

Por divisor de tensión V2= Vin*R2/(R1+R2)

Si quiero medir hasta 30V sin llevar al limite al pic puedo usar R1=100k R2=10k
V2=V(RA1)=30*1K/(100K+10K) = 30/11 V = 2.72V
Código:
#include <16f716.h> //pic16f716
#device adc=8       //ADC 8 bits
#FUSES NOWDT
#FUSES NOBROWNOUT 
#FUSES XT           
#use delay(clock=3800000)
#BYTE portb=6       //puerto B en 06h
#BYTE porta=5       //puerto A en 05h 
#BYTE trisa=133     //TRISA en 85h
#BYTE trisb=134     //TRISB en 86h

#DEFINE del 5
#DEFINE time 200

    int16 unidades (int16 numero) ;
    int16 decenas (int16 numero) ;
    int16 centenas (int16 numero) ;
    int16 miles (int16 numero) ;
    void print_seg (int16 value) ;
    
void main() 
{
   
   int16 lectura,vi,r1,r2;

   r1=100; //R1=100k
   r2=10; //R2=1K
 
   trisa=17; 
   trisb=0x00; 

   
   setup_adc_ports(AN0_AN1_AN3); 
   delay_us(20);
   setup_adc(ADC_CLOCK_DIV_2); 
   delay_us(20); 
   while (true)
   {

         set_adc_channel(1);
         delay_us(50);
         lectura=read_adc();
         delay_us(50);
         vi=1.9607*((r1+r2)/r2)*lectura;

         print_seg(vi);
      }
      
   }

int16 unidades(int16 numero)
{
   int16 unidades = 0;
   unidades = numero % 10;
   return unidades;
}
int16 decenas(int16 numero)
{
   int16 decenas = 0;
   decenas = (numero / 10) % 10;
   return decenas;
}
int16 centenas(int16 numero)
{
   int16 centenas = 0;
   centenas = (numero / 100) % 10;
   return centenas;
}
int16 miles(int16 numero)
{
   int16 miles = 0;
   miles = (numero / 1000) % 10;
   return miles;
}
void print_seg(int16 value)
{
   portb=16+unidades(value);
   bit_clear(porta,4); //Pone a 0 RA4 para prender punto dec.
   delay_ms(del);
   bit_set(porta,4);
   portb=32+decenas(value);
   delay_ms(del);
   portb=64+centenas(value);
   delay_ms(del);
   portb=128+miles(value);
   delay_ms(del);
}
 
Prueba ahora el programa adjunto con algunas modificaciones.
No tengo el PIC16F716 que estás usando, así que no lo puedo probar físicamente.
Con algún otro PIC tal vez funcione y posiblemente luego realice el montaje.

PD:
El esquema está diseñado de esa forma porque se incluye la simulación y así es como funciona mejor.
Físicamente, se tienen que sustituir los inversores por transistores NPN.

Suerte.
 

Adjuntos

  • Esquema Voltímetro 30V.jpg
    Esquema Voltímetro 30V.jpg
    112.2 KB · Visitas: 25
  • 16F716 Voltímetro 30V.rar
    27.9 KB · Visitas: 7
Última edición:
Atrás
Arriba