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

Visual C++ Discussion :

Communication série: perte de données


Sujet :

Visual C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre émérite Avatar de homeostasie
    Homme Profil pro
    Inscrit en
    Mai 2005
    Messages
    939
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 939
    Par défaut Communication série: perte de données
    Bonjour,

    Pour définir le contexte, j'utilise la classe CCom de Farscape pour récupérer des données en mode asynchrone sur la liaison série. Je lance le thread de réception à partir d'une classe dérivée de CDialog. Lorsque le thread détecte l'événement EV_RXCHAR, il envoie un message WM_CCOMRCV vers ma classe parent dérivée de CDialog. L'arrivée de ce message déclenche la fonction suivante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    long CComTLS::ON_WM_CCOMRCV(WPARAM wparam,LPARAM lparam)
    {
    	char sz[4096+1] = {0};
     
    	m_comDll.ReadBuffer(sz,sizeof(sz)-1);
    	m_sRx += sz;
     
    	m_nTotalOctetLus += m_comDll.GetCountRead();	
     
    	return 0L;
    }
    Ainsi, je viens lire et stocker les données dans le buffer de réception à chaque émission du message WM_CCOMRCV.

    Je gère un time out de réception grace au code suivant: (Ce code fait partie d'une fonction appellée par un autre thread de travail qui attend de réceptionner toutes les données émises).
    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
    if(ret)
    {
    	bool bEndWhile = false;
    	UINT OctetLus = 0;
    	while(!bEndWhile)
    	{
    		OctetLus = m_nTotalOctetLus;
    		Sleep(2000);
    		if( OctetLus == m_nTotalOctetLus )
    		{
    			bEndWhile = true;
    		}
    	}
    	m_sMNV = m_sRx;
    }
    Mon problème:
    Ce code fonctionne depuis un moment. Mais bizarrement, je perds des données depuis peu...
    J'utilise ce même code dans une version antérieure du logiciel que je développe et j'obtenais ceci:
    01 54 00 00 01 00 01 01 01 D8 0810 00000028 00 EF 4C TOTO
    01 42 00 00 01 00 01 03 01 00 0800 000000B6 61 EF 4C TATA
    01 54 00 01 01 00 01 01 01 C9 0810 00000028 00 EF 4C TOTO
    01 42 00 01 01 00 01 03 01 00 0800 000000B6 61 EF 4C TATA
    Maintenant j'obtiens cela:
    01 54 00 00 01 00 01 01 01 D8 0810 00000028 00 EF 4C TOTO0 01 00 01 03 01 00 0800 000000B6 61 EF 4C TATA 01 54 00 01 01 00 01 01 01 C9 0810 00000028 00 EF 4C TOTO01 42 00 01 01 00 01 03 01 00 0800 000000B6 61 EF 4C TATA
    Il me manque donc de temps en temps des caractères (ici le saut de fin de ligne, mais aussi des données)...

    Quelles pourraient être les causes de pertes de données? et quelles pourraient être les raisons pour que d'un côté (version antérieur du logiciel) ca fonctionne et de l'autre (version actuelle) non?

    Il y aurait il une histoire d'augmenter la priorité d'un thread?

    Si vous avez des idées, merci d'avance.

    Nicolas

  2. #2
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Par défaut
    salut,
    pour les pb de perte de caractères il faut déjà être sûr du reste:
    - vitesse adaptée à la longueur du cable et cable blindé et environnement sain.
    - gestion de flux matériel rts/cts (préférable). -> cable correct.
    - buffer de réception adapté.

    si tu as un gestion de flux correct tu ne dois pas perdre de caractères ou alors tu as un chipset vraiment mauvais (ce qui n'est plus le cas depuis des années sur les pc).


  3. #3
    Membre confirmé
    Inscrit en
    Janvier 2006
    Messages
    165
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 165
    Par défaut
    Bonjour,

    Je pense qu'au lieu de fixer la taille de ton buffer de réception par

    char sz[4096 +1]

    tu devrais utiliser plutôt la fonction de la classe CCom de Farscape qui retoure le nombre de caractères disponibles.

  4. #4
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Par défaut
    Citation Envoyé par David Fouejio
    Bonjour,

    Je pense qu'au lieu de fixer la taille de ton buffer de réception par
    char sz[4096 +1]

    tu devrais utiliser plutôt la fonction de la classe CCom de Farscape qui retoure le nombre de caractères disponibles.
    hum effectivement je n'avais pas fait attention a cette partie de code...
    cette portion la :
    pour moi n'est pas correcte...
    si ton buffer de réception reçoit un zéro ton ajout à m_srx sera tronqué.
    il vaut mieux utiliser :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    char sz[4096+1] = {0};
     
    m_comDll.ReadBuffer(sz,sizeof(sz)-1);
    m_sRx += CString(sz,m_comDll.GetCountRead());

  5. #5
    Membre émérite Avatar de homeostasie
    Homme Profil pro
    Inscrit en
    Mai 2005
    Messages
    939
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 939
    Par défaut
    Citation Envoyé par farscape
    si tu as un gestion de flux correct tu ne dois pas perdre de caractères ou alors tu as un chipset vraiment mauvais (ce qui n'est plus le cas depuis des années sur les pc).

    Oui oui, ca ne vient pas de là, c'est clair!

    Sinon j'ai essayé ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    char sz[4096+1] = {0};
     
    m_comDll.ReadBuffer(sz,sizeof(sz)-1);
    m_sRx += CString(sz,m_comDll.GetCountRead());
    Résultat de ceci, je sauvegarde seulement la première lecture du buffer de réception, bizarre...

    Dans mon cas, je me dis que cela
    est correcte car je travaille en ascii. J'initialise au préalable à zéro mon tableau de char pour être sur d'avoir le caractère de fin de chaine afin de stocker seulement ce que jeviens de lire dans mon buffer de réception.

    J'ai effectué un autre test ce matin, en faisant ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    long CComTLS::ON_WM_CCOMRCV(WPARAM wparam,LPARAM lparam)
    {
            char sz[4096+1] = {0};
     
    	m_comDll.ReadBuffer(sz,sizeof(sz)-1);
    	UINT nOctetLus = m_comDll.GetCountRead();
    	TRACE(" %d -> %s",nOctetLus,sz);
    	m_sRx += sz;
     
    	m_nTotalOctetLus += nOctetLus;	
     
    	return 0L;
    }
    Je constate que de temps en temps, GetCountRead() annonce que je viens de lire x caractères (par exemple 42) et que sz n'en compte que y (par exemple 13). La différence entre ces deux valeurs corresponds aux caractères soit disant perdus... Je ne comprends pas d'ou vient le problème!

    A titre d'information, les valeurs retournées par GetCountRead() sont celles que j'attends vraiment. Le soucis viendrait alors de ma facon de récupérer les caractères recus ou sinon de la fonction ReadBuffer() fourni dans la classe CCom qui me stocke incorrectement les caractères reçus(ce qui me surprendrait mais on ne sait jamais...).

    Une idée? Ou une autre facon d'implémenter?

    Merci

    Nicolas

  6. #6
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Par défaut
    salut,
    et pour la gestion de flux ? le cable etc .. ?

  7. #7
    Membre émérite Avatar de homeostasie
    Homme Profil pro
    Inscrit en
    Mai 2005
    Messages
    939
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 939
    Par défaut
    Citation Envoyé par farscape
    salut,
    et pour la gestion de flux ? le cable etc .. ?
    Niveau gestion de flux, je n'ai rien réglé. J'ai laissé l'initialisation par défaut.
    La configuration que j'utilise actuellement fonctionne très bien avec l'hyperterminal et avec des versions antérieures du logiciel.

    Si j'ajoute un sleep(100) dans ma fonction de message privé
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    long CComTLS::ON_WM_CCOMRCV(WPARAM wparam,LPARAM lparam)
    alors je perds encore plus de données, sachant que GetCountRead() me retourne toujours bien le nombre de données que je désirerais lire.

    Cela pourrait il venir du fait que ma pompe à messages ne traite pas assez rapidement le message ou bien le code associé dans le message privé?

    Ma configuration série est de 8 bits de données, 1 bit de stop, et 19200 bauds.

    En espérant que cela fasse avancer l'affaire...

  8. #8
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Par défaut
    si tu n'as rien réglé au niveau gestion de flux il ne faut pas s'etonner si tu perds des caractères .....

  9. #9
    Membre émérite Avatar de homeostasie
    Homme Profil pro
    Inscrit en
    Mai 2005
    Messages
    939
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 939
    Par défaut
    Citation Envoyé par Farscape
    si tu ne connais pas la gestion de flux ne met pas xon/xoff c'est le plus sur moyen de tout bloquer ...
    règle le en mode rts/cts.
    Avec le mode rts/cts, je ne récupère plus rien!

    J'ai aussi essayé avec les autres modes, cela ne change rien au fait que je perds des données.

    De plus, j'ai implémenté différemment ma lecture du port série, sans passer par le lancement du thread, mais en effectuant ma récupération de données à coup de ReadBuffer(), le résultat est le même...

  10. #10
    Membre émérite Avatar de homeostasie
    Homme Profil pro
    Inscrit en
    Mai 2005
    Messages
    939
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 939
    Par défaut
    Bonjour,

    En fait, l’origine de la panne provient du temps de traitement de l’application vis à vis des messages.
    Dans mon cas de figure, un thread de travail lançait le thread de réception de données. Ce dernier informait l’arrivée de données en émettant un message privée vers mon thread de travail.
    Afin de réaliser un curseur d’attente durant la réception de données à partir de mon thread de travail, j’avais fait le code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    //Forme du curseur en sablier: attente
    ::PostMessage(m_hWnd,WM_GESTION_CURSEUR,0,0);  // Message vers le thread principal d’interface utilisateur
    m_WaitCursor = true;
    Dans mon thread principal d'interface utilisateur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    long CTLDlg::OnReceiveGestionCurseur(WPARAM wparam,LPARAM lparam)
    {
    	BeginWaitCursor();
    	while(m_WaitCursor)
    	{
    		PumpMessages();
    		RestoreWaitCursor();
    		Sleep(50);			
    	}
    	EndWaitCursor();
     
    	return 0l;
    }
    Cette fonction devait me consommer trop de temps de traitement. Depuis que je l’ai mise en commentaires, je n’ai plus de perte de données, enfin presque…

    2 problèmes subsistent :
    - Si l’utilisateur joue avec la fenêtre principale (la bouge dans tout les sens), superpose rapidement une autre fenêtre dessus en déplacement rapide etc…, je perds à nouveau des données, dues au traitement des messages pour mettre à jour la fenêtre de mon application.
    J’ai pourtant augmenté la priorité du thread de travail mais aucun résultat. A ce jour, j’ai intercepté et bloqué tout les clics souris sur le fenêtre de l’application durant la réception des données.
    Il y a t’il une méthode plus astucieuse ?

    - Comment implémenter un curseur d’attente à partir d’un thread de travail créé à partir du thread principal de l’interface utilisateur ?
    J’ai fait ceci mais cela n’y fait rien, pas de curseur d'attente :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    HCURSOR hCursor = AfxGetApp()->LoadStandardCursor(IDC_WAIT);
    if(NULL == hCursor)
    AfxMessageBox("Erreur pour charger le curseur d'attente",MB_OK);
    Merci pour votre aide.

    Nicolas

  11. #11
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Par défaut
    salut,
    je sais je me répète mais :
    c'est pour cela que l'on travaille avec une gestion de flux ....
    pour éviter de perdre des caractères quand le récepteur n'est pas prêt.
    il vaudrait mieux que tu creuses la question de la gestion de flux coté émetteur.
    on ne peut pas faire du transfert de données en flux continu sans gestion de flux...

  12. #12
    Membre émérite Avatar de homeostasie
    Homme Profil pro
    Inscrit en
    Mai 2005
    Messages
    939
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 939
    Par défaut
    C'est vrai, tu as raison!

    Citation Envoyé par farscape
    il vaudrait mieux que tu creuses la question de la gestion de flux coté émetteur
    A vrai dire je crois qu'il y en a pas (aucune spéc sur l'équipement indique une gestion de flux), et je ne pourrais modifier le code implémenté dans l'équipement.

    Ayant essayé tout les modes possibles de gestion de flux et n'ayant pas eu de résultats probants, j'en conclue donc que la gestion de flux coté émetteur n'a pas été géré...

    Il y a un truc qui m'échappe. Je pensais que toutes données recues sur le port série sont stockées dans un buffer de réception géré au niveau hardware, pourquoi perdrais je des données? A moins que si je recois des données alors que le processeur est occupé pour une autre tâche, alors je perds ces dernières?

  13. #13
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Par défaut
    le buffer au niveau du hardware est très limité (quelques octets) ça dépend du chipset série,
    ici c'est windows qui prend le relai au niveau du buffer .
    dans ma classe le buffer est réglé par défaut à 1050 octets .
    tu as peut être intérêt a augmenter la valeur par défaut.
    la gestion de flux assure au moins que lorsque le buffer est rempli l'émetteur est avertit pour qu'il s'arrête d'émettre ...
    je peux pas croire que le matériel en question ait fait l'impasse sur ce sujet.

  14. #14
    Membre émérite Avatar de homeostasie
    Homme Profil pro
    Inscrit en
    Mai 2005
    Messages
    939
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 939
    Par défaut
    Citation Envoyé par farscape
    dans ma classe le buffer est réglé par défaut à 1050 octets .
    tu as peut être intérêt a augmenter la valeur par défaut.
    C'est déjà fait!
    Mais je ne suius pas sur que cela est servi car j'ai rajouté une Trace après l'appel de la fonction GetOverlappedResult() et je recois puis lis de 1 a 2 octets.

    Citation Envoyé par farscape
    je peux pas croire que le matériel en question ait fait l'impasse sur ce sujet.
    C'est un équipement conçu et développé par la boite dans laquelle je travaille. Et j'ai l'impression que le programmeur qui s'est occupé de cette partie a omi la gestion de flux.
    Je vais tâcher de me renseigner.

    En tout cas, merci pour les renseignements!


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

Discussions similaires

  1. Perte de données sur laison série
    Par antyriad dans le forum Linux
    Réponses: 0
    Dernier message: 08/12/2008, 10h55
  2. [VB.NET] Communication série
    Par DotNET74 dans le forum Windows Forms
    Réponses: 4
    Dernier message: 16/03/2005, 14h02
  3. Crash InnoDB,perte de données définitives... Info ou Intox ?
    Par Alexandre T dans le forum Administration
    Réponses: 3
    Dernier message: 17/01/2005, 10h44
  4. [JTable] Perte des données
    Par david71 dans le forum Composants
    Réponses: 8
    Dernier message: 09/01/2005, 00h37
  5. [API] Communication série NON-bloquante : OVERLAPPED/Thread
    Par Rodrigue dans le forum C++Builder
    Réponses: 2
    Dernier message: 07/11/2003, 13h43

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