Introduction
This is a basic sample of serial port (COM port) listening in C#. Serial port listening is done in a background worker.
Serial port listening applications usually have this only as a part of a bigger solution, while this application does nothing else than list available COM-ports, list available baud rates for the selected COM-port and starts printing the data to screen.
Using the code
The serial port handling code is placed in a class called SerialPortManager. This class contains methods for start and stop listening for data on the serial port.
Finding installed serial ports
Rather than just assuming the number of serial ports, or leaving it up to the user to know this in forehand, the code finds the installed serial ports. A string array of serial ports is received through a call made in the constructor of the class
SerialPortManager.
public SerialPortManager()
{
_currentSerialSettings.PortNameCollection = System.IO.Ports.SerialPort.GetPortNames();
_currentSerialSettings.PropertyChanged +=
new System.ComponentModel.PropertyChangedEventHandler
(_currentSerialSettings_PropertyChanged);
if (_currentSerialSettings.PortNameCollection.Length > 0)
_currentSerialSettings.PortName = _currentSerialSettings.PortNameCollection[0];
_workingThread = new BackgroundWorker();
InitializeBackgroundWorker();
}
Updating baud rates supported by the selected device
When a serial port is selected by the user, a query for supported baud rates is done. Depending on the hardware, different collections of baud rates may be supported. The field
dwSettableBaud from the
COMMPROP Structure is a join of all supported baud rates.
private void UpdateBaudRateCollection()
{
_serialPort = new SerialPort(_currentSerialSettings.PortName);
_serialPort.Open();
// Getting COMMPROP structure, and its property dwSettableBaud.
object p = _serialPort.BaseStream.GetType().GetField("commProp", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(_serialPort.BaseStream);
Int32 dwSettableBaud = (Int32)p.GetType().GetField("dwSettableBaud", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public).GetValue(p);
_serialPort.Close();
_currentSerialSettings.UpdateBaudRateCollection(dwSettableBaud);
}
Serial port settings
The class named SerialSettings contain the current selected serial port settings, and also includes lists of alternatives for the different setting properties. All is data bound to the GUI.
Start listening to a serial port
The serial port is instantiated using the current selected settings
// Connects to a serial port defined through the current settings
public void StartListening()
{
if (_serialPort != null)
{
if (_serialPort.IsOpen)
_serialPort.Close();
_serialPort.Dispose();
}
_serialPort = new SerialPort(
_currentSerialSettings.PortName,
_currentSerialSettings.BaudRate,
_currentSerialSettings.Parity,
_currentSerialSettings.DataBits,
_currentSerialSettings.StopBits);
_workingThread.RunWorkerAsync();
}
The actual serial port reading
The actual serial port reading is running in a BackgroundWorker. When data is received on the serial port, an event is raised and _serialPort_DataReceived is called.
void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
object thislock = new object();
lock (thislock)
{
int dataLength = _serialPort.BytesToRead;
char[] data = new char[dataLength];
int nbrDataRead = _serialPort.Read(data, 0, dataLength);
if (nbrDataRead == 0)
return;
string strData = new string(data);
_latestRecieved = strData;
NotifyPropertyChanged("LatestRecieved");
}
}
Stop listening
We stop listening by stopping the thread running
/// Closes the serial port
public void StopListening()
{
// if already closed
if (!ThreadRunning)
return;
_workingThread.CancelAsync();
}
This attachment is hidden for guests. Please log in or register to see it.