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 :

Traitement des données d'un port série


Sujet :

C#

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Décembre 2011
    Messages
    62
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2011
    Messages : 62
    Points : 18
    Points
    18
    Par défaut Traitement des données d'un port série
    Bonjour à tous,

    Je rencontre un soucis au niveau de mon port série. Je suis en train de développer une petite application qui me permet de lire les données d'un chronomètre. Voici mon 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
    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
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
     
    using System;
    using System.Text;
    using System.Drawing;
    using System.IO.Ports;
    using System.Windows.Forms;
    using System.IO;
     
    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            private SerialPort sp = new SerialPort();
            public enum LogMsgType { Incoming, Outgoing, Normal, Warning, Error };
            private Color[] LogMsgTypeColor = { Color.Blue, Color.Green, Color.Black, Color.Orange, Color.Red };
     
            public Form1()
            {
                InitializeComponent();
     
                sp.BaudRate = 9600;
                sp.Parity = Parity.None;
                sp.StopBits = StopBits.One;
                sp.DataBits = 8;
                sp.RtsEnable = true;
                sp.Handshake = Handshake.None;
                sp.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
     
            }
     
            private void button1_Click(object sender, EventArgs e)
            {
                bool erreur = false;
     
                // Si le port est ouvert, il faut le fermer
                if (sp.IsOpen) sp.Close();
                else
                {
                    // Réglage paramètre du port
                    sp.PortName = cmbPortName.Text;
     
                    try
                    {
                        // Ouvrir le port
                        sp.Open();
                    }
                    catch (UnauthorizedAccessException) { erreur = true; }
                    catch (IOException) { erreur = true; }
                    catch (ArgumentException) { erreur = true; }
     
                    if (erreur)
                        MessageBox.Show("Impossible d'ouvrir le port COM. Très probablement, il est déjà en cours d'utilisation, a été supprimé, ou n'est pas disponible.", "COM Port indisponible", MessageBoxButtons.OK, MessageBoxIcon.Stop);
                    else
                        MessageBox.Show("Connexion réussi", "Port disponible");
                }
            }
     
            // Connexion à la fenêtre du terminal
            private void Log(LogMsgType msgtype, string msg)
            {
                rtfTerminal.Invoke(new EventHandler(delegate
                {
                    rtfTerminal.SelectedText = string.Empty;
                    rtfTerminal.SelectionFont = new Font(rtfTerminal.SelectionFont, FontStyle.Bold);
                    rtfTerminal.SelectionColor = LogMsgTypeColor[(int)msgtype];
                    rtfTerminal.AppendText(msg);
                    rtfTerminal.ScrollToCaret();
                }));
     
     
            }
     
            //Convertit un tableau d'octets en une chaîne formatée de chiffres hexadécimaux.
            private string ByteArrayToHexString(byte[] data)
            {
                StringBuilder sb = new StringBuilder();
                foreach (byte b in data)
                    sb.Append(Convert.ToString(b, 16).PadLeft(2, '0').PadRight(3, ' '));
     
                return sb.ToString().ToUpper();
            }
     
            static public string ReverseString(string str)
            {
                char[] charArray = str.ToCharArray();
                Array.Reverse(charArray);
                return new string(charArray);
            }
     
            public static string Reverse(string text)
            {
                string retour = "";
                string[] str = text.Split(' ');
                for (int i = 0; i < str.Length; i++)
                {
                    retour += ReverseString(str[i]);
                    retour += " ";
                }
                return retour;
            }
     
     
     
            public void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
            {
     
                switch (e.EventType)
                {
                    case SerialData.Chars:
                        {
                            // Si le port est ouvert, le fermer
                            if (!sp.IsOpen) return;
     
                            // Obtenir le nombre d'octets en attente dans le tampon du port
                            int bytes = sp.BytesToRead;
                            // Créez une zone tampon (tableau d'octets) pour stocker les données entrantes
                            byte[] buffer = new byte[bytes];
                            // Lire les données du port et de le stocker dans la mémoire tampon
                            sp.Read(buffer, 0, bytes);
     
                            // Montrer à l'utilisateur les données entrantes dans un format hexadécimal
                            Log(LogMsgType.Incoming, ByteArrayToHexString(buffer));
                            string s = Reverse(ByteArrayToHexString(buffer)).Substring(0, 1);
     
                            MessageBox.Show(s);
                            break;
                        }
                    case SerialData.Eof:
                        {
                            sp.Close();
                            break;
                        }
                }
            }
     
        }
    }
    Voici un exemple de ce que je reçois : 60 00 50 00 53 51 80 00 51

    Mon soucis,c'est que je reçois deux MessagesBox avec (si on reprends l'exemple), le 1er MessageBox qui affiche '6' et le second qui affiche '0'. Donc en gros ça me fait deux chaînes :
    chaîne1 = 60 et chaîne2 = 00 50 00 53 51 80 00 51
    Alors qu'en fait j'aimerais obtenir qu'une seule chaîne concaténant la chaîne1 et la chaîne2
    Du coup, je comprends pas pourquoi j'obtiens ce résultat

    Je vous remercie d'avance

  2. #2
    Membre éclairé
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2011
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2011
    Messages : 610
    Points : 713
    Points
    713
    Par défaut
    Hello,

    Il te sert a quoi ton substring()??
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    string s = Reverse(ByteArrayToHexString(buffer)).Substring(0, 1);

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Décembre 2011
    Messages
    62
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2011
    Messages : 62
    Points : 18
    Points
    18
    Par défaut
    J'aimerais récupérer la première valeur reçue. Si on prends l'exemple que j'ai donné, ici, ça serai '6'

  4. #4
    Membre éclairé
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2011
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2011
    Messages : 610
    Points : 713
    Points
    713
    Par défaut
    Mais quel est l'utilité? Parce que je ne comprend rien de ce que tu as expliquer en dessous:
    Citation Envoyé par Narizuke Voir le message
    Mon soucis,c'est que je reçois deux MessagesBox avec (si on reprends l'exemple), le 1er MessageBox qui affiche '6' et le second qui affiche '0'. Donc en gros ça me fait deux chaînes :
    chaîne1 = 60 et chaîne2 = 00 50 00 53 51 80 00 51
    Alors qu'en fait j'aimerais obtenir qu'une seule chaîne concaténant la chaîne1 et la chaîne2
    La chaîne que tu reçois correspond à ta recherche non?? Quel est donc l'utilité de la découper si tu la veux entière???

  5. #5
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 174
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 174
    Points : 25 115
    Points
    25 115
    Par défaut
    la lecture de données sur un port série est plus compliqué
    une trame peut etre découpée, et donc lever plusieurs évènements
    de plus s'il y a des parasites les octets peuvent être faussés
    rajouté à celà que si 2 trames arrivent alors que tu n'as pas encore lu les octets, il faut savoir où les données s'arrêtent

    en général il y a un caractère de début et/ou de fin de trame, et un checksum pour vérifier que la trame est utilisable
    voir avec la doc du chrono donc ...

    après c'est à toi de découper tout ca

  6. #6
    Membre à l'essai
    Profil pro
    Inscrit en
    Décembre 2011
    Messages
    62
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2011
    Messages : 62
    Points : 18
    Points
    18
    Par défaut
    Pol63, tu viens de me perdre là

    FrameBreak : je te l'a refais.
    Justement, je ne la veux pas en entière puisque j'aimerais la découper pour obtenir quelques choses dans ce genre :
    string s1 = 6;
    string s2 = 0005;
    string s3 = 00053518;
    string s4 = 0005 ;
    string s5 = 1;

    Mais si j'ai bien compris ce que m'a expliqué Pol63, ma trame aurait été découpée c'est donc pour ça que je reçois deux chaînes. Et je n'en veux pas deux, j'en voudrais une que je découpe comme je l'ai dis plus haut.

    J'ai mis deux screen de ce que j'obtiens. Ce qui est dans ma richtextbox c'est ma trame en entière (cf. capture2) mais quand je fais un subtring(0,1), j'obtiens une MessageBox avec la valeur '6' (cf. capture) et une autre avec la valeur '1' (cf. capture2). Et quitte à me répéter, j'aimerais avoir que la première MessageBox.
    Images attachées Images attachées   

  7. #7
    Membre éclairé
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2011
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2011
    Messages : 610
    Points : 713
    Points
    713
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    string s = Reverse(ByteArrayToHexString(buffer));
    string ch1 = s.Substring(0, 1);
    string ch2 = s.Substring(1, 4);
    string ch3 = s.Substring(5, 8);
    string ch3 = s.Substring(13, 4);
    string ch3 = s.Substring(17, 1);
    Ca devrait marcher si la longueur de ta chaîne est fixe

    Edit : Je viens de voir que ce problème est déjà en cours sur le forum, donc que ta chaîne n'est pas fixe

  8. #8
    Membre à l'essai
    Profil pro
    Inscrit en
    Décembre 2011
    Messages
    62
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2011
    Messages : 62
    Points : 18
    Points
    18
    Par défaut
    Déjà essayer et malheureusement ça ne me la découpe pas comme je souhaite. Logique puisque ma trame d'après Pol63 est découpée.
    Il faudrait que je puisse récupérer ma trame en entière, du coup, je cherche un moyen pour le faire mais sachant que je suis que débutant dans la lecture des ports séries, je pense que je vais bien galérer.

  9. #9
    Membre éclairé
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2011
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2011
    Messages : 610
    Points : 713
    Points
    713
    Par défaut
    Citation Envoyé par Pol63 Voir le message
    En général il y a un caractère de début et/ou de fin de trame, et un checksum pour vérifier que la trame est utilisable
    voir avec la doc du chrono donc ...
    Pol63 a tout à fait raison, si ta trame n'est pas fixe c'est qu'il y a dans ta trame des règles pour la découper
    La doc devrait t'aider...

  10. #10
    Membre éclairé
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2011
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2011
    Messages : 610
    Points : 713
    Points
    713
    Par défaut
    J'ai retrouver ta doc, ce n'est pas si compliqué que ca:
    - Tu as 7 chaines différentes (qui inclura 7 découpages différents)
    - Tu peux différencier la chaîne grâce au premier chiffre (ici 6) donc tu sait grâce à ta doc que la longueur de ta chaîne vaut 18, dans le cas ou le premier nombre est '5' ta longueur sera de 6 caractères.
    - Il te reste seulement à découper la chaîne selon les indication :
    --- Place : 4
    --- Heure : 2
    --- Min : 2
    --- Seconde : 4
    --- BIB : 4
    --- Lane : 1
    Si tu comptabilise cela correspond à 18 si tu ajoute le premier caractère '6' qui te permet de savoir le découpage.

    Donc un switch avec 7 cas, et une fonction de découpage pour chaque trame

    Edit: l'adresse de la doc http://www.developpez.net/forums/att...exte/scan.jpg/

  11. #11
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 174
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 174
    Points : 25 115
    Points
    25 115
    Par défaut
    dans la majorité des cas la trame ne sera pas découpée et ne posera pas de soucis
    la doc n'a pas l'air d'avoir de checksum ou autre système de vérification d'erreur (hormis des plages définis, si tu recois 0A alors qu'il faut 00 à 99 c'est que la trame s'est fait parasitée, mais dans d'autres cas tu ne détecteras pas de parasitage)

    la doc est pas super explicite mais si j'ai bien compris, le 1er caractère te permet de connaitre le type de trame envoyé
    chaque type de trame a l'air d'avoir une taille fixe, il est donc possible de coder le découpage et le décodage facilement

  12. #12
    Membre à l'essai
    Profil pro
    Inscrit en
    Décembre 2011
    Messages
    62
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2011
    Messages : 62
    Points : 18
    Points
    18
    Par défaut
    FrameBreak j'ai bien compris le système de découpage de ma trame. Chaque type de message a une longueur différente.
    Mais comme je l'ai dis, pour moi les ports séries et tout le traitement qu'il y a derrière c'est tout nouveau pour moi.
    chaque type de trame a l'air d'avoir une taille fixe, il est donc possible de coder le découpage et le décodage facilement
    Oui mais justement comment faire pour coder le découpage ? Je sèche totalement.Et quand je veux récupérer le 1er caractère j'ai le soucis dont je vous ai expliqué.

    J'ai essayé de faire ceci pour récupérer la première valeur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     byte msgType = (byte)(buffer[0] & (0x0F));
    mais toujours le même soucis

    Et juste une question comme ça, est-il préférable que je travaille directement avec la chaîne que je reçois ? ou faut-il que je travaille directement sur le buffer ?

  13. #13
    Membre éclairé
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2011
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2011
    Messages : 610
    Points : 713
    Points
    713
    Par défaut
    Je ne vois pas le rapport entre le port série et le découpage
    Tu extrais le buffer que tu convertira en hexa dans une chaîne.
    Puis tu extrais par un substring le premier caractère de la chaîne.
    Ensuite tu appel une fonction qui aura pour argument carac ( le premier caractère) et string hex (ta chaîne entière converti en hexa).
    Dans ta fonction tu met un switch avec 7cas (tes 7 trames différentes).
    Carac te permetra de choisir le cas qui aura la bonne méthode pour découper ta trame hex...
    Voila

  14. #14
    Membre à l'essai
    Profil pro
    Inscrit en
    Décembre 2011
    Messages
    62
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2011
    Messages : 62
    Points : 18
    Points
    18
    Par défaut
    Voici ce que j'ai 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
    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
     
     public void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
            {
                if (e.EventType == SerialData.Chars)
                {
                    // Si le port est ouvert, le fermer
                    if (!sp.IsOpen) return;
     
                    // Obtenir le nombre d'octets en attente dans le tampon du port
                    int bytes = sp.BytesToRead;
                    // Créez une zone tampon (tableau d'octets) pour stocker les données entrantes
                    byte[] buffer = new byte[bytes];
     
                    // Lire les données du port et de le stocker dans la mémoire tampon
                    sp.Read(buffer, 0, bytes);
     
                    // Montrer à l'utilisateur les données entrantes dans un format hexadécimal
                    Log(LogMsgType.Incoming, Reverse((ByteArrayToHexString(buffer))));
                    //MessageBox.Show(msgType.ToString());
     
                    string chaine = Reverse((ByteArrayToHexString(buffer)));
                    string mType = Reverse((ByteArrayToHexString(buffer))).Substring(0,1);
     
                    Decoupe(mType, chaine);
                }
     
            }
     
            public void Decoupe(string car, string hexa)
            {
                switch (car)
                {
                    case "0" :
                        MessageBox.Show("0"); // A remplacer par le découpage
                        break;
                    case "1": 
                        MessageBox.Show("1");// A remplacer par le découpage
                        break;
                    case "2":
                        MessageBox.Show("2");// A remplacer par le découpage
                        break;
                    case "3": 
                        MessageBox.Show("3");// A remplacer par le découpage
                        break;
                    case "4": 
                        MessageBox.Show("4");// A remplacer par le découpage
                        break;
                    case "5":
                        MessageBox.Show("5");// A remplacer par le découpage
                        break;
                    case "6":
                        MessageBox.Show("6");// A remplacer par le découpage
                        break;
     
                }
            }
    Mais toujours impossible de récupérer ma trame en entière malgré que je fasse ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    string chaine = Reverse((ByteArrayToHexString(buffer)));
    Je réédite ma question de tout à l'heure :
    est-il préférable que je travaille directement avec la chaîne que je reçois ? ou faut-il que je travaille directement sur le buffer ?

  15. #15
    Membre à l'essai
    Profil pro
    Inscrit en
    Décembre 2011
    Messages
    62
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2011
    Messages : 62
    Points : 18
    Points
    18
    Par défaut
    En faisant ceci dans ma fonction Decoupe()

    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
     
    case "6":
                        string Place = hexa.Substring(1,4);
                        textBox1.Invoke(new EventHandler(delegate
                        {
                            textBox1.SelectedText = string.Empty;
                            textBox1.AppendText(Place);
                            textBox1.ScrollToCaret();
                        }));
     
                        string temps = hexa.Substring(5, 8);
                        textBox2.Invoke(new EventHandler(delegate
                        {
                            textBox2.SelectedText = string.Empty;
                            textBox2.AppendText(temps);
                            textBox2.ScrollToCaret();
                        }));
     
                        string BIB = hexa.Substring(13,4);
                        textBox3.Invoke(new EventHandler(delegate
                        {
                            textBox3.SelectedText = string.Empty;
                            textBox3.AppendText(BIB);
                            textBox3.ScrollToCaret();
                        }));
     
                        string Lane= hexa.Substring(17,1);
                        textBox4.Invoke(new EventHandler(delegate
                        {
                            textBox4.SelectedText = string.Empty;
                            textBox4.AppendText(Lane);
                            textBox4.ScrollToCaret();
                        }));
                        break;
    Voici l'erreur que j'obtiens :
    L'index et la longueur doivent faire référence à un emplacement situé dans la chaîne.

Discussions similaires

  1. [Embarqué] Lire des données par le port série (Qt ExtSerialPort) sans fausse mesure
    Par Jugulaire dans le forum Plateformes
    Réponses: 1
    Dernier message: 01/04/2015, 09h22
  2. [WD 9] traiter des données provenant du port série
    Par kouki507 dans le forum WinDev
    Réponses: 2
    Dernier message: 13/12/2007, 19h00
  3. Envoyer des données sur le port série
    Par jbidou88 dans le forum Flash
    Réponses: 3
    Dernier message: 18/09/2006, 11h33
  4. [javax.comm] Envoyer des données sur le Port série
    Par deuspi dans le forum Applets
    Réponses: 2
    Dernier message: 29/08/2006, 09h40

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