[C] Traitement d'une trame GPS

Traitement d'une trame GPS [C] - C - Programmation

Marsh Posté le 16-03-2011 à 22:36:22    

Bonsoir,
 
Je souhaite récupérer puis traiter les données transmises par un petit module GPS relié à une antenne, via liaison série. Les données sont sous forme d'une chaîne de caractères contenant différents codes et symboles liés au protocole GPS, et bien sûr les données que je souhaite, à savoir l'heure, la latitude et la longitude; pour l'instant en tout cas.
 
J'ai plusieurs pour la traiter. D'abord, il faut récupérer les portions précises de la chaîne de caractère contenant la trame complète, correspondant aux données voulues, puis les scinder ensuite chacune afin de traiter les données correctement. Par exemple, récupérer les 2 caractères correspondant à l'heure et les convertir en une seule variable de type int, de même pour les minutes et secondes. (la chaîne 123454 doit conduire à 3 variables entières valant 12, 34 et 54, dans le cas de l'heure)
On pourra ensuite ranger ces trois variables dans une structure définissant l'heure "complète", de même pour latitude et longitude.
 
C'est sans doute pas compliqué, mais je n'ai pas trouvé jusque là et si quelqu'un pouvait m'aider ou me donner d'autres idées, je lui en serais reconnaissant!
Merci d'avance.

Reply

Marsh Posté le 16-03-2011 à 22:36:22   

Reply

Marsh Posté le 17-03-2011 à 15:45:59    

Up, personne ?

Reply

Marsh Posté le 17-03-2011 à 15:56:43    

Sur quelle partie bloques-tu ? Manipulation des chaînes, conversions, autres ?

Reply

Marsh Posté le 17-03-2011 à 16:03:09    

Sur l'extraction de chacune de mes sous-chaînes correspondant aux données voulues, et de leur décomposition ensuite en "morceaux" de chaîne à convertir en int.

Reply

Marsh Posté le 17-03-2011 à 16:13:53    

Pour l'extraction d'une sous-chaîne, le plus simple c'est snprintf je pense.

 

Par exemple :

Code :
  1. char * tesDonnesGPS = <recuperation des donnees>;
  2. int length = <longueur de la chaine a recuperer>;
  3. int position = <position de depart>;
  4.  
  5. char * sousChaine = malloc((length+1) * sizeof(char));
  6.  
  7. snprintf(sousChaine, length+1, "%s", tesDonneesGPS + position);
  8.  
  9. [... reste du code ...]
  10.  
  11. free(sousChaine);
 

Pour la conversion en int, regarde la fonction strtol, ça fait exactement ce que tu veux.


Message édité par Elmoricq le 17-03-2011 à 16:15:06
Reply

Marsh Posté le 17-03-2011 à 18:15:14    

Je comprends pas le dernier argument de snprintf. Je suis bien en C, pas en C++...

Reply

Marsh Posté le 17-03-2011 à 18:40:51    

C'est bien du C. C'est une opération sur pointeur, l'adresse d'un char* débutant au premier caractère, et sizeof(char) valant toujours 1, si tu fais (adresse + n) tu pointes sur le n-ième caractère de la chaîne.


Message édité par Elmoricq le 17-03-2011 à 18:41:15
Reply

Marsh Posté le 17-03-2011 à 19:10:08    

J'ai essayé de faire un exemple, en créant moi-même un chaîne de caractères comme si elle venait du GPS, et je n'obtiens rien à l'écran..
Voilà mon code:

 

#include <stdlib.h>
#include <stdio.h>

 


void process_gps_buffer_heure(unsigned char *buffer);

 

int main(void)
{  
    unsigned char buffer[]={5,4,8,5,7,5,0,6,3,2,1,5,5,8,4,8};
   
    process_gps_buffer_heure(buffer);
   

 

   return 0;
}

 

void process_gps_buffer_heure(unsigned char *buffer)
{
 int length=6;
 int position=6;
 
 char * heure= malloc((length+1) * sizeof(char));
 snprintf(heure, length+1, "%s", buffer+position);
 
 printf("%s", heure);

 

}


Message édité par Titsushi le 17-03-2011 à 19:10:22
Reply

Marsh Posté le 17-03-2011 à 20:34:19    

Comme tu parlais de conversion en int, je pensais que tu recevais des chaînes de caractères, du genre :
 

Code :
  1. char * buffer = "5485750632155848";  // enfin pas '=' mais l'idée est là


 
Equivalent à :

Code :
  1. char buffer[] = { '5', '4', '8', '5', '7', '5', '0', '6', '3', '2', '1', '5', '5', '8', '4', '8' };


 
Ou encore :

Code :
  1. unsigned char buffer[] = {53, 52, 56, 53, 55, 53, 48, 54, 51, 50, 49, 53, 53, 56, 52, 56 };


 
Et si tu copies tel quel ce dernier exemple dans ton code, tu obtiens ceci :

063215


 
Dans ton exemple à toi, tu n'obtiens "rien"... mais en fait, si. Tu obtiens des caractères spéciaux qui n'ont pas de représentation graphique, raison pour laquelle tu ne vois rien (cf.  http://asciitable.com/ pour comprendre).
 
Du coup, il faut que tu aies une idée plus claire, ou bien que tu exposes ici plus clairement, sous quel format exactement tu reçois tes données GPS. :)

Reply

Marsh Posté le 17-03-2011 à 21:14:21    

La trame GPS est sous forme d'une suite de caractères reçus via liaison série RS232 par un micro contrôleur, et que je range un à un dans une chaîne de caractères, que j'appelle buffer ici.
Quelle est la différence entre ma déclaration de buffer, qui "simule" ma trame GPS, et celle que tu donnes ds ton message?? Je ne vois pas..

Reply

Marsh Posté le 17-03-2011 à 21:14:21   

Reply

Marsh Posté le 17-03-2011 à 21:50:23    

Fondamentalement, il n'y en a pas. Un caractère dispose d'un identifiant auquel correspond, selon la table d'encodage utilisée, une représentation graphique.
Raison pour laquelle je ne suis pas revenu sur ton code, mais sur le contenu de ta variable buffer.

 

En ASCII :
5 => est un caractère de contrôle sans représentation graphique
53 => est un caractère auquel correspond la représentation graphique '5'

 

De plus, un "char" en C contient simplement une valeur numérique encodée sur 1 byte (= 8 bits sur nos ordinateurs modernes). Donc allant de -128 à 127 (0 à +255 en unsigned).
En C, les "chaînes de caractères" n'existent pas : ce sont simplement des suites de nombres trouvant le plus souvent leur correspondance dans la table ASCII, suivie par un 0 terminal.

 

Par exemple :

Code :
  1. const char * foo = "foobar";
 

Est équivalent à :

Code :
  1. const char foo[] = {'f', 'o', 'o', 'b', 'a', 'r', '\0'};
 

Et tout aussi équivalent à :

Code :
  1. const char foo[] = {102, 111, 111, 98, 97, 114, 0};
 

Et donc, pour en revenir à tes trames GPS : il te faut analyser si les nombres que tu reçois correspondent des caractères, auquel cas il faut les traiter comme des "chaînes" et les convertir (par exemple : tu reçois 52 puis 50, tu les traduis ce qui te donne '4' puis '2' puis, après conversion, le nombre 42), soit ce sont directement des nombres exploitables tels quels (par exemple, tu reçois directement 42, qui vaut tout bêtement 42, et non le caractère '*').


Message édité par Elmoricq le 17-03-2011 à 21:55:00
Reply

Marsh Posté le 17-03-2011 à 22:02:02    

Oui oui c'est bien le 2nd cas que tu évoques concernant la trame..
La chaîne de caractères reçue contient directement les données exploitables. Dans le cas de l'heure par exemple, s'il est 15h30 et 19 secondes, la chaîne de caractères débutera ainsi: "$GPGGA153019", et c'est là que je veux extraire "153019", puis convertir-je sais pas si c'est le bon terme- en trois variables différentes, valant 15, 30 et 19...

Reply

Marsh Posté le 17-03-2011 à 22:10:24    

Si tu reçois réellement "$GPGGA153019" (et donc la suite numérique : 36, 71, 80, 71, 71, 65, 49, 53, 51, 48, 49, 57), alors mon bout de code au tout début fonctionne. :)
 
Par exemple, pour récupérer l'heure :

Code :
  1. const char * tesDonneesGPS = "$GPGGA153019";
  2. int hourLen = 2;
  3. int hourPosition = 6;
  4.  
  5. char * hourStr = malloc((hourLen+1) * sizeof(char));
  6.  
  7. snprintf(hourStr, hourLen+1, "%s", tesDonneesGPS + hourPosition);
  8.  
  9. long hour = strtol(hourStr, NULL, 10);
  10.  
  11. printf("Hour (string): %s, Hour (int): %ld\n", hourStr, hour);
  12.  
  13. free(hourStr);


 
Ce qui donne bien :

Hour (string): 15, Hour (int): 15

Reply

Marsh Posté le 17-03-2011 à 22:23:00    

Un immense merci ! Ça marche parfaitement.
Je vais l'adapter exactement de la même façon pour récupérer la longitude et la latitude..

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed