Problèmes liés à SerialPort Class

J’ai beaucoup de problèmes à essayer d’obtenir un port série pour recevoir le message correct. Il continue à tronquer les messages. Voici mon code et je vais essayer d’élaborer après le code.

public SerialComms(SerialPort sp) { this.sp = sp; this.sp.Open(); this.sp.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived); do { Console.WriteLine("port open waiting message"); Console.ReadKey(); } while(!_terminate); this.sp.Close(); } void sp_DataReceived(object sender, SerialDataReceivedEventArgs e) { ssortingng dataReceived; SsortingngComparer strComp = SsortingngComparer.OrdinalIgnoreCase; SerialPort sp = (SerialPort)sender; int i = sp.BytesToRead; byte[] _byte = new byte[i]; char[] _char = new char[i]; sp.read(_byte, 0, i); dataReceived = Encoding.UTF8.GetSsortingng(_byte); //dataReceived = new ssortingng(_char); //dataReceived = sp.ReadExisting(); if (strComp.Equals("00000000000000"), dataReceived)) _terminate = true; Console.WriteLine(dataReceived); } 

Maintenant, j’ai un projet de test que nous utilisons pour tester nos coms série en production avec des logiciels hérités – je sais que tout se passe bien. J’ai connecté un moniteur série au port et le message qui passe est transmis sans problème. Lorsque j’envoie un message tel que 012345678901234 lors de la première utilisation, il passe généralement très bien et, à la réception, le moniteur l’affiche; Cependant, lorsqu’il imprime sur la console, il est tronqué après le premier message. Je joins des captures d’écran du message transmis sur le moniteur de port et la sortie de la console (le smiley et le cœur affichés sont les octets de préfixe convertis; pourquoi il s’agit d’un coeur et d’un smiley, je n’en ai aucune idée)

Ok, je ne peux donc pas publier l’image car je n’ai pas assez de réputation pour le faire. Je vais écrire à quoi ressemble la sortie sur la console ci-dessous (dans ce cas, le premier message a également été tronqué :()

Sur le moniteur de port série, le message transmis est le suivant (je l’ai envoyé trois fois avec quelques secondes de décalage entre chaque envoi de message):
02 31 32 33 34 35 36 37 38 39 30 31 31 33 33 34 03 .12345678901234.
02 31 32 33 34 35 36 37 38 39 30 31 31 33 33 34 03 .12345678901234.
02 31 32 33 34 35 36 37 38 39 30 31 31 33 33 34 03 .12345678901234.

J’ai reçu sur la console (les caractères et ♥ sont 02 et 03, il s’agit d’un message STX et ETX standard pour nos transmissions):
45123456
78901234 ♥

123
456
7890
123
4 ♥

123
456
7890
123
4 ♥

Ce problème me rend fou !!! S’il vous plaît aider! L’inheritance utilise la version obsolète MSCommLib et nous passons à .Net 4

Ceci est tout à fait normal et courant dans tout protocole de communication. TCP sur un réseau possède également cette propriété. Les octets sont transférés sous forme de stream , pas de paquet de données. Ainsi, lorsque votre gestionnaire d’événements DataReceived est déclenché, vous savez seulement que vous avez des octets disponibles. Il vous appartient d’assembler les octets de réception en une réponse complète avant de la traiter.

Cela nécessite un protocole , un moyen de reconnaître que vous avez une réponse complète. Vous en avez un, ces octets STX et ETX vous le disent. ETX en particulier, le STX est un moyen de filtrer les octets de bruit que vous pourriez obtenir lorsque vous connectez le périphérique.

Un moyen très simple de démarrer consiste à définir la propriété NewLine sur (char)3 et à appeler ReadLine ().

Une meilleure méthode consiste à filtrer le bruit que STX vous aide à éliminer et à éviter les situations de blocage:

 private const int MaxResponse = 42; private const int STX = 2; private const int ETX = 3; private byte[MaxResponse] response; private int responseLength; void sp_DataReceived(object sender, SerialDataReceivedEventArgs e) { var sp = (SerialPort)sender; int cnt = sp.BytesToReceive; for (int ix = 0; ix < cnt; ++ix) { byte b = (byte)sp.ReadByte(); if (responseLength == 0 && b != STX) continue; if (b != ETX) response[responseLength++] = b; else { var str = Encoding.ASCII.GetString(response, 0, responseLength); HandleResponse(str); responseLength = 0; } } } 

Et écrivez la méthode HandleResponse () pour traiter les données que vous avez reçues.

Il existe une combinaison possible de deux problèmes.

Premièrement, une erreur courante lors de l’utilisation de stream est que le simple fait de demander des octets à Read ne signifie pas que Read lira en fait autant d’octets. Il est peu probable que votre problème soit détecté, mais vous devez en être conscient. Voir la réponse à cette question le bon modèle .

Deuxième problème, les stream sont des stream, pas des messages. Il ne sait pas que vous avez envoyé ☺12345678901234♥ , il sait simplement qu’il a reçu ☺123456 entre la dernière fois qu’il a été vérifié et maintenant et qu’il devrait signaler ces informations à l’utilisateur.

Vous devez modifier votre code de lecture pour conserver les données en mémoire tampon jusqu’à ce qu’il reçoive le prochain puis prendre tout le tableau d’octets en mémoire tampon et l’envoyer à l’utilisateur. C’est la raison pour laquelle les et sont envoyés le long du fil, cela permet au récepteur de détecter le moment où il a frappé le début ou la fin d’un message.