Haz una pregunta
  Foros de Electrónica » Diseño digital » Microcontroladores y sistemas embebidos
Foros Registrarse ¿Olvidaste tu contraseña?

Temas similares

28/03/2014 #1


Duda general programa en CCS PIC16F88
Hola a todos. Estoy desarrollando una aplicación y al compilar tengo uno errores en el programa. Vamos hay un poco de todo. Explicaré el programa para que sepáis qué hace exactamente.

Desde otro PIC master yo enviaré una solicitud para pedir una lectura del ADC. En esa solicitud especificaré la dirección de mi PIC slave y también el canal del que deseo obtener la información. La trama a enviar por puerto serie desde el PIC master hacia mi PIC slave será la siguiente: "$ADQ,P01,CHx," donde [ x ] será un valor del 0 al 5 (referente al canal de lectura).

Una vez reciba la trama por el puerto serie de mi PIC slave primero de todo tendré que comprobar si la dirección recibida coincide con la del PIC slave. La dirección de éste PIC slave es la siguiente: "$ADQ,P01,". Comprobaré si coincide con la recibida y posteriormente miraré qué canal de lectura hay que leer. La cadena de caracteres a obtener de la trama recibida es solamente "CHx" para saber qué canal hay que leer. Para éstas dos cosas defino unos strings para guardar la dirección recibida y el canal recibido.

Una vez sepa el canal realizo la lectura y lo guardo en una variable. Es evidente que para cambiar de un valor Numérico a un String tengo que hacer una conversión. Hay unas funciones como por ejemplo itoa() pero prefiero hacerlo manualmente.

Una vez convierto este valor del ADC a string concateno unos strings para obtener mi dato a devolver por puerto serie. El dato a devolver es el siguiente: "$DAT,P01,CHx,xxxxxxxxxx" donde xxxxxxxxxx es el valor del ADC de 10 bits del PIC 16F88.


Quiero comprobar que todo esté bien definido ya que obtengo errores al compilar y no tengo ni idea... llevo muy poco con CCS. Ya sé que el programa quizás es un poco largo pero si alguien pudiera repasarlo. Cualquier duda respecto al funcionamiento que quiero hacer puedo responder.

Muchas gracias

Código:
#include <16F88.h>
#include <stdio.h>
#include <string.h>

#device adc=10 //INDICO EL NÚMERO DE BITS DEL ADC
#fuses HS, NOWDT, NOLVP, NOBROWNOUT, NOPROTECT, PUT
#use delay(clock=8000000)
#use rs232(baud=9600, xmit=PIN_B5, rcv=PIN_B2) //*CONFIGURO PUERTO SERIE

char DireccionPIC[10]= "$ADQ,P01,"; //Es la direccion del PIC
char DireccionPICrespuesta[10]="$DAT,P01,"

int strcmp(const char *cadena1, const char *cadena2); //Definicion funcion STRCMP creo que es obligatorio

#INT_RDA
void INT_UART() {

//Definición de variables
int ValorADC=0; //Variable para lectura ADC
int i=0; //Variable para ciclos for
int Maskara=0; //Variable para obtencion de bits '0' o '1'
char StringValorADC[12]={0};//Cadena de caracteres para guardar valor ADC en Carcteres
char PreDatoSalida[15]={0};
char DatoEntrada[15]={0}; //String para guardar el dato de entrada por UART
char DatoSalida[24]={0}; //String para guardar lo que envio por UART
char DireccionRecibida[10]={0}; //Variable para guardar direccion entrada
char CanalRecibido[6]={0}; //Variable para guardar canal ADC a leer 


DatoEntrada=fgets();

for(i=0;i<10;i++){  //Con éste for obtengo la direccion recibida por UART
    DireccionRecibida[i]=DatoEntrada[i];
}
    i=0;
    DireccionRecibida[10]='/0'; //Pongo caracter nulo para que sea string

if(strcmp(DireccionRecibida, DireccionPIC)==0){ //Comparo si la direccion recibida coincide con la del PIC

   for(i=0;i<5;i++){
      CanalRecibido[i]=DatoEntrada[i+9]; //Si coincide obtengo el canal de lectura del ADC 
   }
    i=0;
    variable2[5]='/0';   //Pongo caracter nulo para que sea string

   if(strcmp(CanalRecibido,"CH0")==0){ //voy comparando para ver qué canal he obtenido y leo CHX
     set_adc_channel(0); //SELECCIONO CANAL 0 (PIN A0) DEL ADC PARA A LEER.
   }

   else if(strcmp(CanalRecibido,"CH1")==0){
      set_adc_channel(1);
   }
  
   else if(strcmp(CanalRecibido,"CH2")==0){
      set_adc_channel(2);
   }

   else if(strcmp(CanalRecibido,"CH3")==0){
      set_adc_channel(3);
   }
  
   else if(strcmp(CanalRecibido,"CH4")==0){
      set_adc_channel(4);
   }
  
  else if(strcmp(CanalRecibido,"CH6")==0){
      set_adc_channel(5);
   }

delay_us(20); //retardo para leer ADC
ValorADC=read_adc(); //lectura ADC

for(i=0;i<10;i++){ //Con un for recorreré solo 10 posiciones del resultado ValorADC (ADC 10 bits)

    CopiaValorADC=ValorADC; //Realizo una copia del valor numérico del ADC para no perderlo
    Maskara=CopiaValorADC>>i; //Quiero tener el bit "i" a la derecha del todo
    Maskara=Maskara&0x0000000000000001;  //realizo una AND para ver si tengo un [1] o un [0].
    if(Maskara==1){
       StringValorADC[10-i]='1';  //Meto los bits (en forma de caracter) en el String StringValorADC
    }
    else{
       StringValorADC[10-i]='0';
    }
}

StringValorADC[0]=','; //Pongo una ',' al principio del resultado
StringValorADC[11]='/0'; //Por último pongo el caracter nulo (para que sea String)

PreDatoSalida=strcat(DireccionPICrespuesta,CanalRecibido); //Concateno DireccionPICrespuesta y el canal "CHX")

DatoSalida=strcat(PreDatoSalida,StringValorADC);//concateno String anterior y Valor del ADC

puts(DatoSalida); //Envio un solo String con la direccion, canal CHX y el resutado del PIC por UART.

} //ya he enviado por UART: "$ADQ,P01,CHx,xxxxxxxxxx"


void main(){

enable_interrupts(GLOBAL); //HABITILRO TODAS LAS INTERRUPCIONES GLOBALES
enable_interrupts(INT_RDA); //HABILITO LA INTERRUPCIÓN UART
setup_adc_ports(sAN0,sAN1,sAN2,sAN3,sAN4,sAN5); //INDICO EL PIN A0/A1/A2/A3/A4/A5 COMO ENTRADA ANALÓGICA 
setup_adc(ADC_CLOCK_INTERNAL); //CLOCK INTERNO PARA CONVERSIÓN ADC
return(0);
}
---------- Actualizado después de 29 minutos ----------

Bueno donde dice CH6 es en realidad CH5

---------- Actualizado después de 22 minutos ----------

Hay alguna variable que no estaba definida pero ya lo solventé.
28/03/2014 #2

Avatar de juanma2468

Podrias pegar el log de los errores que te tira??.
Vi que declaras muchas variables en la rutina de la interrupcion, luego usas alguna de esas variables en otra parte del programa??, porque estan declaradas como variables locales y no como variables globales. Si solo las usas en esa subrutina entonces esta bien que sean locales.
28/03/2014 #3


Sí, las variables locales solo las utilizo localmente. Hay algunos errores de tipo ";" pero creo que lo tengo bien.


Código PHP:
*** Error 23 "D:\Documents and Settings\Administrador.DESKTOP\Mis documentos\Programa PIC\project1.c" Line 5(8,9): Can not change device type this far into the code
*** Error 48 "D:\Documents and Settings\Administrador.DESKTOP\Mis documentos\Programa PIC\project1.c" Line 5(9,12): Expecting a (
*** 
Error 43 "D:\Documents and Settings\Administrador.DESKTOP\Mis documentos\Programa PIC\project1.c" Line 5(13,15): Expecting a declaration
*** Error 36 "D:\Documents and Settings\Administrador.DESKTOP\Mis documentos\Programa PIC\project1.c" Line 13(5,8): Expecting a ; or ,
*** 
Error 43 "D:\Documents and Settings\Administrador.DESKTOP\Mis documentos\Programa PIC\project1.c" Line 13(11,12): Expecting a declaration
*** Error 46 "D:\Documents and Settings\Administrador.DESKTOP\Mis documentos\Programa PIC\project1.c" Line 13(31,32): Expecting an =
*** 
Error 46 "D:\Documents and Settings\Administrador.DESKTOP\Mis documentos\Programa PIC\project1.c" Line 13(52,53): Expecting an =
*** 
Error 43 "D:\Documents and Settings\Administrador.DESKTOP\Mis documentos\Programa PIC\project1.c" Line 13(53,54): Expecting a declaration
*** Error 49 "D:\Documents and Settings\Administrador.DESKTOP\Mis documentos\Programa PIC\project1.c" Line 31(1,12): Expecting LVALUE such as a variable name  or  * expression
*** Error 45 "D:\Documents and Settings\Administrador.DESKTOP\Mis documentos\Programa PIC\project1.c" Line 37(23,25): Subscript out of range
*** Error 5 "D:\Documents and Settings\Administrador.DESKTOP\Mis documentos\Programa PIC\project1.c" Line 37(27,29): Character constant constructed incorrectly
*** Error 5 "D:\Documents and Settings\Administrador.DESKTOP\Mis documentos\Programa PIC\project1.c" Line 37(30,32): Character constant constructed incorrectly
*** Error 12 "D:\Documents and Settings\Administrador.DESKTOP\Mis documentos\Programa PIC\project1.c" Line 45(5,14): Undefined identifier   variable2
*** Error 5 "D:\Documents and Settings\Administrador.DESKTOP\Mis documentos\Programa PIC\project1.c" Line 45(18,20): Character constant constructed incorrectly
*** Error 5 "D:\Documents and Settings\Administrador.DESKTOP\Mis documentos\Programa PIC\project1.c" Line 45(21,23): Character constant constructed incorrectly
*** Error 51 "D:\Documents and Settings\Administrador.DESKTOP\Mis documentos\Programa PIC\project1.c" Line 51(4,8): A numeric expression must appear here
*** Error 51 "D:\Documents and Settings\Administrador.DESKTOP\Mis documentos\Programa PIC\project1.c" Line 55(4,8): A numeric expression must appear here
*** Error 51 "D:\Documents and Settings\Administrador.DESKTOP\Mis documentos\Programa PIC\project1.c" Line 59(4,8): A numeric expression must appear here
*** Error 51 "D:\Documents and Settings\Administrador.DESKTOP\Mis documentos\Programa PIC\project1.c" Line 63(4,8): A numeric expression must appear here
*** Error 51 "D:\Documents and Settings\Administrador.DESKTOP\Mis documentos\Programa PIC\project1.c" Line 67(3,7): A numeric expression must appear here
*** Error 5 "D:\Documents and Settings\Administrador.DESKTOP\Mis documentos\Programa PIC\project1.c" Line 88(20,22): Character constant constructed incorrectly
*** Error 5 "D:\Documents and Settings\Administrador.DESKTOP\Mis documentos\Programa PIC\project1.c" Line 88(23,25): Character constant constructed incorrectly
*** Error 76 "D:\Documents and Settings\Administrador.DESKTOP\Mis documentos\Programa PIC\project1.c" Line 90(1,14): Expect ;
*** 
Error 49 "D:\Documents and Settings\Administrador.DESKTOP\Mis documentos\Programa PIC\project1.c" Line 92(1,11): Expecting LVALUE such as a variable name  or  * expression
*** Error 51 "D:\Documents and Settings\Administrador.DESKTOP\Mis documentos\Programa PIC\project1.c" Line 99(1,5): A numeric expression must appear here
*** Error 58 "D:\Documents and Settings\Administrador.DESKTOP\Mis documentos\Programa PIC\project1.c" Line 103(26,27): Expecting a close paren
*** Error 127 "D:\Documents and Settings\Administrador.DESKTOP\Mis documentos\Programa PIC\project1.c" Line 105(1,7): Return value not allowed in void function
*** 
Error 79 "D:\Documents and Settings\Administrador.DESKTOP\Mis documentos\Programa PIC\project1.c" Line 110(0,1): Expect }
      
28 Errors,  0 Warnings
28/03/2014 #4

Avatar de ByAxel

Hola.
Copie tal cuál el código y luego de compilar... pufff... es verdad te hace falta muchas correcciones...
Por ejemplo :
- Falta (;) en char DireccionPICrespuesta[10]="$DAT,P01,"
- En main poner return(0); no va!, la función no soporta parámetro de retorno... void main()... es más para PICs no he visto tal cosa dentro main... main es la función más baja o principal... no hay nada más en el fondo.
- Falta cerrar llaves ( } )...

Mejor lee línea por línea ya que la escritura está mal.

Saludos.
28/03/2014 #5

Avatar de TRILO-BYTE

yo tengo una duda en valor array tipo char

¿es valido hacer esto?
char DireccionPICrespuesta[10]="$DAT,P01,";

digo ocupa 3 char y quiere ocuparlo en un char
28/03/2014 #6

Avatar de ByAxel

TRILO-BYTE dijo: Ver Mensaje
yo tengo una duda en valor array tipo char

¿es valido hacer esto?
char DireccionPICrespuesta[10]="$DAT,P01,";

digo ocupa 3 char y quiere ocuparlo en un char
Es un array de 10 char y el valor es una cadena/string de 9 caracteres... el caracter nulo o '\0' se establece automáticamente.

La cadena "$DAT,P01," también puede ir entre llaves o separados cada caracter por comas incluyendo el '\0'.
29/03/2014 #7


Bueno iré por partes he conseguido solucionar bastantes errores de compilación pero me sigue dando uno que la verdad no sé que puedo hacer.

Cuando realizo lo siguiente:

FlagString=strcmp(CanalRecibido,"CH5");
else if(FlagString==0){
set_adc_channel(5);
}



Me da un error del tipo: A numeric expression must appear here

La librería #define <string.h> la he definido en el programa. Antes de ese else if va un if y otros else if (no he puesto el else if solo)

---------- Actualizado después de 16 minutos ----------

Bueno y cuando cambio "CH5" por el array de caracteres CH5 (Ya que he definido CH5[4]="CH5"). También me da un error.
29/03/2014 #8

Avatar de ByAxel

Hola.
#define <string.h> NO , #include <string.h> SI.

El fragmento de código es así? pasa que no puede haber una línea de código sobre ELSE IF... es decir que la línea FlagString=strcmp(CanalRecibido,"CH5"); debe estar arriba o al final de todo el bloque de IFs, no en medio pero si dentro de las llaves.

Código:
// Aquí
IF (...){
   ... // o Aquí
}
ELSE IF(){
   ... // o Aquí
}
// o aquí..
Respecto a FlagString=strcmp(CanalRecibido,"CH5");, necesitas crear un puntero a memoria donde se hubica el string "CH5"... puede ser con:
Código:
FlagString = strcmp(CanalRecibido,(char*)"CH5");
Si ambos string son variables, no hay problema y ojo que cuando manipules los arrays deben de tener el caracter NULL al final de la cadena de lo contrario va atener problemas accediendo a la memoria.

Saludos
29/03/2014 #9


ByAxel dijo: Ver Mensaje
Hola.
#define <string.h> NO , #include <string.h> SI.

El fragmento de código es así? pasa que no puede haber una línea de código sobre ELSE IF... es decir que la línea FlagString=strcmp(CanalRecibido,"CH5"); debe estar arriba o al final de todo el bloque de IFs, no en medio pero si dentro de las llaves.

Código:
// Aquí
IF (...){
   ... // o Aquí
}
ELSE IF(){
   ... // o Aquí
}
// o aquí..
Respecto a FlagString=strcmp(CanalRecibido,"CH5");, necesitas crear un puntero a memoria donde se hubica el string "CH5"... puede ser con:
Código:
FlagString = strcmp(CanalRecibido,(char*)"CH5");
Si ambos string son variables, no hay problema y ojo que cuando manipules los arrays deben de tener el caracter NULL al final de la cadena de lo contrario va atener problemas accediendo a la memoria.

Saludos

Perfecto. Gracias a tu aporte he conseguido solucionar los errores referentes a la función STRCMP. Pero no entiendo el por qué de poner FlagString = strcmp(CanalRecibido,(char*)"CH5"); Es decir la definición de la función es la siguiente int strcmp(const char *cadena1, const char *cadena2). En mi caso poniendo CanalRecibido accedo directamente al contenido del mismo no? Pero en el segundo argumento poniendo solo "CH5" no accedo al mismo no? Necesito acceder a al registro de memoria donde está guardado el array de caracteres "CH5" cierto?

La comparación de cadenas las he puesto de ésta forma al final. No sé como lo verás. El compilador me da Warnings pero no errores respecto a ésto:

if((FlagString=strcmp(CanalRecibido,(char*)"CH0")) ==0){ //voy comparando para ver qué canal he obtenido y leo CHX

set_adc_channel(0); //SELECCIONO CANAL 0 (PIN A0) DEL ADC PARA A LEER.
}

else if((FlagString=strcmp(CanalRecibido,(char*)"CH1")) ==0){

set_adc_channel(1);
}


Respecto a la definición de qué canales quiero analógicos y cuales no sigo teniendo un problema.
Yo he definido: setup_adc_ports(sAN1,sAN2,sAN3,sAN4,sAN5); //INDICO EL PIN A0/A1/A2/A3/A4/A5 COMO ENTRADA ANALÓGICA

El compilador me da un problema, mirando en el fichero 16F88.h indica lo siguiente:

// Constants used in SETUP_ADC_PORTS() are:
#define sAN0 1 //| A0
#define sAN1 2 //| A1
#define sAN2 4 //| A2
#define sAN3 8 //| A3
#define sAN4 16 //| A4
#define sAN5 32 //| B6
#define sAN6 64 //| B7
#define NO_ANALOGS 0 // None
#define ALL_ANALOG 127 // A0 A1 A2 A3 A4 B6 B7

Así que no se qué estoy haciendo mal.
29/03/2014 #10

Avatar de ByAxel

Wever20 dijo: Ver Mensaje
En mi caso poniendo CanalRecibido accedo directamente al contenido del mismo no?
Si, es una variable.
Wever20 dijo: Ver Mensaje
Pero en el segundo argumento poniendo solo "CH5" no accedo al mismo no? Necesito acceder a al registro de memoria donde está guardado el array de caracteres "CH5" cierto?
Es una constante... el aviso o error pide un puntero a la constante o a la dirección en memoria donde se encuentra el string.
Wever20 dijo: Ver Mensaje
Respecto a la definición de qué canales quiero analógicos y cuales no sigo teniendo un problema.
Yo he definido: setup_adc_ports(sAN1,sAN2,sAN3,sAN4,sAN5); //INDICO EL PIN A0/A1/A2/A3/A4/A5 COMO ENTRADA ANALÓGICA

El compilador me da un problema, mirando en el fichero 16F88.h indica lo siguiente:

// Constants used in SETUP_ADC_PORTS() are:
#define sAN0 1 //| A0
#define sAN1 2 //| A1
#define sAN2 4 //| A2
#define sAN3 8 //| A3
#define sAN4 16 //| A4
#define sAN5 32 //| B6
#define sAN6 64 //| B7
#define NO_ANALOGS 0 // None
#define ALL_ANALOG 127 // A0 A1 A2 A3 A4 B6 B7

Así que no se qué estoy haciendo mal.
En una función cada parámetro de entrada se separa por comas, sucede que SETUP_ADC_PORTS() solo acepta un parámetro de entrada... la forma es usando un OR de bits.
Código:
setup_adc_ports(sAN1 | sAN2 | sAN3 | sAN4 | sAN5);
Es decir, que combinando sAN1 | sAN2 | ... van a dar solo un valor que va a ser escrito en el registro respectivo que configura el ADC del PIC.

Saludos.
29/03/2014 #11


Otra cosa más solucionada ) Gracias ByAxel. Si me permites te consultaré esta pequeña duda también ya que no sé si estoy procediendo correctamente: Yo quiero pasar el numero que obtengo del conversor ADC a caracteres. Yo realizo una rotación a la derecha de los bits del resultado del ADC para ir quedandome con esos bits mediante una mascara. Claro yo no sé si cuando realizo la rotación en vez de rotar los bits como a mi me interesa estoy multiplicando el valor (creo que rotar a la derecha es multiplicar) Entonces yo realizo lo siguiente (que no sé si estoy procediendo correctamente):

for(i=0;i<10;i++){ //Con un for recorreré solo 10 posiciones del resultado ValorADC (ADC 10 bits)

CopiaValorADC=ValorADC; //Realizo una copia del valor numérico del ADC para no perderlo
Maskara=CopiaValorADC>>i; //Quiero tener el bit "i" a la derecha del todo
Maskara=Maskara&0x0000000000000001; //realizo una AND para ver si tengo un [1] o un [0].
if(Maskara==1){

StringValorADC[10-i]='1'; //Meto los bits (en forma de caracter) en el String StringValorADC
}
else{
StringValorADC[10-i]='0';
}
}



// la mascara tiene 16 bits porque el valor del ADC
// está metido en un INT (aunque solo me interesan los
//10 bits menores de ese INT
30/03/2014 #12


Rotar bits a la derecha es dividir. Lo dije mal.
30/03/2014 #13

Avatar de ByAxel

Hola.
Creo entender... es un conversor de valor numérico a caracteres ( string ) pero representado como binario??.

Si utilizas Proteus te puedes valer de su depurador para ver por pasos la ejecución de tu programa... solo necesitas el archivo *.cof que se carga igual que el *.HEX y pausar la simulación... aparecen ventanas como muestra en la imagen. Código y lista de variables...

Por lo pronto, veo que el código no cumple exactamente con lo que creo que buscas.

Si es lo que creo tambien puedes usar las instrucciones de bits... por ejemplo:
Código:
for(i=0 ; i<10 ; i++){
         if(bit_test(ValorADC, i))
            StringValorADC[i] = '1';
         else
            StringValorADC[i] = '0';
      }
o esto que lo hace al revéz.
Código:
for(i=9 ; i>-1; i--){
         StringValorADC[i] = '0' + ((ValorADC >> i) & 1);
      }
Ver printf() , fprintf() , itoa()

Saludos.
Imágenes Adjuntas
Tipo de Archivo: jpg debugProteus.jpg (72,5 KB (Kilobytes), 4 visitas)
30/03/2014 #14


Muchas gracias. Me va a servir de gran ayuda esa función para leer bits. Pero ahora que pienso... lo que quiero enviar por el puerto serie no es el número de bits de la conversión sino el valor numérico convertido a caracteres.

Es decir yo al final del programa realizo ésta serie de funciones que me permiten ir contactenando lo que yo quiero para enviarlo en un solo string por el puerto serie. (He modificado el código desde que lo mostré por primera vez ya que al principio no compilaba).

Código:
strcat(DatoSalida,DireccionPICrespuesta); //Concateno DireccionPICrespuesta y el canal "CHX")
strcat(DatoSalida,CanalRecibido);
strcat(DatoSalida,StringValorADC);//concateno String anterior y Valor del ADC
puts(DatoSalida); //Envio un solo String con la direccion, canal CHX y el resutado del PIC por UART.
Sé que con la función itoa() puedo realizar directamente la conversión de valor numérico a String pero me gustaría aprender la forma manual. Entonces para que la anterior contactenación que he mostrado sea válida necesito pasar ValorADC a String... eso como podría realizarlo? (el ADC es de 10 bits)
30/03/2014 #15


He leido sobre sprintf. Con ésta función es posible escribir en el puerto serie o solo sirve para conversión?

Realizando ésto creo que podría enviar el dato deseado por el puerto serie: sprintf(StringAlmacen, "Quiero enviar esto:"%d", ValorADC) así enviaría un solo string por el puerto serie. Luego si ésta función solo es para conversión utilizaria luego puts(StringAlmacen) para enviar el string por puerto serie. ¿Es correcto?
Respuesta
¿Tienes una mejor respuesta a este tema? ¿Quieres hacerle una pregunta a nuestra comunidad y sus expertos? Registrate

Foros de Electrónica » Diseño digital » Microcontroladores y sistemas embebidos

Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO ©2011, Crawlability, Inc.