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 :

Optimisation de l'utilisation du port COM en C++ sous linux


Sujet :

C++

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    janvier 2006
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : janvier 2006
    Messages : 12
    Points : 34
    Points
    34
    Par défaut Optimisation de l'utilisation du port COM en C++ sous linux
    Salut,
    J'utilise la bibliothèque Termios pour faire de la lecture écriture sur port série.
    Mais j'obtiens des taux de transferts vraiment trop bas...
    J'aurai aimé savoir si l'un de vous avait une idée sur comment améliorer ça...

    Voilà les bouts de codes en rapport avec l'utilisation du port série :
    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
    //ouverture et configuration du port :
     handle = open(m_comname.c_str(), O_RDWR | O_NOCTTY);
        if (handle < 0) {
          return OC_CREATE_HANDLE_ERR;
        }
        struct termios newtio;
        bzero(&newtio, sizeof (newtio));
     
        newtio.c_cflag = m_baudrate | CS8 | CLOCAL | CREAD;
        newtio.c_iflag = IGNPAR;
        newtio.c_oflag = 0;
     
        /* set input mode (non-canonical, no echo,...) */
        newtio.c_lflag = 0;
     
        newtio.c_cc[VTIME] = 1; /*0.1sec timeout between each char*/
        newtio.c_cc[VMIN] = 188; /* blocking read until 188 chars received (max length of a reading) or until timeout exceed*/
        newtio.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
                | INLCR | IGNCR | ICRNL | IXON);
        newtio.c_oflag &= ~OPOST;
        newtio.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
        newtio.c_cflag &= ~(CSIZE | PARENB);
        newtio.c_cflag |= CS8;
     
     
        tcflush(handle, TCIOFLUSH);
        tcsetattr(handle, TCSANOW, &newtio);
     
    //Lecture ecriture :
        tcflush(handle, TCIOFLUSH);
        bStatus = write(handle, pSendBuf, sendLength);
        if ((bStatus == 0) || (bStatus == -1)) {
            return TRANSMIT_ERR_WRITE;
        }
     
        bStatus = read(handle, pRecvBuf, 255);
        if (bStatus < 0) {
            return TRANSMIT_ERR_WRITE;
        }
     
        recvLength = bStatus;
    Merci beaucoup d'avoir ne serait-ce que jeter un œil a mon code...
    Avec cette méthode là, j'ai réussi a améliorer déjà pas mal la réactivité, mais pas encore assez pour rendre tout ça utilisable...

    A++
    Fabien

  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
    Points : 13 008
    Points
    13 008
    Par défaut
    Salut,
    Que vaut m_baudrate ? A quoi sert newtio.c_cc[VTIME] ? Est-ce cohérent avec m_baudrate ?

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    janvier 2006
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : janvier 2006
    Messages : 12
    Points : 34
    Points
    34
    Par défaut
    m_baudrate = B9600 , c'est la variable définissant le fonctionnement d'un port com en 9600bps
    newtio.c_cc[VTIME] sert de timeout, ici de timeout de réception entre chaque caractère.
    extrait du man:
    VMIN Nombre minimal de caractères lors d’une lecture en mode non
    canonique.

    VTIME Délai en dixièmes de seconde pour une lecture en mode non canonique.


    Dans le mode non canonique, l’entrée est disponible tout de suite (sans
    que l’utilisateur ait à taper de caractère délimiteur de ligne) et
    l’édition des lignes est désactivé. La valeur des paramètre MIN
    (c_cc[VMIN]) et TIME (c_cc[VTIME]) détermine les circonstances dans
    lesquelles read(2) se termine ; il y a quatre cas différents :

    * MIN == 0; TIME == 0 : Si des données sont disponibles, read(2)
    retourne immédiatement le nombre d’octets disponibles ou le nombre
    d’octets demandés (le plus petit des deux). Si aucune donnée n’est
    disponible, read(2) renvoie 0.

    * MIN > 0; TIME == 0 : read(2) est bloquant jusqu’à ce que MIN octets
    ou le nombre d’octets demandés soient disponibles, puis renvoie le
    plus petit de ces nombres.

    * MIN == 0; TIME > 0 : TIME spécifie une limite de temps en dixièmes de
    secondes. Le décompte du temps est démarré lors de l’appel à read(2).
    read(2) retourne si au moins un octet est disponible ou si la tempo‐
    risation expire. Si la temporisation expire sans qu’il n’y ait eu de
    données disponibles, read(2) renvoie 0.

    * MIN > 0; TIME > 0 : TIME spécifie une limite de temps en dixièmes de
    secondes. Quand un premier caractère est disponible en entrée, la
    temporisation est démarrée, puis remise à zéro à chaque caractère
    reçu. read(2) retourne quand le nombre d’octets demandés ou MIN
    octets ont été lus, ou si le délai entre deux octets est dépassé.
    Comme la temporisation n’est démarrée que lors de la réception du
    premier octet, au moins un octet sera lu par read(2).

  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
    Points : 13 008
    Points
    13 008
    Par défaut
    Citation Envoyé par mithraw Voir le message
    m_baudrate = B9600 , c'est la variable définissant le fonctionnement d'un port com en 9600bps
    newtio.c_cc[VTIME] sert de timeout, ici de timeout de réception entre chaque caractère.
    Ok. Alors, tes deux équipements peuvent-ils communiquer par un taux de transfert plus important ? Il me semble qu'on peut monter jusqu'à 115.2 kbps. Existe-t-il un B115200 ?

  5. #5
    Nouveau membre du Club
    Profil pro
    Inscrit en
    janvier 2006
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : janvier 2006
    Messages : 12
    Points : 34
    Points
    34
    Par défaut
    non, ils ne peuvent pas aller plus vite... :/

  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
    Points : 13 008
    Points
    13 008
    Par défaut
    Tu as regardé du côté de la taille des buffers d'émission et de réception : sont-ils adaptés à la taille de tes trames ?

  7. #7
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Je rappelle, au cas où, que 9600 bauds correspondent, en RS-232, à un taux de transfert maximal de 1,171875 ko/s... Et encore, à 8 bits de données, pas de parité, pas de bits de stop en plus. Et sans compter les octets dûs au protocole logique, hors encodage !

    Donc, si tu es vers 1 ko/s de taux de transfert, c'est (hélas) tout à fait normal... Si tu es bien plus bas que ça, il faudra peut-être envisager un thread de gestion, c'est en général ainsi que je procédais pour tenir des taux et une réactivité corrects avec les liaisons série.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  8. #8
    Nouveau membre du Club
    Profil pro
    Inscrit en
    janvier 2006
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : janvier 2006
    Messages : 12
    Points : 34
    Points
    34
    Par défaut
    Merci encore pour vos réponses, c'est vraiment super sympa de m'aider!

    Pour ce qui est des buffers, ils sont corrects, juste suffisant pour envoyer et recevoir les données...
    Pour ce qui est des pertes, j'ai l'impression qu'ils sont due a la gestion des timeout trop large... mais je ne sais pas trop comment l'affiner... sous windows par exemple les timeouts sont en millisecondes, là c'est en dixième de seconde ... :/
    Parce que quand la réponse est de 15 octets, il va attendre 100ms de plus qu'un autre octet n'arrive... hors, il doit y avoir 50% de réponses qui contiennent moins de la taille max (188 octets) ...
    La fonction en question est une fonction bas niveau de mon api de lecture, il est donc difficile pour elle de déterminer ce qu'elle va recevoir ...
    C'est pour ça que je pense qu'il serait mieu de voir du coté des timeout ...

  9. #9
    Membre habitué

    Profil pro
    Inscrit en
    mars 2004
    Messages
    126
    Détails du profil
    Informations personnelles :
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : mars 2004
    Messages : 126
    Points : 127
    Points
    127
    Par défaut
    Salut!

    Je sais pas si ça va t'aider mais j'ai eu l'occasion de travailler sur un projet qui nécessitait l'utilisation d'un port COM sous linux. Bon c'était un projet en Ruby certes mais les quelques suggestions que je pourrais te faire sont p-e adaptables :

    L'émission et la reception de données étaient gérées par un thread. Mieux encore, si mes souvenirs sont bons, la meilleure solution que nous avions trouvé était l'utilisation d'un "select" car sauf erreur, les ports COM sous linux utilisent des fichiers comme buffer (les fameux tty.... me semble-t-il) et le "select" permettait de garder un oeil sur le descripteur de fichier pour guetter toute modification (réception d'un caractère entre autre).

    Ce ne sont que des pistes (que p-e quelqu'un de plus expérimenté pourrait confirmer/infirmer) qui j'espère t'aideront. Je vais essayer de retrouver la doc que j'avais fait pour ce projet voir s'il n'y a pas quelque chose d'utile pour toi dedans.

  10. #10
    Nouveau membre du Club
    Profil pro
    Inscrit en
    janvier 2006
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : janvier 2006
    Messages : 12
    Points : 34
    Points
    34
    Par défaut
    Un select ?
    Ca correspond a un genre de trigger ?

  11. #11
    Membre habitué

    Profil pro
    Inscrit en
    mars 2004
    Messages
    126
    Détails du profil
    Informations personnelles :
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : mars 2004
    Messages : 126
    Points : 127
    Points
    127
    Par défaut
    C'est une fonction de synchronisation qui permet d'attendre un événement (par exemple la réception d'un caractère sur le port COM). J'avais utilisé ça pour un projet. Le select était dans une boucle while infinie (enfin... avec une condition d'arrêt quand même). Et ce while dans un thread. Ainsi, durant toute la durée de vie du thread, le select vérifie la reception de caractères. Il me semble qu'on peut lui dire d'exécuter une fonction à chaque fois qu'il sort de son état d'attente. Une fonction du genre "lecture sur le port COM".

    Encore une fois, si quelqu'un pouvait confirmer ça serait top Que je t'envois pas sur de fausses pistes.

    [EDIT 1] Détail important : l'attente du select est une attente inactive
    [EDIT 2]http://www.linux-kheops.com/doc/man/.../select.2.html

Discussions similaires

  1. Utilisation des ports COM en Java avec RXTX
    Par philippe57460 dans le forum Général Java
    Réponses: 13
    Dernier message: 02/02/2010, 13h18
  2. Besoin d'un tuto pour l'utilisation du port COM
    Par megamario dans le forum VB.NET
    Réponses: 5
    Dernier message: 09/07/2009, 17h25
  3. Utiliser les ports série avec Wine sous linux
    Par JP.NUAGE dans le forum Matériel
    Réponses: 1
    Dernier message: 21/10/2007, 14h12
  4. comment utiliser le port com a mes application?
    Par zakichanedz dans le forum VB 6 et antérieur
    Réponses: 3
    Dernier message: 27/05/2007, 21h03
  5. Utilisation du port COM
    Par chourmo dans le forum Composants VCL
    Réponses: 10
    Dernier message: 13/06/2005, 12h09

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