|
|
View previous topic :: View next topic |
Author |
Message |
morind79
Joined: 11 Apr 2008 Posts: 2
|
Help on RS232 and string |
Posted: Sun May 02, 2010 10:55 am |
|
|
Hi all,
I am sorry, I did some C coding a long time ago, and I need to create a program but it does not work.
Here is what I want to do : the Pic receive data from the serial port, and it should get some value from it.
Here is the data received :
Quote: |
TDETAT 000000 B
ADCO 050622013932 8
OPTARIF HC.. <
ISOUSC 45 ?
HCHC 000000000 F
HCHP 000000001 T
PTEC HP..
IINST 000 W
IMAX 000 ?
PAPP 00000 !
HHPHC A ,
|
I want to get the HCHC and HCHP value 000000000 and 000000001 respectively.
Here is my code:
Code: |
char etiquettes[12][16] = {"ADCO", "OPTARIF", "ISOUSC", "HCHP", "HCHC", "PTEC", "IINST", "IMAX", "PAPP", "HHPHC", "MOTDETAT", "ADPS"} ;
char valeurs[12][18];
char checksum[255];
char ligne[30];
int res;
/*------------------------------------------------------------------------------*/
/* Test checksum d'un message (Return 1 si checkum ok) */
/*------------------------------------------------------------------------------*/
int checksum_ok(char *etiquette, char *valeur, char checksum)
{
unsigned char sum=32 ; // Somme des codes ASCII du message + un espace
int i ;
for (i=0; i<strlen(etiquette); i++) sum=sum+etiquette[i];
for (i=0; i<strlen(valeur); i++) sum=sum+valeur[i];
sum=(sum&63)+32;
if (sum==checksum) return 1; // Return 1 si checkum ok.
//syslog(LOG_INFO, "Checksum lu:%02x calculé:%02x", checksum, sum) ;
return 0;
}
char *readSerial(char *key)
{
char sep[3], *ptr;
char car_prec;
char ch;
int id, i=0;
// Space is the separator
strcpy(sep," ");
// Read data (0d 03 02 0a => end transmission and start of a new one)
do
{
car_prec=ch;
ch=getc();
}
while (!(ch==0x02 && car_prec==0x03)); // Wait for the end and begining of transmission
do
{
ch=getc();
}
while (ch!=0x03); // Wait for the end of transmission.
for (id=0; id<12; id++)
{
// Read the complete line
gets(ligne);
// Split ligne in 3, separator is space
ptr = strtok(ligne, sep);
while (ptr!=0)
{
// 3 fields to read
if (i<3)
{
if (i==0) strcpy(etiquettes[id], ptr);
if (i==1) strcpy(valeurs[id], ptr);
if (i==2) strcpy(checksum, ptr);
i++;
}
ptr = strtok(0, sep);
}
// Test if the checksum is correct
if (!checksum_ok(etiquettes[id], valeurs[id], checksum[0]))
{
// Test if the value is the one we are interested of
if (etiquettes[id]==key)
{
return(valeurs[id]);
}
}
}
}
|
I am prety sure the code is not correct (pointer...)
If you have some advices :-)
Thanks
Denis |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Sun May 02, 2010 4:13 pm |
|
|
A few comments:
1) Code: | (etiquettes[id]==key) | This is not the right method for comparing strings. Use strcmp instead.
2) If you don't find a match the function is exited without a return value.
3) You are reading a fixed number of 12 lines. I only count 11, or is the line with code 0x03 also terminated by a newline character? Better would be to change the code and not to assume a fixed number of lines but to read until a 0x03 is found. This way you can also reduce memory consumption by not declaring all arrays as 12 but only use a single array for each type.
4) Code: | do
{
car_prec=ch;
ch=getc();
}
while (!(ch==0x02 && car_prec==0x03)); // Wait for the end and begining of transmission
do
{
ch=getc();
}
while (ch!=0x03); // Wait for the end of transmission.
| you are waiting for a new message to start, but then you skip another whole message. Why? |
|
|
morind79
Joined: 11 Apr 2008 Posts: 2
|
|
Posted: Mon May 03, 2010 1:26 am |
|
|
Hi,
Thank you for your answer. I rewrite this part of code completely here is the new code :
Code: |
// Here is the description of a transmission :
//
// 0x02
// LF (0x0A) Label (4 to 8 characters) SP (0x20) Data (1 to 12 charaters) SP (0x20) CRC (Character control) CR (0x0D)
// ...
// 0x03
char *readSerial(char *key)
{
char label[10];
char data[14];
char crc;
int il, id;
char ch;
int field=0;
// Empty strings
label[0]='\0';
data[0]='\0';
crc='\0';
// Loop waiting for the beginning of transmission (0x02)
do
{
ch=getc();
}
while (ch!=0x02);
// Read until end of transmission (0x03)
do
{
ch=getc();
// End of field line 0x0D
if (ch==0x0D)
{
field=0;
if (!checksum_ok(label, data, crc))
{
// Test if this is the required key
if (strcmp(label, key)==0)
{
return(data);
}
}
}
// Get field 1 (Label)
if ((field==1) && (ch!=0x20))
{
label[il]=ch;
il++;
}
// Get field 2 (Data)
if ((field==2) && (ch!=0x20))
{
data[id]=ch;
id++;
}
// Get field 3 (CRC)
if ((field==3) && (ch!=0x20))
{
crc=ch;
label[il]='\0';
data[id]='\0';
}
// First field after 0x0A
if (ch==0x0A)
{
field=1;
il=0;
id=0;
}
// Each 0x20 is a separator for a new field
if(ch==0x20) field++;
}while (ch!=0x03);
return('\0');
}
|
I think this will be better handled like this. I do not use gets anymore.
Hope it is the right way.
Br,
Denis |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Mon May 03, 2010 1:55 pm |
|
|
Be careful, the first iteration of the loop has the variables 'field', 'il' and 'id' not initialised. This can lead to data loss and/or memory corruption by writing out of array bounds. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|