In diesem Tutorial wird vorgestellt, wie unter Visual Studio Serial Port genutzt werden kann. Im Beispiel kann der Nutzer Texte über dem Com-Port senden, welche der Mikrocontroller als Echo zurücksendet.
Die serielle Kommunikation wird voraussichtlich für die Kommunikation zwischen zwei Teilnehmern benötigt (hier der MCU und der PC). Bevor noch irgendetwas implementiert wird, macht es Sinn zuerst sich auf die Protokoll-Einstellungen zu einigen. Sender und Empfänger müssen die gleichen Einstellungen aufweisen. Für dieses Projekt werden willkürlich folgende Einstellungen festgelegt:
- Baudrate: 9600
- Databits: 8
- Stopbit: 1
- Parity Bit: Keins
Mikrocontroller
Als Hardware wird der EXP430G2-Launchpad Revision 1.5 von Texas Instruments eingesetzt. Darauf sitzt der Mikrocontroller MSP430G2553. Der Mikrocontroller spielt im diesem Beispiel den Kommunikationsteilnehmer. Dabei soll der MCU empfangenen Daten vom PC als Echo zurücksenden. Da das Launchpad einen USB zu UART-Wandler integriert hat, wird keine zusätzliche Hardware benötigt. Bei der Hardware ist zu beachten, dass die Jumper für Hardware UART eingesteckt sind (vgl. Abbildung).
Der Fokus dieses Tutorials soll jedoch nicht auf dem Mikrocontroller, sondern auf das Visual Studio Projekt liegen.
Visual Studio Serial Port
Das Programm wurde mit Visual Studio 2010 geschrieben. Um es selber zu kompilieren, sollte der Anwender einer Version mindestens ab 2010 installiert haben. Das Projekt wurde mySerial benannt.
Nachdem Visual Studio gestartet wurde, wie folgt vorgehen:
- Neues Projekt mit Visual Studio anlegen, dabei Windows-Form und C# als Sprache auswählen
- Füge folgende Elemente ein und benenne diese wie in der Tabelle
Original Name | Neuer Name | Funktion |
SerialPort1 | mySerial | Regelt die Kommunikation zwischen PC und Mikrocontroller über dem ComPort. |
Button1 | btConnect | Mikrocontroller mit GUI verbinden |
Button2 | btSend | Sende String über SerialPort |
ComboBox1 | cbPort | Auswahl vom verfügbaren ComPort |
TextBox1 | tbSend | Sende String-Nachricht |
RichTextBox1 | rtbReceive | Empfange String-Nachricht |
Label1 | Label1 | – |
Label1 | Label2 | – |
Label3 | lbStatus | Zeigt den aktuellen Status |
- Das Ergebnis soll so aussehen:
- Das Programm soll folgende Funktion aufweisen:
- Suche nach den verfügbaren Serial Ports und zeige diese an
- Verbinde mit Mikrocontroller per Knopfdruck
- Sende Nachrichten per Knopfdruck
- Empfange Echo
- Elemente vorbereiten
SerialPort; Zuerst müssen wir die Einstellungen am SerialPort (hier als mySerial benannt) einstellen. Dazu auf mySerial klicken und rechts unter Eigenschaften die Einstellungen setzen. In diesem Fall müssen wir nur die Baudrate auf 9600 einstellen.
Form1_Load(); Drücke irgendwo auf der Form. Nun gehe im Eigenschaften Fenster und klicke auf Ereignisse. Durch Doppelklick auf Form1_Load() wird der Event automatisch hinzugefügt.
Form1_FormClosing(); Drücke irgendwo auf der Form. Nun gehe im Eigenschaften Fenster und klicke auf Ereignisse. Durch Doppelklick auf Form1_FormClosing() wird der Event automatisch hinzugefügt.
btConnenct_Click(); Gehe zur Form, mit Doppelklick auf dem Button wird automatisch das Event erzeugt.
- Zusammengefasst die Funktionen die für das ganze Programm benötig werden:
Funktion | Beschreibung |
Form1() | Konstruktor der Form |
Form1_Load() | Zur Form-Ladezeit; Hier sollen die verfügbaren Serial Ports ausgelesen und angezeigt werden |
Form1_FormClosing() | Zur Form-Beenden; Falls die Form einen Serial-Port geöffnet hat, soll die Form diesen hier wieder schließen |
btConnenct_Click() | Per Knopfdruck mit dem Mikrocontroller verbinden |
btSend_Click() | Per Knopfdruck die eine String-Nachricht zu dem Mikrocontroller senden |
portDataReceived() | Event bei der vom Mikrocontroller empfangen Nachrichten bearbeitet werden |
DisplayData() | Funktion welche die empfangene Nachricht in der rtbReceice anzeigt. Um keinen Threat-Übergreifenden-Fehler auszulösen, muss die Funktion per Invoke-Befehl in der portDataReceived-Funktion aufgerufen werden. |
- Der Quellcode kann hier eingesehen werden (oder direkt am Anfang des Artikels das ganze Projekt runterladen)
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 |
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace mySerial { public partial class Form1 : Form { //########################################################################################################################################################################## public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { string[] myPort = System.IO.Ports.SerialPort.GetPortNames(); // Füge die möglichen Ports ein cbPort.DataSource = myPort; } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { if (mySerial.IsOpen) mySerial.Close(); // Schließe Port wieder } //########################################################################################################################################################################## private void btConnenct_Click(object sender, EventArgs e) { // Verbidung mit dem MCU aufbauen try // Fehler abfangen { int index = cbPort.SelectedIndex; if (!(mySerial.IsOpen)) // Gehe rein wenn der Comport geschlossen ist { mySerial.PortName = cbPort.Items[index].ToString(); // Weise meiner Port-Variable den gewünschten Port zu mySerial.Open(); // Öffne den Port mySerial.DataReceived += new Sys-tem.IO.Ports.SerialDataReceivedEventHandler(portDataReceived); // Starte Übertragung (bin Bereit) lbStatus.Text = "Connected"; // Gebe Anwender Status zurück btSend.Enabled = true; } // if else lbStatus.Text = "Not connected"; // Gebe Anwender Status zurück } // try catch (UnauthorizedAccessException) { } // Fehler wenn ich einen unautharisierten Comport öffnen möchte catch (System.IO.IOException) { lbStatus.Text = "Connection does not exist"; } // Anschluss nicht vorhanden } private void btSend_Click(object sender, EventArgs e) { // Text vom der TexBox dem MCU senden if (mySerial.IsOpen) // Nur falls Port geöffnet { mySerial.DiscardOutBuffer(); // Verwerfe wenn etwas im Puffer war mySerial.Write(tbSend.Text+"\n"); // Sende String * } // if // * Beachte die Funktion Write() kann auch Byte-Array (für Hex-Zahlen) oder Char-Array senden } //########################################################################################################################################################################## private void portDataReceived(object sender, Sys-tem.IO.Ports.SerialDataReceivedEventArgs e) { // Empfange Daten Event this.Invoke(new EventHandler(DisplayData)); } private void DisplayData(object s, EventArgs e) { // Empfangene Daten vom MCU über der RichTextBox anzeigen rtbReceive.Text = ""; char[] puffer = new char[100]; int i = 0; while (puffer[i] != '\n') { mySerial.Read(puffer, 0, 1); rtbReceive.Text += puffer[i].ToString(); } // while } } } |
Für weitere Fragen bezüglich Visual Studio Serial Port stehe ich jederzeit zur Verfügung. Einfach per Mail kontaktieren.