Comment puis-je envoyer des octets à un périphérique série en C#?
J'ai un appareil qui utilise de série (via un adaptateur USB) à l'interface avec mon PC. Je vais avoir de réelle difficulté à la faire jouer gentiment en C#. Je sais qu'il fonctionne correctement parce que le fournisseur du logiciel se comporte comme prévu. Je sais aussi que je suis capable de recevoir des données à l'aide de mon code grâce à un mode de test qui envoie à plusieurs reprises "OK".
Voici mon code:
private SerialPort port;
public SerialConnection()
{
this.port = new SerialPort("COM3", 38400, Parity.None, 8, StopBits.One);
this.port.WriteTimeout = 2000; port.ReadTimeout = 2000;
this.port.Open();
this.port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
}
public void SendCommand(byte[] command)
{
this.port.Write(command,0,command.Length);
string chars = "";
foreach (byte charbyte in command) chars += (char)charbyte;
Console.WriteLine(" -> " + chars);
}
void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
string data = this.port.ReadLine();
Console.WriteLine(" <- " + data);
}
Pour le moment je suis en utilisant un autre mode de test qui est censé faire écho à tout ce qu'il reçoit. En conséquence, je suis d'appeler SendCommand avec les octets suivants:
byte[] {
0x50,
0x69,
0x6E,
0x67
}
Mais rien ne semble l'avoir envoyé.
Je n'ai aucune idée de ce à essayer ensuite. Quelqu'un a des suggestions?
Pour une question subsidiaire, j'ai posté quelques PortMon journaux. Je pense qu'ils pourraient être utiles ici aussi, donc, ici, ils sont:
- Les fournisseurs de logiciel - avec tous les
IOCTL_SERIAL_GET_COMMSTATUS
entrées filtrées - Mon orteil-dip tentative
Merci Brad. J'ai essayé et trouvé qu'il n'est pas envoyer quoi que ce soit de retour. Il est d'une grande utilité.
Vous devriez lire plus sur le protocole à la main. Je soupçonne que vous manque quelque chose. Si il est utile pour vous, utilisez utilitaire de même avec le logiciel de l'appareil est venu avec, et de comparer vos données. Si vous envoyez exactement les mêmes commandes, puis vérifier l'état des lignes et assurez-vous qu'ils sont les mêmes aussi.
Je ne sais pas pourquoi je n'ai pas essayer d'espionnage sur la condition d'application avant, mais quand je le fais, il semble être en utilisant les mêmes séquences d'octets que j'utilise. J'ai essayé de l'inspection de la configuration des broches, mais à l'aide de la
table
vue de l'serial port monitor est apparemment un moyen infaillible de se planter mon PC.assurez-vous de débrancher le logiciel de surveillance avant de fermer les programmes qui accèdent au port série, ou de débrancher l'adaptateur série. Il y a un logiciel similaire disponible... peut-être Franson vous donnera gratuitement un essai: franson.com/serialtools En tout cas, je soupçonne que votre statut de lignes doivent être définis.
OriginalL'auteur Tom Wright | 2011-03-31
Vous devez vous connecter pour publier un commentaire.
Chaque RS-232 appareil a besoin d'utiliser une sorte de contrôle de flux mécanisme pour informer la partie opposée en cours de communication. Il existe trois mécanismes de base:
(démarrer la mise à jour)
Initiale de la longueur des files d'attente et les délais d'attente dans l'héritage de l'app:
alors que vous n'avez pas à les définir. Essayez de définir les tailles de file d'attente à l'aide de
SerialPort.WriteBufferSize
etSerialPort.ReadBufferSize
. De même, définir les délais à l'aide deSerialPort.ReadTimeout
etSerialPort.WriteTimeout
.(mise à jour)
Dans votre cas, l'héritage de l'app n':
pendant que vous faites:
Vous ne définissez pas le DTR (Terminal de Données Prêt) signal et donc l'appareil n'est pas en attendre des données ou des commandes sur la ligne série. Ainsi mis en
SerialPort.DtrEnable
àtrue
.Deuxième problème est que vous ne tournez pas sur la poignée de main. L'héritage de l'app n':
pendant que vous faites:
L'activer par la mise en
SerialPort.Poignée de main
àpoignée de main.RequestToSend
.Aussi, vous semblez être l'ouverture, la fermeture et la reconfiguration du port série très fréquemment. Essayez de configurer le port et ensuite utiliser la même instance de
SerialPort
pour l'ensemble de la session. N'essayez pas de l'ouvrir, parce que vous allez être à l'origine des reconfigurations de l'état physique du port de broches.De communication série n'est pas de la magie noire, mais il est assez sensible sur l'installation et les appareils divers exigent des paramètres et de traitement. Un bon timing, de commandes peut être un problème aussi.
Si vous avez certains de la documentation technique pour votre appareil, ne le lire deux fois et obéir à la première place. Au moins handshaking les modes, les commandes, etc. devraient être documentés correctement.
Si vous n'avez pas la documentation, essayez d'atténuer les différences, un par un.
Mise à JOUR: l'Envoi et la réception de données.
Vous avez écrit que vous avez envoyé la commande
'Ping'
(comme décodé à partir de hex ASCII). Toutefois, vous ne faites pas mention de l'envoi et de commande de séquence de fin. Généralement périphériques série s'attendre à une fin de ligne séquence (généralement un CR LF) que la résiliation de la commande. Avant que l'appareil reçoit un complète de commande, y compris fin de ligne, il ne peut pas répondre.Vous manipulez les données de réception de l'événement en appelant
ReadLine
— toutefois, à l'endroit où vous ne pouvez pas vous attendre toute une ligne de données (c'est à dire avec une fin de ligne pour être en mesure de détecter un comlete ligne). Vous devez examiner les arguments de l'événement prévu et lire l'entrée octet par octet.C'est une bonne idée de créer une classe wrapper qui fournira un accompagnement sur mesure, envoyez-commande, réception de la réponse, envoyez-données de réception données caractéristiques. L'emballage devra en interne fonctionne de manière asynchrone en ce qui concerne le reste de votre code. De cette façon, vous aurez une utilisable API personnalisé et une sage port série de la manipulation.
Noter que le
SerialPort.NewLine
de la propriété sert le but d'indiquer comment une fin de ligne séquence ressemble. (Dans votre question, vous avez mentionné que vous étiez en train de définir le jeu de caractères spéciaux. Que c'était faux en effet.)Cela fait déjà quelques temps que j'étais un serial comm héros (ceux qui étaient les jours, nous n'avions pas de vmware, mais deux 486-alimenté Pc et une paire de directement connecté modems pour développer et déboguer des applications de communication :-)), mais j'espère que cela aide au moins un peu.
Dernier mais non le moins, une certaine terminologie commune:
C'est difficile à dire sans le réel de l'appareil. Il y a probablement quelque chose de mal avec votre flux de contrôle de l'installation.
Une fois les modifications effectuées, exécutez la surveillance de nouveau et de comparer ce qui a changé, et que l'IOCTL séquence est plus semblable à ce que vous avez enregistré avec l'héritage de l'app. En général, .NET propose un wrapper sur la non géré API et peuvent ne pas offrir le même niveau de contrôle. Très probablement, vous aurez à gérer pour l'obtenir vers le haut et en cours d'exécution à l'aide pur .NET, mais de recourir à des appels à l'API Win32 non gérée peut être une option à envisager.
Mise à jour de ma réponse à couvrir les dépassements de délai et des tailles de file d'attente.
Wright Comment ça se passe? Avez-vous une dernière mise à jour concernant l'envoi et la réception de données d'aide à aller de l'avant?
OriginalL'auteur Ondrej Tucny
Avez-vous essayé de changer les Poignée de main propriété? Peut-être que l'appareil nécessite une certaine poignée de main sur le contrôle de pins, avant d'accepter des données.
OriginalL'auteur shf301
Vous devez activer la RtsEnable ou DtrEnable propriétés, l'appareil ignorer tout ce que vous envoyez, ni envoyer quelque chose en retour quand il ne détecte pas vous en ligne à partir de ces signaux. Réglage de la poignée de main bien à la RTS devrait avoir fait cela.
Méfiez-vous que le ReadLine() la méthode se bloque jusqu'à ce qu'il obtient le caractère de Saut de ligne. Vous n'êtes pas l'envoi d'un, donc vous ne serez pas obtenir un retour. En utilisant Read() serait un meilleur test.
Faire quelques dépannage de base d'abord par un de programme de travail, en éliminant les problèmes de câblage, mauvaise transmission en bauds ou de l'appareil tout simplement pas de l'écho-ing en arrière. Utiliser HyperTerminal ou de Mastic.
OriginalL'auteur Hans Passant
Tom ,
J'ai eu des problèmes similaires,
Je vais placer mon pari sur le fait que ReadLine() renvoie uniquement une fois qu'il a reçu un \r\n ou quelque chose qui .NET croit est une nouvelle ligne.
Dans vos journaux, je ne vois pas Winbird signaler tout de caractères de nouvelle ligne, je crois que l'APP est la lecture de l'octet par octet, et ne pas attendre les retours à la ligne.
De sorte que vous pouvez envoyer le nombre d'octets de données, et il continuera de blocage jusqu'à ce qu'il reçoive le bon de caractères de nouvelle ligne.
Afin de donner SerialPort.Lire un essai, par la lecture de 1 octet à la fois pour les débutants,
)
Si cela ne marche pas à le résoudre, vous pourriez envisager la suite
Certains de mes problèmes ont été résolus grâce à l'ajout d'un peu de Fil.Sleep()'s parce que j'ai réalisé le PC de l'Uart ne sont pas assez rapide pour électriquement transmettre les données via l'interface RS232/RS485 ports correctement, également attendre quelques millisecondes après l'ouverture du port.
Je voudrais aussi vous conseille de plutôt créer un thread séparé pour gérer la série comms, au lieu d'utiliser SerialDataReceivedEventHandler, créer un tampon d'envoi, qui est envoyé dans le bon incréments sans bloquer votre application, également de lire les données et ajouter des octets reçus à la mémoire tampon jusqu'à ce que vous avez reçu suffisamment de données.
Vous allez également avoir besoin d'une deuxième série de l'appareil pour capturer vos données pour vous assurer que votre application en C#, c'est transmettre des données correctes.
À elimate la question de la poignée de main, test par n'avoir que des BROCHES 2,3 + BROCHE 5 (GND) connecté.
Espère que cette aide
OriginalL'auteur John Smith