C# de série du problème de port - trop simple à l'échec, mais
Ok, ce doit être la saleté simple. Je suis en train de lire charactes à partir d'un périphérique série. C'est que si j'envoie un caractère d'espace, il les échos de retour d'une chaîne de chiffres et de fin de vie. C'est tout.
Je suis à l'aide de l'Unité 3.3 (.Net 2.0), et le "port série" est une série Prolifique à l'adaptateur USB. BTW: l'Utilisation d'Hyperterminal, tout fonctionne parfaitement, donc je sais que ce n'est pas de pilote ni de matériel.
Je peux ouvrir le port sur ok. Il semble que je peux envoyer mon espace avec le port.Write(" "); Mais même si je l'ai ESSAYER d'appeler ReadChar, ReadByte, ou ReadLine (comme d'interrogation), il se fige jusqu'à ce que je débranchez le câble USB, et ma sortie de la console ne montre rien (exceptions ont été pris).
Ainsi, au lieu-je configurer un DataReceviedHandler, mais il n'est jamais appelé.
J'ai lu quelques posts où les gens ont fait ce genre de chose avec des Arduinos etc. (ce n'est pas un Arduino mais bon), en utilisant rien de plus que de ReadLine. Leur code ne fonctionne pas pour moi (et pas de réponses, donc loin de ces auteurs).
Donc, des conseils? Dois-je utiliser un autre thread? Si vous connaissez n'importe quelle Unité (Mono) de codage, des conseils, le long de ces lignes grandement apprécié.
Ce code un mashup de http://plikker.com/?p=163 et http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.datareceived.aspx#Y537
using UnityEngine;
using System.Collections;
using System.IO.Ports;
using System;
public class SerialTest : MonoBehaviour {
SerialPort stream;
void Start () {
try {
stream = new SerialPort("COM3", 9600);
stream.Parity = Parity.None;
stream.StopBits = StopBits.One;
stream.DataBits = 8;
stream.Handshake = Handshake.None;
stream.DataReceived += new SerialDataReceivedEventHandler(DataReceviedHandler);
stream.Open();
Debug.Log("opened ok"); //it DOES open ok!
} catch (Exception e){
Debug.Log("Error opening port "+e.ToString()); //I never see this message
}
}
void Update () { //called about 60 times/second
try {
//Read serialinput from COM3
//if this next line is here, it will hang, I don't even see the startup message
Debug.Log(stream.ReadLine());
//Note: I've also tried ReadByte and ReadChar and the same problem, it hangs
} catch (Exception e){
Debug.Log("Error reading input "+e.ToString());
}
}
private static void DataReceviedHandler(
object sender,
SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender; //It never gets here!
string indata = sp.ReadExisting();
Debug.Log("Data Received:");
Debug.Log(indata);
}
void OnGUI() //simple GUI
{
//Create a button that, when pressed, sends the 'ping'
if (GUI.Button (new Rect(10,10,100,20), "Send"))
stream.Write(" ");
}
}
Le Code a été ajouté.
Pouvez-vous essayer dans l'autre sens, pouvez-vous vérifier que votre programme peut effectivement envoyer les choses à partir de ce port?
À l'aide de Serial Port Monitor, comme dirait ma 'ping' caractères pour obtenir envoyé, ou au moins SPM voit. Mais pas de données. Je l'ai fait avec Hyperterminal et il semble similaire, sauf que les données. Quelle est la diff? Quelqu'un sait comment lire les journaux?
Maintenant que vous avez posté votre code: Pourquoi avez-vous lu à partir du port série dans la méthode de mise à Jour, et pourtant s'attendre à voir quelque chose dans le gestionnaire d'événement? Est mise à Jour appelée 60 fois par seconde, même si le dernier appel n'a pas fini? Cela fonctionne si vous désactivez la mise à Jour de boucle? Et enfin, avez-vous essayer avec la plaine .NET sur Windows, juste pour être sûr?
OriginalL'auteur Dave | 2011-04-20
Vous devez vous connecter pour publier un commentaire.
Assurez-vous que vous êtes à l'ouverture du port de droite, à l'aide de paramètres corrects. Voici un exemple de comment vous pouvez le configurer:
Je recommande l'open source RealTerm terminal, il dispose d'un riche ensemble de fonctionnalités et peut vous aider à déboguer. Essayez d'écrire un octet manuellement à l'aide de ce logiciel, et si cela fonctionne, alors le problème est dans votre programme. Autrement, cela pourrait être un problème de pilote (mais plus probablement il ne l'est pas).
[Modifier]
Appel
SerialPort.ReadLine
est en fait censé bloquer le thread jusqu'à ce queSerialPort.De retour à la ligne
est reçu. AussiReadChar
etReadByte
va s'accrocher jusqu'à ce qu'au moins un octet est reçu. Vous devez vous assurer que vous êtes en train de recevoir des caractères de l'autre côté, et vous ne serez pas les recevoir si votre application est bloquée et ne peut pas envoyer de l'espace.Depuis je n'ai jamais utilisé l'Unité, je ne suis pas sûr de savoir comment
Update
est appelé, mais je suis en espérant qu'il a tiré sur un thread de premier plan à intervalles réguliers (sinon, votre application ne serait pas de gel).L'exemple que vous avez lié (Arduino et de l'Unité exemple) montre que l'Arduino envoie les données en permanence, et c'est pourquoi leur
Update
méthode est constamment à la réception de données (pas de caractère d'espace doit être envoyé vers le périphérique). Si ils débranchez le périphérique, leur application se bloque tout aussi bien.Bien, peut-être pas, parce que dans .NET 1.1, la valeur par défaut pour
ReadTimeout
n'était pas infini, comme il est .NET 2.0.Donc, ce que vous pouvez faire est:
un. Définir la
ReadTimeout
de la propriété à une valeur raisonnable. Par défaut .NET 2.0 est InfiniteTimeout, qui ne répondent pas à vos besoins. Inconvénients: méthode de mise à jour va quand même s'accrocher un moment sur chaque appel, mais pas à l'infini.b. Quelqu'un a dit que les événements ne sont pas mises en MONO SerialPort, donc je suppose que l'aide
DataReceived
seulement n'est pas une option.c. Déplacez votre l'envoi de la logique à la
Update
méthode également, de sorte que vous n'avez pas de lire des données à tous, jusqu'à ce qu'il est temps de le lire:Noter que, si votre appareil n'est pas de l'envoi des données, il permet également de bloquer à
stream.ReadLine()
, donc assurez-vous que votreReadTimeout
est défini à une valeur raisonnable. Vous voudrez aussi pour arrêter l'envoi à un certain point, mais je vous laisse à vous.d. Envoyer de l'espace dans
OnGui
comme vous le faites maintenant, mais toujours vérifier s'il existe des données dans votre mémoire tampon avant de le lire:Avertissement: ceci est directement hors de ma tête, pas testé, donc il peut y avoir quelques erreurs de syntaxe qui, je suis sûr que vous allez gérer.
Ok, essayé cela, mais il n'aime pas DiscardNull ni ReceivedBytesThreshold (je suis sur .NET 2.0), a commenté ces. Toujours pas de travail.
ReceivedBytesThreshold et DiscardNull en fait, existent .NET 2.0, vouliez-vous dire .NET 1.1? Mais leurs valeurs par défaut sont en fait
1
etfalse
, de sorte qu'il n'a pas d'importance (j'ai juste copié d'un ancien projet sans vérifier).Merci pour le modifier! Je suis en fait à l'aide de l'Unité (3.3), qui utilise Mono (2.6.3) et .NET 2.0. À l'aide de MonoDevelop j'ai mis un point d'arrêt après le port est ouvert pour voir ce qu'il en est, et le débogueur lui-même dit que certaines de ces choses n'ont pas d'objet valide, ou quelque chose comme ça. J'ai pensé que bizarre pour des choses qui devraient être des chiffres ou des morceaux. J'ai essayé de lecture BytesToRead mais il n'a pas fait non plus (message d'erreur quand je rentre à ma machine de dev)
À l'aide de court délai, suppléant du fil, et d'envoyer le "ping" souvent, également de réglage de Saut de ligne à l'excentrique inverse de la chaîne de cette chose a de, le tout enveloppé. Merci beaucoup pour votre aide. Tout le monde.
OriginalL'auteur Groo
Événements ne sont pas mises en Mono
SerialPort
classe, de sorte que vous ne recevrez pas de notifications, vous avez à effectuer (blocage) lire explicitement. Autre problème possible - je ne suis pas sûr de la façon de l'Unité des Comportements de travail, êtes-vous certain que toutes les méthodes d'accès à laSerialPort
sont invoquées sur le même thread? Et vous n'êtes pas débarrassez-vous du port de l'objet, cela peut aussi causer des problèmes.Exactement, et le détail des différences entre C# et Mono mise en œuvre de SerialPort est décrit ici : mono-project.com/archived/howtosystemioports/#limitations
OriginalL'auteur skolima
Peut-être que votre problème est la configuration du port série. Il est important non seulement pour vérifier la vitesse de transmission ou d'Arrêt. Aussi, vous devez configurer le signal DTR, RTS, poignée de main, tout. C'est aussi une cause importante peut-être un autre programme moches, les valeurs et la configuration doit être explicitement défini à chaque démarrage ou de certains paramètres de la connexion ancienne vous des ennuis.
Aussi peut-être de prendre un coup d'oeil dans l'un de ces outils:
Ils peuvent vous aider à talon de votre interface série ou de prendre un regard plus profond dans la connexion. Aussi peut-être essayer d'en parler à votre série de l'appareil en utilisant HyperTerminal ou tout autre outil qui est prouvée à travailler.
À l'aide de Serial Port Monitor, comme dirait ma 'ping' caractères pour obtenir envoyé, ou au moins SPM voit. Mais pas de données. Je l'ai fait avec Hyperterminal et il semble similaire, sauf que les données. Diff est HypTerm "set actuel masque d'événement' (??) et l'envoyé caractères sont des enfants de (précédé?) D'attente pour l'événement " et IRP_MJ_READ (puis il écrit mon ping char), puis IRP_MJ_READs dans les parages et là, les données sont. Comment puis-je obtenir que cela se produise dans mon code?
OriginalL'auteur Oliver
Eu le même problème avec Mono, mise à niveau 2.6.7 aidé.
Découvert l'Unité est 2.6.3 🙁
Il a été 2.6.3 2.6.4. Eh bien, de ne pas être mis à niveau de l'Unité? Peut-être que vous devriez le contacter.
OriginalL'auteur konrad.kruczynski
Ne pas mélanger les données de l'événement et le blocage de la lecture. Qu'attendez-vous de se produire si les données arrivent? Que la lecture de la méthode et de l'événement devrait obtenir les mêmes données reçues?
Vous devriez aussi lire sur le sujet:
Petit port série tutoriel décrivant tous les états: http://www.wcscnet.com/Tutorials/SerialComm/Page1.htm
OriginalL'auteur jgauffin