Autor Tema: Código sencillo en 16F84A  (Leído 3079 veces)

0 Usuarios y 2 Visitantes están viendo este tema.

Desconectado Wheatley

  • PIC10
  • *
  • Mensajes: 7
Código sencillo en 16F84A
« en: 18 de Mayo de 2013, 07:43:44 »
Estoy escribiendo un código en C para un PIC 16F84A en MPLAB y no consigo compilarlo.
Tengo conocimientos básicos de C, de haber cursado una asignatura en ingeniería industrial, así que no se identificar los errores que saltan. Alguna ayuda?
Ahí va el código:

Código: [Seleccionar]
#include "16F84A.h"
#use delay(clock=20000000)
#define SENSORA PIN_A0
#define SENSORB PIN_A1
#define RAPIDO PIN_B0
#define LENTO PIN_B1
void main(void)
{
int velocidad, espacio, tiempo;
espacio=1;
if (SENSORA != 0)
{
   SETUP_TIMER_0(RTCC_INTERNAL|RTCC_DIV_2|RTCC_8_BIT);
}
if (SENSORB != 0)
{
   tiempo=get_timer0();
}
velocidad= espacio/ tiempo;
if (velocidad >= 1)
{
   OUTPUT_HIGH(RAPIDO);
 else
   OUTPUT_HIGH(LENTO);
}
}

Y una captura de MPLAB después de intentar compilar:



Uploaded with ImageShack.us

Gracias y un saludo.
« Última modificación: 18 de Mayo de 2013, 07:49:57 por Wheatley »

Desconectado man3s

  • PIC12
  • **
  • Mensajes: 69
Re: Código sencillo en 16F84A
« Respuesta #1 en: 18 de Mayo de 2013, 09:18:14 »
Bueno amigo, he notado un error:

Si lo que deseas es preguntar por una entrada debes utilizar la funcion input(),
La funcion input() regresa true (1) si la entrada esta en estado alto o false (0) si esta en estado bajo, entonces, en lugar de:
Citar
if (SENSORA != 0)
debes utilizar:
Citar
if(input(SENSORA) !=0)
o simplemente
Citar
if(input(SENSORA))
ya que lo que haces es preguntar por el estado diferente de cero, es decir 1, eso para todos los pines de entrada que desees saber su estado.

Tambien note el siguiente detalle en tu if:

Citar
if (velocidad >= 1)
{
   OUTPUT_HIGH(RAPIDO);
 else
   OUTPUT_HIGH(LENTO);
}

Lo que seguramente intentaste hacer es lo siguiente:
Citar
if (velocidad >= 1)
{
   OUTPUT_HIGH(RAPIDO);
 }else{
   OUTPUT_HIGH(LENTO);
}

Recuerda que la estructura del if es:
Citar
if(condicion){
     //codigo
}else{
    //codigo
}

aunque tambien pudiste simplemente escribir:
Citar
if (velocidad >= 1)
   OUTPUT_HIGH(RAPIDO);
 else
   OUTPUT_HIGH(LENTO);

debido a que solo existe una unica linea despues del if o else.

En cuanto a que uso le das a tu programa no lo mencionas, pues solo mencionar que:

Citar
tiempo=get_timer0();

solo obtiene el valor del timer crudo, es decir en "ticks" no en unidad de tiempo, toma en cuenta eso,
y espero recuerdes que los timers se desbordan pasado x tiempo por lo cual yo resetearia el timer cuando ya halla leido el valor y asi empezar a contar desde 0.

Tambien noto que la variable espacio nunca cambia, ya que has inicializado a 1
Citar
...
espacio=1;
...
velocidad= espacio/ tiempo;

por lo cual no veo sentido declarar una variable para dicho fin, a menos de que tu codigo aun no la implemente hasta este punto  :mrgreen:.

y un error (horror) 1/tiempo devuelve un float por lo cual al intentar guardarla en una variable entera se hara un casting a int, perdiendo exactitud y en este caso nunca vas a tener un valor en velocidad.

Citar
velocidad= espacio/ tiempo;

Sumado a esto yo daria pequeños retardos (~20ms) a la "salida" de los if para permitir que la señal de la entrada se disipe y no reentre al if innecesariamente.

Creo es todo lo que note, saludos.




Desconectado Wheatley

  • PIC10
  • *
  • Mensajes: 7
Re: Código sencillo en 16F84A
« Respuesta #2 en: 18 de Mayo de 2013, 11:04:14 »
Antes de nada muchas gracias por la ayuda ;)

He modificado los ifs que mencionas, quedando el código así:

Código: [Seleccionar]
#include "16F84A.h"
#use delay(clock=20000000)
#define SENSORA PIN_A0
#define SENSORB PIN_A1
#define RAPIDO PIN_B0
#define LENTO PIN_B1
void main(void)
{

int velocidad, espacio, tiempo;
espacio=1;

if(input(SENSORA))
   SETUP_TIMER_0(RTCC_INTERNAL|RTCC_DIV_2|RTCC_8_BIT);

if(input(SENSORB))
   tiempo=get_timer0();

velocidad= espacio/ tiempo;

if (velocidad >= 1)
   OUTPUT_HIGH(RAPIDO);
 else
   OUTPUT_HIGH(LENTO);

}



Uploaded with ImageShack.us

Primero te respondo a los errores que comentas que no sé como arreglar y luego te comento lo que se pretende hacer con el código:


Citar
tiempo=get_timer0();

solo obtiene el valor del timer crudo, es decir en "ticks" no en unidad de tiempo, toma en cuenta eso,
y espero recuerdes que los timers se desbordan pasado x tiempo por lo cual yo resetearia el timer cuando ya halla leido el valor y asi empezar a contar desde 0.

La variable tiempo debe recoger (en segundos, claro) el valor de tiempo transcurrido entre los instantes en los que SENSORA es distinto de 0 y SENSORB es distinto de 0.
El problema es que no tengo muy claro el funcionamiento del timer0 del PIC. Lo ideal sería recoger el tiempo con una exactitud de milisegundos.


Tambien noto que la variable espacio nunca cambia, ya que has inicializado a 1
Citar
...
espacio=1;
...
velocidad= espacio/ tiempo;

por lo cual no veo sentido declarar una variable para dicho fin, a menos de que tu codigo aun no la implemente hasta este punto  .

y un error (horror) 1/tiempo devuelve un float por lo cual al intentar guardarla en una variable entera se hara un casting a int, perdiendo exactitud y en este caso nunca vas a tener un valor en velocidad.


La variable espacio se pretende que sea introducida mediante un ordenador, es la segunda parte del código (que aún no ha sido comenzada). Si no consiguiera implementarlo la variable se quedaría con valor 1.


Función del código.

Colocaré dos sensores (SENSORA y SENSORB) a una distancia (tal vez variable, si consigo implementar la segunda parte del código). Cuando un móvil atraviese el primer sensor se activará el contador, cuando pase el segundo se parará. Este valor se recogerá en la variable tiempo. Después de la operación para hallar la velocidad, se evaluará entre dos opciones.

Gracias de nuevo ;)

Un saludo.
« Última modificación: 18 de Mayo de 2013, 11:09:23 por Wheatley »

Desconectado man3s

  • PIC12
  • **
  • Mensajes: 69
Re: Código sencillo en 16F84A
« Respuesta #3 en: 18 de Mayo de 2013, 13:58:51 »
Un detalle muy grande, y del que no me percate la primera vez  :D, es que no tienes tu bucle infinito, entonces tu codigo solo se realizara una unica vez, deberia ser algo asi:
Citar
void main(){
   for(; ;){  //o while(1)
       //...tu codigo
   }
}

En cuanto a el uso del timer te recomiendo que primero sepas como funciona, te recomiendo esta pg, espero los MODs no se enojen xD,,,: http://www.aquihayapuntes.com/indice-practicas-pic-en-c/uso-del-tmr0-como-temporizador.html.

EDITO:
Este codigo lo he compilado de manera correcta en el IDE que trae el CCS
Código: [Seleccionar]
#include "16F84A.h"
#use delay(clock=20000000)
#define SENSORA PIN_A0
#define SENSORB PIN_A1
#define RAPIDO PIN_B0
#define LENTO PIN_B1
void main(void)
{

      int velocidad, espacio, tiempo;
   espacio=1;
   for(;;){
      if(input(SENSORA))
         SETUP_TIMER_0(RTCC_INTERNAL|RTCC_DIV_2|RTCC_8_BIT);

      if(input(SENSORB))
         tiempo=get_timer0();

      velocidad= espacio/ tiempo;
     
      if (velocidad >= 1)
         OUTPUT_HIGH(RAPIDO);
      else
         OUTPUT_HIGH(LENTO);
   }
}
para mi que el detalle esta en el MPLABX, por lo que veo metiste el codigo fuente en la parte de librerias y no se si por eso te genere error, yo siempre los creo en Source File, aunque de ese IDE se aun poco, apenas empiezo a usarlo, pero no le veo sentido utilizarlo, con el IDE que trae el CCS me basta.
« Última modificación: 18 de Mayo de 2013, 14:12:03 por man3s »

Desconectado Wheatley

  • PIC10
  • *
  • Mensajes: 7
Re: Código sencillo en 16F84A
« Respuesta #4 en: 20 de Mayo de 2013, 05:43:16 »
Intento compilar éste código en PCW Compiler y tengo dos problemas:

1. Al crear un proyecto, no sale el 16F84A en la lista de PICs.

2. Me da dos errores.

El código:

Código: [Seleccionar]
#include "C:\Users\acer\Dropbox\Proyecto Automática\definitivo.h"
#int_TIMER0
#include "16F84A.h"
#use delay(clock=4000000)
#define SENSORA PIN_A0
#define SENSORB PIN_A1
#define RAPIDO PIN_B0
#define LENTO PIN_B1

void main(void)
{

   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_CLOCK_DIV_2);
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);setup_wdt(WDT_18MS);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   enable_interrupts(INT_TIMER0);
   enable_interrupts(GLOBAL);

   int velocidad, espacio, tiempo;
   espacio=1;
   for(;;)
   {
      if(input(SENSORA))
         SETUP_TIMER_0(RTCC_INTERNAL|RTCC_DIV_2|RTCC_8_BIT);

      if(input(SENSORB))
         tiempo=get_timer0();

      velocidad= espacio/ tiempo;
     
      if (velocidad >= 1)
         OUTPUT_HIGH(RAPIDO);
      else
         OUTPUT_HIGH(LENTO);
   }
}

Una captura de los errores:



Uploaded with ImageShack.us

Desconectado Wheatley

  • PIC10
  • *
  • Mensajes: 7
Re: Código sencillo en 16F84A
« Respuesta #5 en: 20 de Mayo de 2013, 08:39:23 »
Ya he conseguido compilarlo  :-/
Ahora no consigo quemarlo, el programador que utilizo es un TE-20x. Que software se utiliza para este programador?

Desconectado ppyote

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 929
Re: Código sencillo en 16F84A
« Respuesta #6 en: 20 de Mayo de 2013, 08:55:26 »
ic-prog por ejemplo
PPyote... siempre estareis en mi corazon.... Te quiero Hermano...

Desconectado Wheatley

  • PIC10
  • *
  • Mensajes: 7
Re: Código sencillo en 16F84A
« Respuesta #7 en: 20 de Mayo de 2013, 11:34:05 »
ic-prog por ejemplo

Sigo teniendo problemas (para no variar). Ahora el PC no reconoce el programador a menos que se conecte directamente por un puerto serie (del cual no dispongo en casa). Parece que el conversor USB/R232 no funciona, aunque el PC reconoce el dispositivo conectado y he instalado los drivers.

Desconectado man3s

  • PIC12
  • **
  • Mensajes: 69
Re: Código sencillo en 16F84A
« Respuesta #8 en: 20 de Mayo de 2013, 12:30:58 »
Parece que ese programador no funciona con el cable convertidor Ver post , seria bueno te consigas un master-prog o compres uno, no son muy caros y he visto que salen buenos (creo son clones del pickit). Saludos  :mrgreen:.

Desconectado Wheatley

  • PIC10
  • *
  • Mensajes: 7
Re: Código sencillo en 16F84A
« Respuesta #9 en: 22 de Mayo de 2013, 04:34:23 »
He podido hacerme con un PicKit3 y he grabado el 16F84A sin problemas ;)
Luego implementaré el circuito porque ahora mismo no tengo cable para hacerlo.

Hay algún problema con no utilizar MPLAB como entorno para codificar y compilar el código y luego grabar en un pickit3?

El código:

Código: [Seleccionar]
#include "16F84A.h"
#int_TIMER0
#use delay(clock=4000000)
#define SENSORA PIN_A0
#define SENSORB PIN_A1
#define RAPIDO PIN_B0
#define LENTO PIN_B1

void main(void)
{
  setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);setup_wdt(WDT_18MS);
   
  int velocidad, espacio, tiempo;
   
  espacio=1;
   
  for(;;)
  {
    if(input(SENSORA))
      set_timer0(1); 

    if(input(SENSORB))
      tiempo=get_timer0();

    velocidad= espacio/tiempo;
     
    if (velocidad >= 1)
      OUTPUT_HIGH(RAPIDO);
    else
      OUTPUT_HIGH(LENTO);
   }
}

Algun error?
Porque esto no va xD
Un saludo.
« Última modificación: 22 de Mayo de 2013, 13:34:21 por Wheatley »

Desconectado gab163

  • PIC16
  • ***
  • Mensajes: 111
Re: Código sencillo en 16F84A
« Respuesta #10 en: 28 de Mayo de 2013, 15:08:33 »
Hola, encontre varios errores del código así como lo tienes para saber el tiempo debes ver a cuantos segundos equivalen las cuentas del timer segun tu configuración lee un poco mas sobre los timers, no especificas que pines del puerto A Y b usas como entradas y salidas, para alcanzar a ver la condición de salida hay que dejar un tiempo porque si no lo hace tan rápido que no se vera, si una vez detectado el sensor A es indispensable esperar la accion del sensor B puedes crear un bucle para que no haga ninguna otra acción hasta que no reciba la señal del sensor B.

Código: [Seleccionar]
#include <16F84A.h>
#fuses xt,nowdt
#use delay(clock=4000000)
#define SENSORA PIN_A0
#define SENSORB PIN_A1
#define RAPIDO PIN_B0
#define LENTO PIN_B1

void main(void)
{
 
  int velocidad, espacio, tiempo;
  set_tris_a(255);   //todo el puerto a como entradas
  set_tris_b(0);     //todo el puerto b como salidas
  output_low(RAPIDO);   //inicializa el estado de los leds
  output_low(LENTO);
 
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256); //configuracion del timer
  //setup_wdt(WDT_18MS);
 
  espacio=1;
   
  for(;;)
  {
    if(input(SENSORA)) //si detecta sensor a
      set_timer0(0);           //se inicia timer
      while(!input(SENSORB))     //y espera hasta que llegue el pulso de sensorb
         tiempo=get_timer0();    //se obtiene las cuentas del timer
         velocidad= espacio/tiempo;
      if (velocidad >= 1){
         OUTPUT_HIGH(RAPIDO);
         output_low(LENTO);
         delay_ms(500);}
      else{
         OUTPUT_HIGH(LENTO);
         output_low(RAPIDO);
         delay_ms(500);}
   }
}
revisalo no se si me me haya pasado algún detalle así como esta ya me compila, saludos.

Desconectado Wheatley

  • PIC10
  • *
  • Mensajes: 7
Re: Código sencillo en 16F84A
« Respuesta #11 en: 29 de Mayo de 2013, 20:36:27 »
Hola, encontre varios errores del código así como lo tienes para saber el tiempo debes ver a cuantos segundos equivalen las cuentas del timer segun tu configuración lee un poco mas sobre los timers, no especificas que pines del puerto A Y b usas como entradas y salidas, para alcanzar a ver la condición de salida hay que dejar un tiempo porque si no lo hace tan rápido que no se vera, si una vez detectado el sensor A es indispensable esperar la accion del sensor B puedes crear un bucle para que no haga ninguna otra acción hasta que no reciba la señal del sensor B.

Código: [Seleccionar]
#include <16F84A.h>
#fuses xt,nowdt
#use delay(clock=4000000)
#define SENSORA PIN_A0
#define SENSORB PIN_A1
#define RAPIDO PIN_B0
#define LENTO PIN_B1

void main(void)
{
 
  int velocidad, espacio, tiempo;
  set_tris_a(255);   //todo el puerto a como entradas
  set_tris_b(0);     //todo el puerto b como salidas
  output_low(RAPIDO);   //inicializa el estado de los leds
  output_low(LENTO);
 
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256); //configuracion del timer
  //setup_wdt(WDT_18MS);
 
  espacio=1;
   
  for(;;)
  {
    if(input(SENSORA)) //si detecta sensor a
      set_timer0(0);           //se inicia timer
      while(!input(SENSORB))     //y espera hasta que llegue el pulso de sensorb
         tiempo=get_timer0();    //se obtiene las cuentas del timer
         velocidad= espacio/tiempo;
      if (velocidad >= 1){
         OUTPUT_HIGH(RAPIDO);
         output_low(LENTO);
         delay_ms(500);}
      else{
         OUTPUT_HIGH(LENTO);
         output_low(RAPIDO);
         delay_ms(500);}
   }
}
revisalo no se si me me haya pasado algún detalle así como esta ya me compila, saludos.

Conseguí hacer el código la semana pasada, funcionó perfectamente ;)

Me quedó así:

Código: [Seleccionar]
#include "16f84a.h"                        // pic a utilizar
#use delay (clock=4000000)           // Fosc=4Mhz
#fuses xt,nowdt,noprotect              // fusibles
#byte port_a=5                             // declaramos el puerto a en su localidad
#byte port_b=6                             // declaramos el puerto b en su localidad

#define SENSORA PIN_A0
#define SENSORB PIN_A1
#define VERDE PIN_B0
#define ROJO PIN_B1
#define BLANCO PIN_B2
#int_TIMER0
void main(void)
{
  set_tris_a(0b00000001);              // programamos el puerto a para que RA0 sea entrada
  set_tris_a(0b00000010);              // programamos el puerto a para que RA1 sea entrada               
  set_tris_b(0b00000000);             // programamos el puerto b para q sea salida (ENTERO)
  port_b=0x00;                            // inicialmente todo el puerto b estara apagado
  float tiempo;
 
 while (true)                               // bucle infinito,o que el programa se ejecutara infinitamente
 {
    tiempo=0;
    output_low (VERDE);
    output_low(ROJO);
    output_low (BLANCO);
   
    if (input(SENSORA)==0)
    {
      while (input(SENSORB)==0)
      {
        delay_ms(1);
        tiempo=tiempo+1;
        output_high (BLANCO);
      }
      output_low (BLANCO);
      tiempo=tiempo/1000;
     
      if(tiempo<=5)
      {
        output_high (ROJO);
        delay_ms(4000);
        port_b=0x00;
      }
      else
      {
        output_high(VERDE);
        delay_ms(4000);
        port_b=0x00;
      }
    }
   
   
   
   
 }
}

Desconectado gab163

  • PIC16
  • ***
  • Mensajes: 111
Re: Código sencillo en 16F84A
« Respuesta #12 en: 29 de Mayo de 2013, 23:22:40 »
excelente  ;-)