Autor Tema: problema al mandar cadenas de caracteres por rs232 entre dos pics  (Leído 2884 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado clavo182

  • PIC10
  • *
  • Mensajes: 15
problema al mandar cadenas de caracteres por rs232 entre dos pics
« en: 29 de Noviembre de 2015, 09:57:52 »
hola, tengo un problema al enviar tres cadenas de caracteres por rs232. Bueno lo que estoy tratando de hacer es mandar tres variables int (humedad,temperatura,intensidad de luz) en forma de cadena de caracteres esto por rs232, el motivo es para poder agregar un señalizador a cada cadena, y asi el pic receptor pueda diferenciarlos.
Ahora mi problema es que en la simulacion en proteus por medio de la terminal virtual, las cadenas se andan uniendo, ademas que van apareciendo otros caracteres en las cadenas(les dejo una imagen), la verdad no se si esto esta bien o necesito usar otro metodo para mandar estas cadenas, aunque si mando solo una de cualquiera de las cadenas, me funciona bien. Bueno espero que alguien sea tan amable de poder ayudarme, gracias de antemano.
Les adjunto el codigo , la simulacion (proteus 8.1) y una imagen de la simulacion.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:problema al mandar cadenas de caracteres por rs232 entre dos pics
« Respuesta #1 en: 29 de Noviembre de 2015, 16:07:04 »
Tenes un error de concepto sobre las strings en C

http://www.tutorialspoint.com/cprogramming/c_strings.htm

Observa que un string es un array de caracteres, ademas termina con un caracter nulo ( 0x00 ). Si vos pasas de un entero a un string, supongamos que la temperatura es 49, eso como string ocuparia:

temp[3] = {'4','9','\0'}

Ahora si quisiera unir otro caracter necesitaria mas lugar, Si quisiera poner la T en la posicion 2 queda:

temp[3] = {'4','9','T'}

Lo cual es incorrecto, ya que una string si o si debe terminar con un caracter nulo. Entonces: Deberias tener realmente algo asi:

temp[4] = {'4','9','T','\0'}

Pero eso no son los unicos errores. Tambien aparece algo como esto:

   char iluminacion[3];

Que luego usas asi:

      iluminacion[3]='I';

Es un error, por que tu array tiene 3 lugares, y tenes que recordar que comienza de 0 el indice, 0, 1, 2 , y alli tendrias tus 3, Tal ves con ese 3 estes escribiendo otro valor

Una cosa mas ,, cuando son numeros enteros:

ilum =(int)((((float)read_adc())*100)+100);
temp=(int)((float)read_adc()*2);

No hace falta el float, solo estarias agregando mas tiempo para realizar el calculo sin sentido. Suponiendo que int sea de 16bit

ilum =(read_adc()*100)+100;
temp=read_adc()*2;

Igual me parece raro el calculo de la temperatura, ya que el ADC va desde 0 a 1023, lo cual podrias tener 2046 grados ? O estas pasando solamente el numero?, y si pasas solamente el numero por que complicarse la vida haciendo los calculos aca xD

Desconectado clavo182

  • PIC10
  • *
  • Mensajes: 15
Re:problema al mandar cadenas de caracteres por rs232 entre dos pics
« Respuesta #2 en: 29 de Noviembre de 2015, 21:11:58 »
ahh ok gracias por la ayuda el link me ayudo de mucho jeje... hice algunos cambios en la conversion de int a string y concatenar strings y ahora si me funciona como queria.

      set_adc_channel(0);  //inicializamos canal 0 para dato de humedad
      delay_us(100);

      hum=(int)((((float)read_adc())*0.4)+0.2);//leemos dato de humedad y realizamos operacion     
      sprintf(humedad,"%2u",hum);//convertimos a string el valor entero
      strcpy(hum_tx,"H");
      strcat(hum_tx,humedad);
      puts(hum_tx);
      delay_ms(10);

Desconectado clavo182

  • PIC10
  • *
  • Mensajes: 15
Re:problema al mandar cadenas de caracteres por rs232 entre dos pics
« Respuesta #3 en: 30 de Noviembre de 2015, 01:50:31 »
una duda mas, en la parte de recepcion de los datos...quice usar la funcion gets() para leer toda una cadena de caracteres haciendo uso de la interrupcion int_rda del pic18f4550,  pero no ha sido posible y me sale el siguiente error.
----Error 51 "PIC184550.c" Line 41(16,17): A numeric expression must apper here---

este es el codigo:

char cad_rx[5];
char hum_rx[4];
char temp_rx[4];
char ilum_rx[5]

void RDA_ISR()   //interrupcion por recepcion de datos
{
   cad_rx=gets();///<-------linea 41
   if(cad_rx[0]=='H')
   {
      strcpy(hum_rx,cad_rx);     
   }
   if(cad_rx[0]=='T')
   {
      strcpy(temp_rx,cad_rx);     
   }
   if(cad_rx[0]=='I')
   {
      strcpy(ilum_rx,cad_rx);     
   }
}

hay alguna otra forma de recepcionar los strings y ademas se pueda diferenciar el dato.
« Última modificación: 30 de Noviembre de 2015, 01:53:31 por clavo182 »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:problema al mandar cadenas de caracteres por rs232 entre dos pics
« Respuesta #4 en: 30 de Noviembre de 2015, 06:46:47 »
Tenes que entender que la interrupcion entra cuando recibe un solo caracter y luego tenes que salir. asi que seria algo asi:

Código: C
  1. char buffer[4],i=0;
  2.  
  3. void RDA_ISR() {
  4.   char c;
  5.   buffer[i++] = getc() o get_char, o como sea
  6.   if (i==4) {
  7.        i=0;
  8.        // Y en buffer tenes tu string. y aca preguntas por cual es.
  9.       }
  10.  
  11. }

Desconectado clavo182

  • PIC10
  • *
  • Mensajes: 15
Re:problema al mandar cadenas de caracteres por rs232 entre dos pics
« Respuesta #5 en: 30 de Noviembre de 2015, 09:10:54 »
ohh ok gracias lo voy a probar

Desconectado clavo182

  • PIC10
  • *
  • Mensajes: 15
Re:problema al mandar cadenas de caracteres por rs232 entre dos pics
« Respuesta #6 en: 30 de Noviembre de 2015, 09:46:16 »
no seria mas conveniente preguntar si c=13 que es el retorno de carro, ya que con este termina una cadena y al final ponerle un '\0'. bueno mi idea es esta

#int_RDA
void RDA_ISR()   //interrupcion por recepcion
{
  output_high(PIN_A0);
  cad_rx[j]=getc();
  if (cad_rx[j]==0x0D)
   {
       
      if(cad_rx[0]=='H')
      {
         strcpy(hum_rx,cad_rx);
         hum_rx[j+1]='\0';
         bandera1=1;
      }
      if(cad_rx[0]=='T')
      {
         strcpy(temp_rx,cad_rx);
         temp_rx[j+1]='\0';
         bandera2=1;
      }
      if(cad_rx[0]=='I')
      {
         strcpy(ilum_rx,cad_rx);
         ilum_rx[j+1]='\0';
         bandera3=1;
      }
      disable_interrupts(INT_RDA);
   }
   j++;
}

las banderas y deshabilitar la interrupcion es para que una vez tenido la cadena completa, yo pueda procesarla en main, y terminado de procesarlo yo reactive la interrupcion
while(TRUE)
{
if(bandera1)
{
/*lo proceso
 bandera1=0, j=0  y luego
reactivo la interrupcion
*/
}
if(bandera2)
{
/*lo proceso.....
bandera2=0, j=0 y luego
reactivo la interrupcion*/
}
if(bandera3)
{
/*lo proceso
bandera3=0, j=0 y luego
reactivo la interrupcion*/
}
}
« Última modificación: 30 de Noviembre de 2015, 10:12:16 por clavo182 »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:problema al mandar cadenas de caracteres por rs232 entre dos pics
« Respuesta #7 en: 30 de Noviembre de 2015, 10:27:18 »
Citar
no seria mas conveniente preguntar si c=13 que es el retorno de carro, ya que con este termina una cadena y al final ponerle un '\0'. bueno mi idea es esta

Ahora que veo el manual de CCS, la funcion puts() envia.. El dato + CR + LF , asi que lo ultimo a recibir es exactamente el \n.

Asi que si usas puts() recibirias (siguiendo el ejemplo):

{'4','9','T','\r','\n'}

Si no me equivoco, con que solo cambies el \r por un \0 es suficiente para que C crea que string termina alli

Desconectado clavo182

  • PIC10
  • *
  • Mensajes: 15
Re:problema al mandar cadenas de caracteres por rs232 entre dos pics
« Respuesta #8 en: 30 de Noviembre de 2015, 12:51:09 »
que mal no logra mostrarme lo que quiero en lcd...creo que estoy haciendo un mal uso de la funcion printf, o es algo que falta en los strings, adjunto el codigo con la simulacion
Código: [Seleccionar]
#include <18f4550.h>  //incluimos libreria de pic18f4550
#DEVICE HIGH_INTS=TRUE
#fuses XT,NOWDT,PUT,NOPROTECT,NODEBUG,NOBROWNOUT,NOLVP
# use delay(clock=4000000)//definimos un reloj de 4Mhz
#use rs232(baud=9600, xmit=pin_c6, rcv=pin_c7)

//#define use_portd_lcd TRUE
//#define use_portb_kbd TRUE
#include <lcd1.c>
//#include <kbd.c>
#include <input.c>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>//incluimos libreria para uso de operaciones en memoria


int hum_max=70,hum_min=30,temp_max=25,temp_min=15,ilum_max=600,ilum_min=500;
int humedad, temperatura, iluminacion;
char cad_rx[5];
char hum_rx[4];
char temp_rx[4];
char ilum_rx[5];
char hum[4];
char temp[4];
char ilum[5];
char cad1[3];
char cad2[4];
char teclado;
int8 cont,i=0,j=0;
int8 bandera=0,bandera1=0,bandera2=0,bandera3=0;

/*#int_RB HIGH
void RB_isr()
{
   teclado=kbd_getc();
 
  if(teclado=='#')
   {     
      bandera=1;
      disable_interrupts(INT_RDA);
   }
}*/

#int_RDA
void RDA_ISR()   //interrupcion por recepcion
{
  output_high(PIN_A0);
  cad_rx[j]=getc();
  if (cad_rx[j]=='\n')
   {
       
      if(cad_rx[0]=='H')
      {
         strcpy(hum_rx,cad_rx);
         hum_rx[j+1]='\0';
         bandera1=1;
      }
      if(cad_rx[0]=='T')
      {
         strcpy(temp_rx,cad_rx);
         temp_rx[j+1]='\0';
         bandera2=1;
      }
      if(cad_rx[0]=='I')
      {
         strcpy(ilum_rx,cad_rx);
         ilum_rx[j+1]='\0';
         bandera3=1;
      }
      disable_interrupts(INT_RDA);
   }
   j++;
}

void main ()   //inicio de programa principal
{     
     
   set_tris_a(0b0000000);//configuramos puerto a
   output_low(PIN_A0);
   output_low(PIN_A1);
//   port_b_pullups(TRUE);
   lcd_init();
   delay_ms(50);
//   kbd_init();
   enable_interrupts(INT_RDA);
//   enable_interrupts(INT_RB);
   enable_interrupts(GLOBAL);
   lcd_putc("\f       PROYECTO ");   
   lcd_putc("\n   INVERNADERO  ");
   delay_ms(2000);
   lcd_init();
    while (TRUE)   //entramos en un ciclo infinito
   {
      if(bandera1==1)
      {
         for(i=0;i<strlen(hum)-1;i++)
         {
            hum[i]=hum_rx[i+1];   
         }
         hum[i]='\0';
         humedad=atoi(hum);
         lcd_gotoxy(5,1);  //posicionamos cursor de lcd
         printf(lcd_putc,"H=");//escribimos en lcd
         lcd_gotoxy(7,1);  //posicionamos cursor de lcd
         printf(lcd_putc,"%d",humedad);//escribimos valor de temperatura en lcd
         lcd_gotoxy(10,1); //posicionamos cursor de lcd
         printf(lcd_putc,"%%");//escribimos en lcd
         bandera1=0;
         j=0;
         output_high(PIN_A0);
         enable_interrupts(INT_RDA);
     }
     if(bandera2==1)
     {
         for(i=0;i<strlen(temp)-1;i++)
         {
            temp[i]=temp_rx[i+1];   
         }
         temp[i]='\0';
         temperatura=atoi(temp);
         lcd_gotoxy(1,2);  //posicionamos cursor de lcd
         printf(lcd_putc,"T=");//escribimos en lcd
         lcd_gotoxy(3,2);  //posicionamos cursor de lcd
         printf(lcd_putc,"%d",temperatura);//escribimos valor de temperatura en lcd
         lcd_gotoxy(5,2); //posicionamos cursor de lcd
         printf(lcd_putc,"'C");//escribimos en lcd
         bandera2=0;
         j=0;
         output_low(PIN_A0);
         enable_interrupts(INT_RDA);
     }
     if(bandera3==1)
     {
         for(i=0;i<strlen(ilum);i++)
         {
            ilum[i]=ilum_rx[i+1];   
         }
         ilum[i]='\0';
         iluminacion=atoi(ilum);
         lcd_gotoxy(8,2);  //posicionamos cursor de lcd
         printf(lcd_putc,"I=");//escribimos en lcd
         lcd_gotoxy(10,2);  //posicionamos cursor de lcd
         printf(lcd_putc,"%d",iluminacion);//escribimos valor de temperatura en lcd
         lcd_gotoxy(14,2); //posicionamos cursor de lcd
         printf(lcd_putc,"lux");//escribimos en lcd
         bandera3=0;
         j=0;
         output_low(PIN_A0);
         enable_interrupts(INT_RDA);
     }
         
      /*if(bandera==1)//entramos para usar el teclado
      {         
         cont=0;
       while(cont<2)
       {
            lcd_gotoxy(1,1);  //posicionamos cursor de lcd
            printf(lcd_putc,"New_H_Min=");//escribimos en lcd
            teclado=kbd_getc();
            if(teclado!=0&&teclado!='#'&&teclado!='*')//obligamos que se ingrese numero
            {
            cad1[cont]=teclado;       
            lcd_gotoxy(13+cont,2);//posicionamos cursor de lcd
            printf(lcd_putc,teclado);//escribimos valor de teclado en lcd
            cont++;
            }
      }
      cad1[cont]='\0';//ponemos 0 al final para poder convertirlo a entero
      hum_min=atoi(cad1);  //convertimos a entero
      cont=0;

      while(cont<2)
      {     
         lcd_gotoxy(1,2);  //posicionamos cursor de lcd
         printf(lcd_putc,"New_H_Max=");//escribimos en lcd
         delay_ms(50);
         teclado=kbd_getc();
         if(teclado!=0&&teclado!='#'&&teclado!='*')
         {
            cad1[cont]=teclado;
 
            lcd_gotoxy(13+cont,2);//posicionamos cursor de lcd
            printf(lcd_putc,teclado);//escribimos valor de humedad en lcd
            cont++;

         }
      }
      cad1[cont]='\0';
      hum_max=atoi(cad1);
      cont=0;
      lcd_init();
      while(cont<2)
      {
         lcd_gotoxy(1,1);  //posicionamos cursor de lcd
         printf(lcd_putc,"New_T_Min=");//escribimos en lcd
         delay_ms(50);
         teclado=kbd_getc();
         if(teclado!=0&&teclado!='#'&&teclado!='*')
         {
            cad1[cont]=teclado;         
            lcd_gotoxy(13+cont,2);//posicionamos cursor de lcd
            printf(lcd_putc,teclado);//escribimos valor de humedad en lcd
            cont++;

         }
      }
      cad1[cont]='\0';
      temp_min=atoi(cad1);
      cont=0;

      while(cont<2)
      {     
         lcd_gotoxy(1,2);  //posicionamos cursor de lcd
         printf(lcd_putc,"New_T_Max=");//escribimos en lcd
         delay_ms(50);
         teclado=kbd_getc();
         if(teclado!=0&&teclado!='#'&&teclado!='*')
         {
            cad1[cont]=teclado;
            lcd_gotoxy(13+cont,2);//posicionamos cursor de lcd
            printf(lcd_putc,teclado);//escribimos valor de humedad en lcd
            cont++;

         }
      }
      cad1[cont]='\0';
      temp_max=atoi(cad1);
      cont=0;
      lcd_init();
      while(cont<3)
      {
         lcd_gotoxy(1,1);  //posicionamos cursor de lcd
         printf(lcd_putc,"New_I_Min=");//escribimos en lcd
         delay_ms(50);
         teclado=kbd_getc();
         if(teclado!=0&&teclado!='#'&&teclado!='*')
         {
            cad2[cont]=teclado;
         
            lcd_gotoxy(13+cont,2);//posicionamos cursor de lcd
            printf(lcd_putc,teclado);//escribimos valor de humedad en lcd
            delay_ms(50);
            delay_ms(50);
            cont++;

         }
      }
      cad2[cont]='\0';
      ilum_min=atoi(cad2);
      cont=0;

      while(cont<3)
      {     
         lcd_gotoxy(1,2);  //posicionamos cursor de lcd
         printf(lcd_putc,"New_I_Max=");//escribimos en lcd
         delay_ms(50);
         teclado=kbd_getc();
         if(teclado!=0&&teclado!='#'&&teclado!='*')
         {
            cad2[cont]=teclado;
   
            lcd_gotoxy(13+cont,2);//posicionamos cursor de lcd
            printf(lcd_putc,teclado);//escribimos valor de humedad en lcd
            delay_ms(50);
            cont++;
         }
      }
      cad1[cont]='\0';
      ilum_max=atoi(cad2);
      cont=0;
      lcd_init();
      bandera=0;
      enable_interrupts(INT_RDA);
     }*/
     
   }
   
}
« Última modificación: 30 de Noviembre de 2015, 12:58:51 por clavo182 »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:problema al mandar cadenas de caracteres por rs232 entre dos pics
« Respuesta #9 en: 30 de Noviembre de 2015, 19:22:19 »
Mejor asi no ?

Código: C
  1. #int_RDA
  2. void RDA_ISR()   //interrupcion por recepcion
  3. {
  4.   output_high(PIN_A0);
  5.   cad_rx[j]=getc();
  6.   j++;
  7.   if (cad_rx[j-1]=='\n')
  8.    {
  9.       switch(cad_rx[2])
  10.       {
  11.        case 'H':
  12.          strcpy(hum_rx,cad_rx);
  13.          hum_rx[2]='\0';
  14.          break;
  15.       case 'T':
  16.          strcpy(temp_rx,cad_rx);
  17.          temp_rx[2]='\0';
  18.          break;
  19.       case 'I':
  20.          strcpy(ilum_rx,cad_rx);
  21.          ilum_rx[2]='\0';
  22.          break;
  23.       default:
  24.          break;
  25.       }
  26.       bandera3=1;
  27.       cad_rx[j-1]='\0'     // Elimino la condicion de igualdad para que no entre mas
  28.       j=0;
  29.    }
  30. }