mcferson
Messages postés33Date d'inscriptionjeudi 7 septembre 2006StatutMembreDernière intervention 1 juin 2012
-
30 août 2010 à 12:11
vb95 -
7 févr. 2020 à 14:31
Bonjour ici.
Voilà, ne connaissant pas bien la classe SerialPort, je ne sais pas comment envoyer une commande sur un port COM.
Par exemple, sur hyperterminal, j'écris ma commande, à destination d'un module GPS, dans son langage d'instruction. Je cherche à faire ça, par l'intermédiaire d'un programme personnel en C#, qui va envoyer la commande saisie sous forme d'une string (en réalité un peu plus complexe que ça, mais la commande est, au final bien envoyée en string, puisque chaque composant est récupéré d'un fichier xml).
il y a bien SerialPort.Write() mais manifestement, ça n'a pas l'air d'être ça (ou bien c'est ma récupération de la réponse qui est foireuse).
cs_casy
Messages postés7741Date d'inscriptionmercredi 1 septembre 2004StatutMembreDernière intervention24 septembre 201440 31 août 2010 à 16:22
C'est bien Write qu'il faut utiliser
Mais Write à la particularité de faire par défaut les envois en ASCIIEncoding, donc tous les caractères dont le code ascii est supérieur à 127 seront remplacer par ?
Pour pouvoir envoyer ces caractères correctement, il faut passer sur un encoding UTF8, UTF32 ou Unicode, mais alors chaque caractère sera représenté par 2 à 4 octets.
Sinon, (de mémoire d'après divers messages vus sur les forums) il faut convertir la chaine de caractère en tableau de byte et envoyer ce tableau.
[i][b]---- Sevyc64 (alias Casy) ----
[hr]# LE PARTAGE EST NOTRE FORCE #/b/i
cs_casy
Messages postés7741Date d'inscriptionmercredi 1 septembre 2004StatutMembreDernière intervention24 septembre 201440 31 août 2010 à 20:24
Ah ok, avec un tableau de byte
Effectivement il te faut 2 paramètres de plus qui sont des nombres.
Le premier indique à partir de quel élément dans le tableau l'envoi se fera, le second indique combien d'éléments du tableau seront envoyés.
Donc pour toi, à priori, l'envoi se fera à partir du premier élément (indice 0) et tu enverra la totalité du tableau (soit un nombre égal à la longueur du tableau
Donc quelque chose comme ça :
mySerialPort.Write(data,0,data.Lenght);
[i][b]---- Sevyc64 (alias Casy) ----
[hr]# LE PARTAGE EST NOTRE FORCE #/b/i
cs_casy
Messages postés7741Date d'inscriptionmercredi 1 septembre 2004StatutMembreDernière intervention24 septembre 201440 1 sept. 2010 à 15:53
Tu peux essayer comme ça
Tu prend ta chaine de commande, brute, tu lui rajoute Environment.Newline, qui normalement sous windows rajoute les caractères CR + LF.
Puis tu envoie le tout avec Write et non pas WriteLine.
Sinon tu converti ta chaine brute en tableau de byte dans un tableau plus grand de 1 ou 2 éléments (suivant ce que tu as besoin). Dans le(ou les 2) dernier(s) élément(s) tu y met manuellement la(es) valeur(s) &h13 (et &h10).
Puis tu balance la totalité du tableau.
[i][b]---- Sevyc64 (alias Casy) ----
[hr]# LE PARTAGE EST NOTRE FORCE #/b/i
mcferson
Messages postés33Date d'inscriptionjeudi 7 septembre 2006StatutMembreDernière intervention 1 juin 2012 Modifié le 7 févr. 2020 à 16:26
aah. ok.
J'ai tenté une conversion "forcée" en ASCII, passant donc par un tableau de bytes.
Voici mon code de test. Je ne reçoit aucune réponse de l'appareil branché, en retour de mes commandes. Par contre il m'envoie des messages que je reçois bien.
public partial class MainForm : Form
{
SerialPort mySerialPort;
public MainForm()
{
//
// The InitializeComponent() call is required for Windows Forms designer support.
//
InitializeComponent();
//
// TODO: Add constructor code after the InitializeComponent() call.
//
}
private void MainFormLoad(object sender, EventArgs e)
{
mySerialPort=new SerialPort();
//paramètres pour le VT10
mySerialPort.PortName="COM3";
mySerialPort.BaudRate = 57600;
mySerialPort.Parity = Parity.None;
mySerialPort.StopBits = StopBits.One;
mySerialPort.DataBits = 8;
mySerialPort.Handshake = Handshake.None;
mySerialPort.Encoding=Encoding.UTF8;
mySerialPort.DtrEnable = true;
mySerialPort.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
}
private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
// Event for receiving data
// Read the buffer to text box.
this.Invoke(new EventHandler(DoUpdate));
}
private void DoUpdate(object s, EventArgs e)
{
txsortie.Text = txsortie.Text + mySerialPort.ReadExisting();
}
private void btSend_Click(object sender, EventArgs e)
{
// Button to send test data
try
{
string output;
byte[] data = Encoding.Unicode.GetBytes(txentree.Text);
output = Encoding.ASCII.GetString(data);
mySerialPort.WriteLine(output);
}
catch (Exception wex)
{
MessageBox.Show(wex.ToString());
}
}
void BtOpenClick(object sender, EventArgs e)
{
if (mySerialPort.IsOpen == false)
try
{
mySerialPort.Open();
//MessageBox.Show("Port Open");
}
catch (Exception oex)
{
MessageBox.Show("Error Opening Port: " + oex.ToString());
}
}
void BtCloseClick(object sender, EventArgs e)
{
mySerialPort.Close();
}
}
cs_casy
Messages postés7741Date d'inscriptionmercredi 1 septembre 2004StatutMembreDernière intervention24 septembre 201440 31 août 2010 à 17:17
Attention à WriteLine qui, à la différence de Write, rajoute automatiquement les caractères de saut de ligne (théoriquement CR et LF) à la fin de la chaine envoyée.
As-tu moyen de savoir si tes caractères sont correctement envoyés, en branchant par exemple un terminal (ou autre pc) à la place de ton module GPS ?
[i][b]---- Sevyc64 (alias Casy) ----
[hr]# LE PARTAGE EST NOTRE FORCE #/b/i
cs_casy
Messages postés7741Date d'inscriptionmercredi 1 septembre 2004StatutMembreDernière intervention24 septembre 201440 31 août 2010 à 22:30
Pour tes tests, si tu n'as pas la possibilité de brancher un second PC sur ton port série pour voir si tu envois bien, il existe des logiciels qui permettent de créer des ports virtuels comme par exemple Virtual Serial Port Driver de l'éditeur Eltima (version d'éval 14 jours).
LE principe c'est de créer 2 ports virtuels sur ta machine. Ces 2 ports sont reliés (virtuellement) comme si tu branchais 2 PC sur des ports réels.
Ensuite tu configure ton appli pour utiliser un des 2 ports, il ne te reste qu'à connecter l'hyperterminal (ou autre logiciel) sur le second port, le tout sur le même PC.
[i][b]---- Sevyc64 (alias Casy) ----
[hr]# LE PARTAGE EST NOTRE FORCE #/b/i
mcferson
Messages postés33Date d'inscriptionjeudi 7 septembre 2006StatutMembreDernière intervention 1 juin 2012 1 sept. 2010 à 13:07
Bon alors, résultat des courses : Mon appli fonctionne impeccablement bien. Que j'envoie directement le contenu string de ma textbox ou que je le convertisse en ascii (ou autre). Je reçoie autant que j'envoie, tout est bon.
Sauf, étrangeté, chaque envoie s'inscrit à la suite, pas sur une ligne suivante. Et si j'utilise WriteLine, il y a bien une ligne passée, mais le texte ne s'affiche pas en début de ligne : à la suite du précédent MAIS une ligne en dessous.
Dans ce style là :
testtest$wp+ver$WP+VERtagada
dgfchdfhgf
testsuite
Perturbant. Toujours est-il que le module GPS branché sur le COM3 (à l'origine) ne semble pas recevoir ou comprendre le blabla que je lui balance (saut de ligne ou pas). peut-être à cause de ce détail bizarre.
cs_casy
Messages postés7741Date d'inscriptionmercredi 1 septembre 2004StatutMembreDernière intervention24 septembre 201440 1 sept. 2010 à 13:29
Oui, j'avais remarqué ça aussi. Cela vient de l'information retour à la ligne ajoutée automatiquement à la fin de la chaine avec la méthode WriteLine et de la façon dont l'interprète le terminal.
Cette information doit être constituée du seul caractère "Saut de ligne" (LF de code ascii 0x10) ou alors elle est constituée des 2 caractères "Saut de ligne" (LF) et "Retour chariot" (CR de code ascii 0x13) mais dans le désordre, c'est à dire LF suivi de CR
Il est vrai qu'habituellement, lorsqu'on envoie les 2 caractères on met le CR avant le LF.
Du coté du terminal, soit il reçoit un seul caractère et l'interprète de façon brute, soit il reçoit les 2 mais n'interprète que le premier. Certains terminaux ont des options pour configurer la façon d'interpréter ces caractères là.
Ensuite, si tu préfère voir le code hexa brut reçu, plutôt que les caractères interprétés par un terminal, tu peux aussi utiliser le petit utilitaire RS232 Hex Com Tool de l'éditeur Virtual Integrated Design (coupure de la connexion toutes les 5 min en version démo)
[i][b]---- Sevyc64 (alias Casy) ----
[hr]# LE PARTAGE EST NOTRE FORCE #/b/i
mcferson
Messages postés33Date d'inscriptionjeudi 7 septembre 2006StatutMembreDernière intervention 1 juin 2012 1 sept. 2010 à 15:44
Ok, c'est résolu !
Le problème venait bien du retour à la ligne. WriteLine envoie le code <LF>, surement en premier, et mon module GPS attend, en tout premier lieu, un <CR>. Donc, il ne répondait pas à ce qu'il ne comprenait pas.
Reste donc à coder ce <CR> en fin de ligne (perso, j'ai juste testé avec une textbox multiligne, donc en appuyant sur "Entrée" avant d'envoyer la commande), car le soft complet, lui, va concaténer toute une commande à partir de multiples paramètres et choix dans des listes, etc... PLUS le code <CR>.