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 la réponse d'une demande MODBUS/JBUS en C


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé

    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    532
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2011
    Messages : 532
    Par défaut Récupérer la réponse d'une demande MODBUS/JBUS en C
    Bonjour a toutes et tous,

    Je souhaite solliciter votre aide pour de la communication série en C. J'ai écris un programme en C qui me permet de réaliser la communication en série (protocole MODBUS/JBUS) entre une carte d'entrées/sorties et mon PC (je travail sous linux Ubuntu et j'utilise eclispe comme environnement de développement).

    Pour définir ma communication série, j'utilise la structure termios utilisée dans la fonction suivante:
    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
     
    int configurationPort()
    {
        int port_serie;
        struct termios options;
     
        port_serie = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);//lecture et ecriture | pas controlling terminal | ne pas attendre DCD
     
        //cas d'erreur d'ouverture
        if(port_serie < 0)
        {
            perror("Erreur d'ouverture du port serie");
            exit(-1);
        }
     
        else
        {
            printf("Port serie numero %d bien ouvert. \n", port_serie);
     
            //chargement des données
            tcgetattr(port_serie, &options);
            //B38400 bauds
            cfsetospeed(&options, B38400);
            options.c_cflag |= (CLOCAL | CREAD);//programme propriétaire du port
            //structure en 8N1 !!
            options.c_cflag &= ~PARENB; //pas de parité
            options.c_cflag &= ~CSTOPB; // 1 bit de stop
            options.c_cflag &= ~CSIZE; //option a 0
            options.c_cflag |= CS8; //8 bits
            tcsetattr(port_serie, TCSANOW, &options); //enregistrement des valeurs de configuration
            printf("Configuration OK strcuture en 8N1 !. \n");
        }
        printf("DEBUG: fin configuration port\n");
        return(port_serie);
    }
    J'ai écris une nouvelle fonction dans laquelle je demande de lire n mots à à partir de l'adresse 0:
    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
     
    void lectureSortiesTOR(int port)
    {
        /*=========================================
         * Description : Formate la trame ModBus et envoi la trame creee
         *=========================================*/
     
        int nombreOctetsEcris;                              // variable de vérification pour l'écriture sur le port
     
        char bufferEmissionModBus[8];
     
     
        bufferEmissionModBus[0] = 2;
        bufferEmissionModBus[1] = 4;
        bufferEmissionModBus[2] = 0 / 256;
        bufferEmissionModBus[3] = 0 & 255;
        bufferEmissionModBus[4] = 0 / 256;
        bufferEmissionModBus[5] = 9 & 255;
     
     
        addCRC16(bufferEmissionModBus, 8 - 2);  // ajout du CRC sur les deux derniers octets du tableau 'bufferEmissionModBUS'
     
        nombreOctetsEcris = write(port, bufferEmissionModBus, 8);  // écriture sur le port série
        printf("DEBUG: nombre octets ecris = %d\n", nombreOctetsEcris);
        if (nombreOctetsEcris < 0)
        {
            perror("ERROR\n");
            printf("DEBUG: visualisation d'une erreur\n");
        }
        printf("DEBUG: Envoie Termine.\n");
     
    }
    et dans mon programme main, voici ce que je fais:
    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
     
    int main(void)
    {
        int port_serie;
     
        printf("DEBUG: Lancement du programme\n");
     
        initialisation();
        printf(flagComStarted ? "DEBUG: true\n" : "DEBUG: false\n");
        port_serie = configurationPort();
     
     
        while(1)
        {
            sleep(1);
            lectureSortiesTOR(port_serie);
            printf("Boucle lectureSortiesTOR");
     
        }
        return(0);
    }
    (la fonction initialisation n'a aucune incidence sur la communication série, c'est pour cela que je n'en parle pas). Maintenant,ce que je veux faire et c'est là que j'ai un problème, c'est que je veux récupérer dans un tableau la réponse de la demande faite en MODBUS/JBUS.

    J'ai trouvé sur internet une fonction qui utilise le read:
    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
     
    void onDataAvailable(int port)
    {
    /*=========================================
     * Description : Lecture du port série
     *=========================================*/
        int reception;
        char buffer[23] = "";
     
        printf("Lecture des donnees en cours ... \n");
        fcntl(port,F_SETFL,10);//mode bloquant pour la fonction read() si aucun caractere dispo, programme attend
     
        reception = read(port, buffer, 23);//buffer contitendra les données, 23 est le nombre d'octets a copier dans cet espace
        printf("message recu : %s\n",buffer);
     
        if(reception == -1)
        {
            printf("DEBUG: Erreur lecture\n");
        }
        else
        {
            printf("DEBUG: Reception finie\n");
        }
    }
    Donc je voulais savoir si cette fonction peut marcher pour récupérer la réponse de ma demande MODBUS/JBUS et je voulais savoir aussi à quelle moment je dois l'utiliser parce que j'ai un gros doute là dessus.

    Merci d'avance pour vos réponses,

    Cordialement

  2. #2
    Membre très actif

    Femme Profil pro
    Collégien
    Inscrit en
    Juillet 2010
    Messages
    592
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Afghanistan

    Informations professionnelles :
    Activité : Collégien

    Informations forums :
    Inscription : Juillet 2010
    Messages : 592
    Par défaut
    Bonjour

    Effectivement c'est read qu'il faut utiliser, mais pas comme ça.
    Read va lire un nombre de byte inférieur ou égale ou nombre demandé.
    Exemple si tu veux en lire 10 et qu'il n'y en a que 3 de disponibles read te renvoie 3

    Tu peux faire un truc du genre:
    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
     
     
    char buffer[BUFFER_SIZE]
    int n = 0;
    int nlus;
     
     
    while( n < N_ OCTETS_NECESSAIRE_POUR_TRAITER_LA_TRAME)
    {
     
        if((nlus = read(port,&buffer[n],BUFFER_SIZE-n)) > 0)
        {   /* lecture de nlus octets => incrément de l'index du buffer*/
            n += nlus;
        }
        else if(nlus <0)
        {
            /* traiter error de lecture*/
        }
        else
        {
            /* nlus == zero , pas de donnees disponibles..*/
     
        }
    }
     
    traiter_trame(buffer);

  3. #3
    Membre éclairé

    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    532
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2011
    Messages : 532
    Par défaut
    J'ai un peux modifier ma fonction onDataAvailable en ajoutant une boucle for dans le cas ou j'ai bien reçu un message où je fais un printf de mon buffer où j'ai stocké mon message:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    if(reception == -1)
        {
            printf("DEBUG: Erreur lecture\n");
        }
        else
        {
            printf("DEBUG: Reception finie\n");
            for(i = 0; i < 23; i++)
            {
                  prinft("DEBUG: buffer[%d] = %d, i, buffer[i];
            }
        }
    du coup si j'ai bien compris, dans mon for, au lieu de faire i < 23 je pourrait faire i < reception pour afficher bien la taille de la réponse reçu si elle est plus courte que la taille de buffer ?

    Autre question: dois-je penser à remettre a 0 mon buffer après l'affichage pour plus de sécurité ou n'est-ce pas nécessaire ???

  4. #4
    Membre éclairé

    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    532
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2011
    Messages : 532
    Par défaut
    Je reviens sur ce topic pour dire que j'ai un peu progresser vu que j'arrive a utiliser le read, mais j'ai encore un problème toujours lier au read.

    Dans la communication série, en protocole MODBUS/JBUS j'envois ce type de demande pour lire N mots de 2 octets: 02 04 00 00 00 09 30 3F
    Grâce au logiciel CommTools, je visualise mes trames MODBUS et voici un exemple de réponse que je reçois suite à ma demande: 02 04 12 00 00 00 FF 2A BC 14 5A 0E F6 00 0A 00 01 00 E7 00 01 F7 DE (cet exemple de réponse est valide, c'est bien ce que je veux)


    Maintenant, lorsque je veux récupérer cette réponse avec mon read, j'ai un problème: il coupe la réponse en 2 morceaux. Je m'explique: je fais un write et derrière je fais un read (normalement c'est logique) et j'affiche dans ma console mon buffer (d'une taille de 23 vu que je m'attends à une réponse de 23 octets), or je reçoit un premier morceau avec: 02 12 00 00 00 FF 2A BC 14 5A 0E F6 (on remarque je le 04 en deuxième position a disparu) puis je refais un write / read et je reçois mon second morceau: 00 0A 00 01 00 E7 00 01 F7 DE. Donc si je veux avoir les trames "complètes" actuellement je dois faire write / read / read

    Donc pouvez-vous me dire d'où peut venir ce problème svp

  5. #5
    Membre très actif

    Femme Profil pro
    Collégien
    Inscrit en
    Juillet 2010
    Messages
    592
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Afghanistan

    Informations professionnelles :
    Activité : Collégien

    Informations forums :
    Inscription : Juillet 2010
    Messages : 592
    Par défaut
    N’essaie pas de traiter la trame tant que tu n'as pas reçu le nombre de caractère espérés.
    Voir mon premier post.

  6. #6
    Membre éclairé

    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    532
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2011
    Messages : 532
    Par défaut
    Citation Envoyé par mith06 Voir le message
    N’essaie pas de traiter la trame tant que tu n'as pas reçu le nombre de caractère espérés.
    Voir mon premier post.
    Est-ce que tu peux m'expliquer comment fonctionne ton code parce que j'ai du mal a comprendre svp ???

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

Discussions similaires

  1. Réponses: 1
    Dernier message: 03/02/2015, 12h17
  2. Récupérer la réponse d'une adresse HTTP
    Par Davesique dans le forum Général Java
    Réponses: 25
    Dernier message: 22/06/2013, 15h18
  3. [Prototype] [AJAX] Récupérer la réponse / Lancer une fonction
    Par Shirraz dans le forum Bibliothèques & Frameworks
    Réponses: 9
    Dernier message: 07/04/2009, 06h50
  4. Récupérer la réponse d'une console DOS
    Par twixi dans le forum VB.NET
    Réponses: 3
    Dernier message: 21/07/2008, 05h19

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