What Is the Correct Way to Read a Serial Port Using .Net Framework

What is the correct way to read a serial port using .NET framework?

Could you try something like this for example I think what you are wanting to utilize is the port.ReadExisting() Method

 using System;
using System.IO.Ports;

class SerialPortProgram
{
// Create the serial port with basic settings
private SerialPort port = new SerialPort("COM1",
9600, Parity.None, 8, StopBits.One);
[STAThread]
static void Main(string[] args)
{
// Instatiate this
SerialPortProgram();
}

private static void SerialPortProgram()
{
Console.WriteLine("Incoming Data:");
// Attach a method to be called when there
// is data waiting in the port's buffer
port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
// Begin communications
port.Open();
// Enter an application loop to keep this thread alive
Console.ReadLine();
}

private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
// Show all the incoming data in the port's buffer
Console.WriteLine(port.ReadExisting());
}
}

Or is you want to do it based on what you were trying to do , you can try this

public class MySerialReader : IDisposable
{
private SerialPort serialPort;
private Queue<byte> recievedData = new Queue<byte>();

public MySerialReader()
{
serialPort = new SerialPort();
serialPort.Open();
serialPort.DataReceived += serialPort_DataReceived;
}

void serialPort_DataReceived(object s, SerialDataReceivedEventArgs e)
{
byte[] data = new byte[serialPort.BytesToRead];
serialPort.Read(data, 0, data.Length);
data.ToList().ForEach(b => recievedData.Enqueue(b));
processData();
}

void processData()
{
// Determine if we have a "packet" in the queue
if (recievedData.Count > 50)
{
var packet = Enumerable.Range(0, 50).Select(i => recievedData.Dequeue());
}
}

public void Dispose()
{
if (serialPort != null)
{
serialPort.Dispose();
}
}

Getting Serial Port Information

There is a post about this same issue on MSDN:

Getting more information about a serial port in C#

Hi Ravenb,

We can't get the information through the SerialPort type. I don't know why you need this info in your application. However, there's a solved thread with the same question as you. You can check out the code there, and see if it can help you.

If you have any further problem, please feel free to let me know.

Best regards,
Bruce Zhou

The link in that post goes to this one:

How to get more info about port using System.IO.Ports.SerialPort

You can probably get this info from a WMI query. Check out this tool to help you find the right code. Why would you care though? This is just a detail for a USB emulator, normal serial ports won't have this. A serial port is simply know by "COMx", nothing more.

Serial port communication in .NET

None of these methods are "event driven", you'd use them in the DataReceived event. Which is called when the serial port has at least one byte of data available to read.

Not sure what "static sized" means. If the device sends a fixed number of bytes then you'd use the Read() method to read them. Pay attention to the return value, you'll get only as many bytes as are available. Store them in a byte[] and append to that in the next DR event until you've got them all.

If the device sends characters rather than bytes then you can usually take advantage of the NewLine property. Set it to the character or string that terminates the response. A linefeed ("\n") is by far the most typical choice. Read the response with ReadLine(). No buffering is required in that case.

You'll get the ObjectDisposed exception when you close a form but don't ensure that the device stops sending data. Be sure to use only BeginInvoke in the DataReceived event, not Invoke. And don't call BeginInvoke if the form's IsDisposed property is true.

Read Serial Reply After Write With C#

Yes, call ReadLine().

There's an issue however, serial ports are glacially slow. A common baudrate setting is 9600 baud, each character takes one millisecond to get received. Say you get 6 digits back, you're looking at RC + lf + 000000 + lf + controller overhead milliseconds. Your program is dead to the world for at least 10 milliseconds. The equivalent of about 20 million cpu cycles.

Whether that's a real problem entirely depends on how many cpu cycles you need in your app. You solve it by using threading, either explicitly with a thread that does nothing but talking to the controller or by using the DataReceived event.

Misunderstanding of C# SerialPort.Write() method

Kunif is right. We can't write and read simultaneously at the same port via code (at least by using .NET Framework 4). So decision is to use free software com0com for creating a connection between 2 virtual ports. The first one calls write() method, the second one handles an input signal.

class SerialPortProgram
{
private SerialPort port, port2;

[STAThread]
static void Main(string[] args)
{
new SerialPortProgram();
}

private SerialPortProgram()
{
port = new SerialPort("COM3", 9600, Parity.None, 8, StopBits.One);
port.Open();

port2 = new SerialPort("COM4", 9600, Parity.None, 8, StopBits.One);
port2.DataReceived += new SerialDataReceivedEventHandler(port2_DataReceived);
port2.Open();

port.Write("Hello!");

Console.Read();
}

void port2_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
Console.WriteLine("COM4 incoming data:");
Thread.Sleep(300);
string inp = port2.ReadExisting();
Console.WriteLine(inp);
Console.WriteLine("----");
}
}


Related Topics



Leave a reply



Submit