IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C++ Discussion :

Probléme de manipulation de trame


Sujet :

C++

  1. #1
    Membre confirmé Avatar de vtk37
    Inscrit en
    Avril 2009
    Messages
    159
    Détails du profil
    Informations personnelles :
    Âge : 36

    Informations forums :
    Inscription : Avril 2009
    Messages : 159
    Par défaut Probléme de manipulation de trame
    Bonjour à tous,

    je bosse actuellement sur un petit projet de réception de trame hexa par liaison serie.
    j'envoie donc une trame du type "03 1E 17" sans les espace et j'ai une réponse du style: "03 00 00 3A 17 1E 41". 03 veut dire que c'est une lecture de variable
    00 00 3A 17 c'est l'adresse et 1E 41 c'est la donnée à récupérer en l'occurrence une température dans mon programme.

    mon programme principale:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    void main (void)
    {
    	char *chaineRecue;
        chaineRecue=new char[200];   
     
    	char chaineEnvoie[50];
    	char Presence[2];
    	int TimeoutRead = 100; // timeout en ms
    	COMMTIMEOUTS tTimeout;
    	int Select,Envoyer,CheckInit,Etat;
    	char Temp[5];
    	int id,i;
     
     
     
    	/***Ouverture du port de communication***/
    	hSerie=CreateFile(TEXT("COM1"),						//Nom du port
    					  GENERIC_READ|GENERIC_WRITE,	//permet l'ecriture et la lecture sur le port
    					  0,							//Mode de partage
    					  NULL,							//Option de sécurité par défaut
    					  OPEN_EXISTING,				
    					  0,
    					  NULL);
     
    	std::cout<<"Connection en cours...\n";
    	CheckInit=init_serie(); // initialise le port serie
     
     
    	/***configurer le timeout***/
    	tTimeout.ReadIntervalTimeout = MAXWORD;
    	tTimeout.ReadTotalTimeoutMultiplier = 0;
    	tTimeout.ReadTotalTimeoutConstant = TimeoutRead; // pas de time out = 0
    	tTimeout.WriteTotalTimeoutMultiplier = 0;
    	tTimeout.WriteTotalTimeoutConstant = 0;
    	SetCommTimeouts(hSerie,&tTimeout);
     
    	/*verifier la présence de la carte*/
    	Presence[0]=0xAAu;
    	Presence[1]='\0';
    	Envoyer=SendTrame(Presence);
    	Etat=ReceiveTrame(chaineRecue);
     
    	if(chaineRecue[0]==Presence[0])
    		std::cout<<"\nCarte presente\n";
    	else
    		std::cout<<"\nCarte absente\n";
     
     
    	system("pause");
    	/*********************************/
     
     
    		do
    		{
    			system("cls");
    			std::cout<<"\nVariable a observer: \n\t-[1] Alarme voyant \n\t-[2] Temperature air ";
    			std::cout<<"\nSaisir un chiffre puis appuyer sur entree ";
    			std::cin>>Select;
     
    			switch(Select)
    			{
    				case 1:
    					chaineEnvoie[0]=0x03; //lecture d'une variable prédéfinie
    					chaineEnvoie[1]=0x02;
    					chaineEnvoie[2]=0x01;
    					chaineEnvoie[3]='\0';
    					break;
    				case 2:
    					chaineEnvoie[0]=0x03;
    					chaineEnvoie[1]=0x1E;
    					chaineEnvoie[2]=0x02;
    					chaineEnvoie[3]='\0';
    					break;
    				default:
    					std::cout<<"\nErreur de saisie";					
    			}
     
    			Envoyer=SendTrame(chaineEnvoie);
     
    			if(Envoyer==1)
    			{
    				printf("\nReception: \n");
    				Etat=ReceiveTrame(chaineRecue);
     
    			}
    			switch(Select)
    			{
    				case 1:
    					if(chaineRecue[5]==0x00)
    						std::cout<<"\nAlarme eteinte";
    					break;
    				case 2:
     
    					//sprintf(Temp,"%s%s",(unsigned char)chaineRecue[5],(unsigned char)chaineRecue[6]);
    					printf("Temp (hex): %02X%02X --- %X",(unsigned char)chaineRecue[5],(unsigned char)chaineRecue[6],Temp);
    					printf("\nTemperature air= %d%cC",&Temp,167);
    					break;
    				default:
    					std::cout<<"\nErreur de saisie";					
    			}
     
    			std::cout<<"\nAppuyer sur une touche pour continuer ou sur 'Echap' pour quitter\n";
    		}
    		while(_getch()!=27);
     
    	delete[] chaineRecue;
    	CloseHandle(hSerie); // ferme le port
     
    }
    la fonction de reception:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    int ReceiveTrame(char *ChaineRecue)
    {
     
    	BOOL bResult;	
    	unsigned long nBytesRead(0);
    	char *inBuffer;
    	int a,i;
    	int id;
     
     
    	inBuffer  = new char[200]; // réservation mémoire pour le buffer de récéption
    	sprintf(inBuffer,"%s","");
     
    	bResult=ReadFile(hSerie,inBuffer,199,&nBytesRead,NULL);
     
    	if(nBytesRead>0)
    	{
    		for(i=0;i<=nBytesRead-1;i++)
    			printf(" %02X",(unsigned char)inBuffer[i]); //permet de visualiser la chaine Reçue
    	}
    	printf("\nNombre d' octet re%cu:%ld \n",135,nBytesRead);
     
    	if (nBytesRead==0)
    	{
    		printf("Pas de donnee recue\n") ;
    	}
     
    	sprintf(ChaineRecue,"%s",inBuffer); // Retourne la chaine reçue
    	if(nBytesRead>0)
    	{
    		for(i=0;i<=nBytesRead-1;i++)
    			printf(" %02X",(unsigned char)ChaineRecue[i]); //permet de visualiser la chaine Reçue 2
    	}
    	delete[] inBuffer;// Libération de la mémoire
     
    	return(0);
     
     
    }
    donc passons au problème

    dans la fonction réception je fais afficher une première fois la trame reçu et sa correspond tout à fait à ce que je reçoit. Cette trame ce trouvant dans le buffer je la met dans ChaineRecue et la quand je fais afficher de nouveau la trame il y a que le début qui correspond "03 00" la suite c'est totalement aléatoire.

    Dans un second temps je souhaiterai récupérer l'information se trouvant dans les 2 derniers octet et les afficher en decimal mais là je bloque total
    j'ai essayer avec sscanf, sprintf.... la variable Temp est toujours de la forme 17FE38.

    A+

  2. #2
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Bonjour,
    Tu cherches à utiliser des données 'brutes' comme des chaînes de caractères. Donc, les 0 sont considérés comme des fins de chaînes... La ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sprintf(ChaineRecue,"%s",inBuffer); // Retourne la chaine reçue
    ne recopie dans ChaineRecue[0]= 0x03 et ChaineRecue[1] = 0x00, et ça s'arrête car 0 est la fin de chaîne.
    Je pense que tu devrais :
    1/ soit considérer uniquement les données comme des octets sans rapport avec des caractères,
    2/ soit convertir la valeur des octets 0x01 en chaînes de caractère "0x01".
    Mais pas mélanger les deux.

  3. #3
    Membre confirmé Avatar de vtk37
    Inscrit en
    Avril 2009
    Messages
    159
    Détails du profil
    Informations personnelles :
    Âge : 36

    Informations forums :
    Inscription : Avril 2009
    Messages : 159
    Par défaut
    ok
    donc les perte de donnée se passe bien à ce niveau la

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sprintf(ChaineRecue,"%s",inBuffer);
    mais si je convertie la valeur des octets 0x01 en chaînes de caractère "0x01" est ce que je pourrai toujours obtenir une valeur décimale a partir des caractères...

    et pour la premiére solution je vois pas comment faire ... il existe une autre fonction qui permet de ne pas se préoccuper du caractère de fin de chaine?

  4. #4
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par vtk37 Voir le message
    mais si je convertie la valeur des octets 0x01 en chaînes de caractère "0x01" est ce que je pourrai toujours obtenir une valeur décimale a partir des caractères...
    La question à se poser est plutôt que fais-tu des données ? Ce n'est peut être pas pertinent de faire des aller retour valeur décimale/chaîne de caractère. Je ne connais pas ton problème, seul toi peut répondre
    Citation Envoyé par vtk37 Voir le message
    et pour la premiére solution je vois pas comment faire ... il existe une autre fonction qui permet de ne pas se préoccuper du caractère de fin de chaine?
    L'idéal serait d'utiliser un std::vector comme buffer de tes données que tu peux ensuite trimballer dans tes différents traitements. Ou selon le même principe utiliser un pointeur intelligent pour partager sereinement ton buffer.

  5. #5
    Membre confirmé Avatar de vtk37
    Inscrit en
    Avril 2009
    Messages
    159
    Détails du profil
    Informations personnelles :
    Âge : 36

    Informations forums :
    Inscription : Avril 2009
    Messages : 159
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    La question à se poser est plutôt que fais-tu des données ? Ce n'est peut être pas pertinent de faire des aller retour valeur décimale/chaîne de caractère. Je ne connais pas ton problème, seul toi peut répondre
    et bien je reçoit donc une trame donc les 2 dernier octet corresponde à une valeur de température en héxa

    par exemple si je reçoit 03 00 00 22 EE 01 4B

    je voudrai pouvoir mettre 01 4B dans Temp et convertir cette variable en décimale afin d'obtenir 331

  6. #6
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    J'écrirais probablement quelque chose comme ça en repartant de ton code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    int ReceiveTrame(std::vector<unsigned char> &buf_reception)
    {
       const  size_t taille_buffer_reception(200);
    	unsigned long nBytesRead(0);
       std::vector<unsigned char> buffer;
     
       buf_reception.resize(0);
       buffer.resize(taille_buffer_reception);
    	BOOL bResult = ReadFile(hSerie,&buffer[0],taille_buffer_reception-1,&nBytesRead,NULL);
     
    	if((bResult)&&(nBytesRead>0))
    	{
          buffer.resize(nBytesRead);
          buf_reception.resize(nBytesRead);
          // recopie des donnees :
          std::copy(buffer.begin(),buffer.end(),buf_reception.begin());
          // affichage des donnees recues :
          std::copy(
             buf_reception.begin(),
             buf_reception.end(),
             std::ostream_iterator<unsigned int>(std::cout<<std::hex," ")
          );
          std::cout<<std::endl;
          std::cout<<"Nombre d'octets reçus : "<<nBytesRead<<std::endl;
    	}
       else{
          std::cout<<"Aucune données reçues"<<std::endl;
       }  
    	return(0);
    }
    Ensuite la réception :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    std::vector<unsigned char> buffer_rec;
    ReceiveTrame(buffer_rec);
    if(buffer_rec.size()>=7){
       short temperature = buffer_rec[5]<<16 + buffer_rec[6];
    }
    Code à la volé probablement perfectible ...

  7. #7
    Membre confirmé Avatar de vtk37
    Inscrit en
    Avril 2009
    Messages
    159
    Détails du profil
    Informations personnelles :
    Âge : 36

    Informations forums :
    Inscription : Avril 2009
    Messages : 159
    Par défaut
    merci pour ta reponse,

    j'ai essayé avec ta methode et j'obtient ce message quand je ferme le programme

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Windows a déclenché un point d'arrêt dans COM_serie.exe.
     
    Cela peut être dû à une défaillance du tas qui indique un bogue dans COM_serie.exe ou l'une des DLL chargées.
     
    Cela peut également être dû à l'appui sur la touche F12 lorsque COM_serie.exe a le focus
     
    La fenêtre Sortie peut contenir des informations de diagnostic supplémentaires.
    j'obtient d'ailleurs le même en ayant fait quelque modification à mon programme initial.

    en remplaçant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sprintf(ChaineRecue,"%s",inBuffer);
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    if(nBytesRead>0)
    	{
    		for(i=0;i<=nBytesRead-1;i++)
    		     ChaineRecue[i]=inBuffer[i];// Retourne la chaine reçue
     
    	}
    mais sa me permettait au moins de récupérer entièrement la chaine reçue

  8. #8
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    La vérité est ailleurs ?
    En debuggant en mode pas à pas tu ne peux pas voir où se déclenche l'exception ?
    Fais voir ton main complet avec la modif que je te propose.

  9. #9
    Membre confirmé Avatar de vtk37
    Inscrit en
    Avril 2009
    Messages
    159
    Détails du profil
    Informations personnelles :
    Âge : 36

    Informations forums :
    Inscription : Avril 2009
    Messages : 159
    Par défaut
    j'ai trouvé pourquoi, j'avais mis delete[] Temp; mais bon il voulais pas

    sinon avec ta fonction reception, il me dit tout le temps que je ne reçoit rien alors que j'ai reçoit bien des trames...

    EDIT: c'est bon j'ai trouvé pourquoi, boulet inside

  10. #10
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    ?

  11. #11
    Membre confirmé Avatar de vtk37
    Inscrit en
    Avril 2009
    Messages
    159
    Détails du profil
    Informations personnelles :
    Âge : 36

    Informations forums :
    Inscription : Avril 2009
    Messages : 159
    Par défaut
    euh presque

    je manipule pas trés bien std::cout alors est-ce qu'il y a un moyen de toujours afficher en majuscule? et d'avoir le 0 devant?

    car la sa m'affiche 3 0 0 22 ee 1 49 et je voudrai 03 00 00 22 EE 01 49 c'est possible?

    et :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    short temperature = (buffer_rec[5]<<16) + buffer_rec[6];
    std::cout<<"\n Temperature="<<temperature;
    m'affiche température=49, il est passé ou le 1 devant? à quoi correspond le <<16? c'est ce qui permet de convertir en décimale?

  12. #12
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par vtk37 Voir le message
    il est passé ou le 1 devant? à quoi correspond le <<16? c'est ce qui permet de convertir en décimale?
    Je me suis emballé
    <<16 correspond à un décalage de bit.
    Tu veux constuire un short à partir des deux octets buffer_rec[5] et buffer_rec[6]. Il faut donc faire un peu de calcul et pour cela on utilise le décalage de bit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    short temperature = (buffer_rec[5]<<8) + buffer_rec[6];
    ou :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    short temperature = buffer_rec[5]*256 + buffer_rec[6];
    De vieux réflexe C me font souvent écrire la première version. Mais elles sont strictement équivalentes.

    Pour le formatage, oui. C'est possible. Cf FAQ.

  13. #13
    Membre confirmé Avatar de vtk37
    Inscrit en
    Avril 2009
    Messages
    159
    Détails du profil
    Informations personnelles :
    Âge : 36

    Informations forums :
    Inscription : Avril 2009
    Messages : 159
    Par défaut
    super merci beaucoup pour ton aide. Voila maintenant je peux mettre le petit

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 10
    Dernier message: 04/08/2006, 21h56
  2. problème de récupération de trame
    Par thony76 dans le forum Visual C++
    Réponses: 25
    Dernier message: 27/07/2006, 10h38
  3. problème de manipulation de clip
    Par lecyberax dans le forum Flash
    Réponses: 4
    Dernier message: 04/06/2006, 13h31
  4. [DOM] Problème de manipulation DOM avec IE7
    Par volivi dans le forum Général JavaScript
    Réponses: 8
    Dernier message: 25/04/2006, 10h49
  5. Réponses: 4
    Dernier message: 20/08/2004, 10h59

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo