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 :

Récupérer le buffer de ReadFile-Comm UART


Sujet :

C

  1. #21
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Et d'après toi, pourquoi cela affiche n'importe quoi, alors que la même instruction juste avant le return affiche ce que tu veux?

    indice: que signifie return?

    indice aussi: comment expliques-tu en français normal "la sémantique de passage d'argument en C est le passage par initialisation."?

    Dans les deux cas, la leçon devrait être assez cuisante pour que tu t'en souviennes à vie. (C'est comme ça qu'on apprend bien )

  2. #22
    Membre confirmé
    Femme Profil pro
    Étudiant
    Inscrit en
    Mars 2015
    Messages
    75
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 33
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Mars 2015
    Messages : 75
    Par défaut
    Merci pour votre réponse.

    Je vois que c'est un problème de passage de paramètres par variable ou valeur.

    En fait, dans mon cas, j'ai fais un passage par valeur et donc la modification de la variable locale msg dans ma fonction DumpHexa ne modifie la variable passée en paramètre (msg du main) .

    Ce que j'ai corrigé maintenant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    printf(" %s\n\n", DumpHexa(inBuffer, nBytesRead,msg));
    Et là tout est bien.
    Bon, faut dire que ça marche: mon msg est bien affiché dans les deux cas, sauf que l'.exe rencontre un problème et ferme. Donc, je sais pas si c'est lié à l'appelle de la fonction DumpHexa ou non .

    Je sais pas aussi si y a une autre solution ou non . Et si ma solution est ce qu'on appelle passage par variable.


    Merci

  3. #23
    Membre très actif
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    Mai 2010
    Messages
    551
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : No Comment
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Mai 2010
    Messages : 551
    Par défaut
    Bonjour,
    Mise à part ce que les autres membres du forum on dit j’ajouterais juste quelque remarque.
    Premièrement pour être sur et éviter des erreurs éventuelles, il ne serait pas déconnant de mettre un \0 à la fin de chaîne lue comme ça en est sûr que l’on a bien une chaîne de caractère et que l’on pourra faire les manipulations adéquates et adapter par la suite et honnêtement; je ne vois à aucun moment où l’on rajoute la séquence de fin de chaîne. Ceci dit c’est peut-être voulu même après que la fonction ReadFile est renvoyée vrai.
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    fSuccess=ReadFile(hCom, inBuffer, 5, &nBytesRead, NULL);
    if ( fSuccess && ( 0 < nBytesRead) ){
        fprintf(stderr, "Debug\t:%d",  GetLastError() );
        inBuffer[nBytesRead] = '\0';
    }else{
        /*
         *  Faire le necessaire
         */
        CloseHandle(hCom);
        return EXIT_FAILURE;
    }

    Il est essentiel important de comprendre que les fonctions GetCommTimeouts & SetCommTimeouts peuvent être la cause (dans le cas actuel ou futur) de certaines erreurs. Il faut savoir que ces deux fonctions donnent des résultats qui sont imprévisibles soit à cause du temps imparti (temps a écoulé voir beaucoup trop top ou alors le temps adéquat n’a pas été déterminer) ou alors si je peux dire tout simplement de la façon d’on a initialisé et configuré la chose. Plus clairement le comportement de ReadFile et WriteFile est régi par les délais d'attente qui peuvent fournir des résultats imprévisibles si vous ne parvenez pas à définir des valeurs de temporisation satisfaisante.

    Citation Envoyé par abyass Voir le message
    fSuccess = GetCommTimeouts(hCom, &dcb);
    if (!fSuccess)
    {
    //Manipuler l'erreur
    printf("GetCommTimeouts failed with error %d\n", GetLastError());
    }
    //Définition des timeouts
    TimeoutRead= 700; // timeout de 1000ms
    tTimeout.ReadIntervalTimeout= MAXWORD;
    tTimeout.ReadTotalTimeoutMultiplier=0;
    tTimeout.ReadTotalTimeoutConstant=TimeoutRead;
    tTimeout.WriteTotalTimeoutMultiplier=0;
    tTimeout.WriteTotalTimeoutConstant=0;

    //Configuration du Timeout

    fSuccess = SetCommTimeouts(hCom, &tTimeout);
    if (!fSuccess)
    {
    //Manipuler l'erreur
    printf("SetCommTimeouts failed with error %d\n", GetLastError());
    }

    fSuccess=ReadFile(hCom, inBuffer, 5, &nBytesRead, NULL);


    if (!fSuccess)
    {
    //Manipuler l'erreur
    printf("ReadFile failed with error %d\n", GetLastError());
    }
    else if (nBytesRead==0) // pas des octets lus
    printf("pas de chaine reçue \n");
    Plus en détail, si l’on définit ReadIntervalTimeout et/ou ReadTotalTimeoutMultiplier à MAXDWORD et que l’a attribué à ReadTotalTimeoutConstant une valeur supérieure à zéro et inférieure à MAXDWORD, le comportement de ReadFile est directement impacter. Lorsque la fonction ReadFile sera appelée et que s’il y a des data dans votre buffer, ReadFile retourne immédiatement vrai avec les data qui sont dans le buffer (dans votre cas ici buffer est inBuffer).
    Dans un autre cas, s’il n'y a pas de data dans le buffer ReadFile va boucler jusqu'à ce qu'une data arrive et retourne vrai immédiatement. Et si aucune data arrives dans le délai imparti déterminer par ReadTotalTimeoutConstant il y a time out tous simplement.
    Donc par précautions dans un premier temps (debug) je conseille de connaître l’état de ReadFile en utilisant GetLastError même si elle retourne vraie.


    Il y'a également une chose; d’un point de vue général, pour être sûre que toutes les données écrites sont transférées il faut fermer handle immédiatement après l'écriture. Cas contraire cela peut être problématique. Et tout comme ReadFile le comportement de WriteFile est également régi par les délais d'attente configurée par les fonctions respectives GetCommTimeouts & SetCommTimeouts et il peut se produire également des résultats imprévisibles si vous ne parvenez pas à définir les valeurs de temporisation. Donc même scénario que dans ReadFile.
    Autre particularité, WriteFile renvoie des résultats quand le nombre data demandés a été correctement écrit et que l’opération de lecture du côté de la carte est finie de lire ou quand un handle asynchrone est employé et que l'écriture se face également de manière asynchrone. Quant aux erreurs c’est soit quand on annule une opération d’écriture attente ou en cours ou ERROR_NOT_ENOUGH_MEMORY s’il y a trop de demandes en écriture en attente.

    Je trouve donc que ce n’est pas une très bonne idée de laisse le handle ouvert après avoir écrit des données et surtout quelle est la raison valable qui justifie cela j'ai également une question qui me taraude la tête et par curiosité. Je vois oscilloscope, UART et une autre carte électronique donc la question que je vous pose est la suivante on travaille en mode synchrone ou asynchrone pur, car le choix de la fonction de lecture par exemple sera alors différente (ReadFile/ReadFileEx) même-ci ReadFile fais les deux tout comme WriteFile (WriteFileEx).
    Et pour finir, quand un processus s’achève en retournant une valeur qui est différente du zéro c’est qu’il y a un truc qui cloche ou alors je me trompe et que le système d'exploitation Windows retourne systématiquement une valeur positive pour dire que tout s’est bien passé !

    à bientôt

  4. #24
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Je réponds uniquement à ton message, sans rien retirer à la réponse de sambia39
    Citation Envoyé par abyass Voir le message
    Merci pour votre réponse.

    Je vois que c'est un problème de passage de paramètres par variable ou valeur.

    En fait, dans mon cas, j'ai fais un passage par valeur et donc la modification de la variable locale msg dans ma fonction DumpHexa ne modifie la variable passée en paramètre (msg du main) .

    Ce que j'ai corrigé maintenant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    printf(" %s\n\n", DumpHexa(inBuffer, nBytesRead,msg));
    Et là tout est bien.
    Bon, faut dire que ça marche: mon msg est bien affiché dans les deux cas, sauf que l'.exe rencontre un problème et ferme. Donc, je sais pas si c'est lié à l'appelle de la fonction DumpHexa ou non .

    Je sais pas aussi si y a une autre solution ou non . Et si ma solution est ce qu'on appelle passage par variable.

    Merci
    Pas mal répondu

    Supposons la fonction int somme(int a, int b) { return a+b; }.

    return est un mot clé qui permet de définir la valeur de l'expression constituée par l'appel de la fonction.
    Le "passage par initialisation" signifie que les paramètres d'une fonction sont des variables locales, définies par les expressions utilisées en argument pour appeler la fonction.
    C'est la seule façon de passer un argument.

    C'est à dire que l'instruction int i = somme(1, 5-4); est la définition de la variable i, de type int, dont la valeur est initialisée avec l'expression somme(1,2).
    Cette expression est calculée ainsi:
    • Création de la variable a (de somme), initialisée avec la valeur de l'expression 1, c'est à dire 1.
    • Création de la variable b (de somme), initialisée avec la valeur de l'expression 5-4, c'est à dire 1. (note: l'ordre d'évaluation des arguments n'est pas garanti par la norme)
    • évaluation de return a+b;: a+b est d'abord évaluée (1+1=2), puis sa valeur est stocké dans la pile à l'emplacement "valeur de retour". (il y a des détails de compilation à expliquer à ce sujet)
    • Sortie de la fonction, a et b sont détruites (oubliées), et le pointeur de pile redescend à sa place d'avant l'appel de la fonction.
    • la valeur de retour est en haut de la pile, prête à être utilisée

    Une fois l'expression calculée, l'initialisation a lieu.

    Dans ton code précédent, la fonction retourne la nouvelle chaine (celle "malloc"ée), mais tu ne fais rien de cette valeur, elle est perdue.

    Plus grave, et que tu n'as pas résolu.
    le pointeur msg de ta fonction est une variable locale. Lorsque tu fais ton malloc, l'adresse obtenue est stockée dans cette variable locale.
    la variable utilisée pour appelée la fonction, elle, n'est pas modifiée.

    Ce qu'il faudrait faire, c'est soit passer un pointeur msg (donc un char* *msg), et faire le malloc.
    Soit ne pas prendre le pointeur en argument du tout, et seulement le retourner. C'est ce que je ferai, avec un commentaire d'avertissement que la mémoire retournée doit être désallouée.

    Premier cas void DumpHexa(const void* pcvDebut, size_t taille,char **msg);. Je le déconseille, car la gestion de la mémoire serait délicate pour rien.
    Deuxième cas char* DumpHexa(const void* pcvDebut, size_t taille);//le pointeur retournée doit être désalloué.

    Et c'est en allant faire un copié collé que j'ai vu ton problème.
    Ta fonction retourne un char, mais le return est appelé avec un char*.

    Ca compile mais ne fais pas du tout ce que tu veux. Ca convertit ton pointeur en un entier, et le réduit à la taille d'un char.
    Comme il est peut probable que l'adresse soit dans la plage de valeur de char, la valeur retournée n'est plus l'adresse obtenue par malloc.
    Ton printf doit planter, en accédant à de la mémoire interdite.

    La correction immédiate de ton plantage est de retourner un char*. Mais ca ne suffit pas à résoudre le problème de fuite mémoire.
    Tu devrais coder à peu près ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    char * msg = DumpHexa(inBuffer, nBytesRead);
    printf(" %s\n\n", msg);
    free(msg);

    Les expressions passage par valeur et par référence désigne deux logiques qu'on peut simuler plus ou moins facilement.
    Pour le passage par valeur, seule la valeur de l'expression est passée en argument, et la fonction n'a pas accès à la dite expression. Cette logique est celle obtenue par le passage d'argument du C. Au détail près que la valeur est utilisée pour initialiser une variable locale de la fonction, le paramètre.

    Le passage par référence signifie que la fonction reçoit une référence vers une chose qui lui est extérieure, et peut ainsi modifier cette chose. En C, on simule ce fonctionnement avec un pointeur.
    Par exemple, si la fonction prend un int* en argument, elle peut modifier l'entier désigné par l'adresse contenue dans le pointeur.
    Cependant, elle ne peut pas changer le pointeur donné en argument, mais seulement son paramètre, qui est une variable locale.

    Pour faire changer un pointeur par une fonction, il faut lui donner l'adresse du pointeur en argument, valeur qu'on place dans un pointeur de pointeur.

  5. #25
    Membre confirmé
    Femme Profil pro
    Étudiant
    Inscrit en
    Mars 2015
    Messages
    75
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 33
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Mars 2015
    Messages : 75
    Par défaut
    Merci infiniment pour vos réponse claires et bien détaillées et pour vos temps aussi.

    ça fait un moment que je n'ai pas travaillé en C et je commence là à reprendre la main et dans une grande partie, c'est grâce à vous et ce forum .


    sambia39 je vais prendre en considération vos remarques.


    Dans cette phase j'ai finalisé l'envoie/Réception d'une trame ainsi sa réponse. Et je dois attaquer la communication complète: Envoie des plusieurs trames dont je récupère à chaque fois un message différent sans fermer le port. comme j'ai mentionné en haut, ils vont être traité par la suite

    L'écriture (envoie de trrame) marche bien mais je commence à avoir des lacunes cotés réception des différents messages.

    Je voulais en fait, voir si y a des tuto ou cours à me conseiller pour ce fait.

    Je sais pas si je dois ouvrir une nouvelle discussion pour poser mes nouvelles questions ou je continue sur cela .

    Merci

  6. #26
    Membre confirmé
    Femme Profil pro
    Étudiant
    Inscrit en
    Mars 2015
    Messages
    75
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 33
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Mars 2015
    Messages : 75
    Par défaut
    Bonjour tout le monde,

    Je reviens encore une fois vers cette discussion pour demander vos aides SVP.

    En fait, j'ai finalisé mon programme de communication avec le port UART et le traitement des données reçues.

    Sauf que j'ai un problème qui n'apparait que lors de la lecture de 3 registres particuliers (En totalités, j'ai 12 registres à récupérer: 12 requêtes de lecture et écritures).

    En fait, lorsque j'enlève les requêtes qui demandes ces registres: tout marche bien.

    Je n'arrive pas à comprendre le problème :

    Nom : Capture.PNG
Affichages : 312
Taille : 47,0 Ko

    Merci

  7. #27
    Membre émérite
    Avatar de emixam16
    Homme Profil pro
    Chercheur en sécurité
    Inscrit en
    Juin 2013
    Messages
    335
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : Chercheur en sécurité

    Informations forums :
    Inscription : Juin 2013
    Messages : 335
    Par défaut
    Ton erreur est assez claire, tu essayes de lire l'adresse zéro, autrement dit tu fais l'équivalent de *0;. Ceci te donne un comportement indéterminé qui plante ici (tu as de la chance).

    Vérifie tes accès mémoire et trouve où ceux-ci sont incorrects.

    Si tu as la flemme de faire ça manuellement, tu peux utiliser Valgrind. Ce logiciel est très simple d’utilisation. (livré par défaut avec CodeBlocks Contrib)

  8. #28
    Membre confirmé
    Femme Profil pro
    Étudiant
    Inscrit en
    Mars 2015
    Messages
    75
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 33
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Mars 2015
    Messages : 75
    Par défaut
    Merci pour votre réponse.


    En fait ce que je constate que je ne peux pas envoyer plus que 8 trames . Ce n'est pas en fait un problème de quel registre à envoyer mais plutôt un problème de registres à récupérer.

    Sachant que je n'ai rien mentionnée dans le datasheet de la carte. Donc je ne sais pas comment permettre à la carte de recevoir plus que 8 requêtes? Je n'arrive pas à détecter si c'est un problème de timeout ou quoi ? (ça peut que je suis entrain de dire des bêtises )

    Merci

Discussions similaires

  1. [PHP 5.1] Récupérer une carte Google Maps comme une image
    Par ADB34 dans le forum Langage
    Réponses: 2
    Dernier message: 07/07/2014, 00h34
  2. récupérer valeur liste de choix comme paramêtre dans un requete
    Par ecoutertudevra dans le forum Requêtes et SQL.
    Réponses: 5
    Dernier message: 03/03/2012, 11h09
  3. [Cairo] Récupérer le buffer
    Par gerald3d dans le forum GTK+ avec C & C++
    Réponses: 6
    Dernier message: 09/11/2010, 18h32
  4. récupérer une image avec readfile
    Par julien1451 dans le forum Langage
    Réponses: 11
    Dernier message: 27/01/2010, 02h06
  5. Récupérer le buffer de facon dynamique
    Par Bmauet dans le forum Débuter
    Réponses: 2
    Dernier message: 26/10/2008, 19h18

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