Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
DotNETFrameworkNotesForProfessionals.pdf
Скачиваний:
32
Добавлен:
20.05.2023
Размер:
1.82 Mб
Скачать

Chapter 57: Serial Ports

Section 57.1: Basic operation

var serialPort = new SerialPort("COM1", 9600, Parity.Even, 8, StopBits.One); serialPort.Open();

serialPort.WriteLine("Test data"); string response = serialPort.ReadLine(); Console.WriteLine(response); serialPort.Close();

Section 57.2: List available port names

string[] portNames = SerialPort.GetPortNames();

Section 57.3: Asynchronous read

void SetupAsyncRead(SerialPort serialPort)

{

serialPort.DataReceived += (sender, e) => { byte[] buffer = new byte[4096];

switch (e.EventType)

{

case SerialData.Chars:

var port = (SerialPort)sender;

int bytesToRead = port.BytesToRead; if (bytesToRead > buffer.Length)

Array.Resize(ref buffer, bytesToRead);

int bytesRead = port.Read(buffer, 0, bytesToRead);

//Process the read buffer here

//...

break;

case SerialData.Eof:

//Terminate the service here

//...

break;

}

};

Section 57.4: Synchronous text echo service

using System.IO.Ports;

namespace TextEchoService

{

class Program

{

static void Main(string[] args)

{

var serialPort = new SerialPort("COM1", 9600, Parity.Even, 8, StopBits.One); serialPort.Open();

string message = ""; while (message != "quit")

{

message = serialPort.ReadLine(); serialPort.WriteLine(message);

}

GoalKicker.com – .NET Framework Notes for Professionals

176

serialPort.Close();

}

}

}

Section 57.5: Asynchronous message receiver

using System;

using System.Collections.Generic; using System.IO.Ports;

using System.Text; using System.Threading;

namespace AsyncReceiver

{

class Program

{

const byte STX = 0x02; const byte ETX = 0x03; const byte ACK = 0x06; const byte NAK = 0x15;

static ManualResetEvent terminateService = new ManualResetEvent(false); static readonly object eventLock = new object();

static List<byte> unprocessedBuffer = null;

static void Main(string[] args)

{

try

{

var serialPort = new SerialPort("COM11", 9600, Parity.Even, 8, StopBits.One); serialPort.DataReceived += DataReceivedHandler;

serialPort.ErrorReceived += ErrorReceivedHandler; serialPort.Open();

terminateService.WaitOne(); serialPort.Close();

}

catch (Exception e)

{

Console.WriteLine("Exception occurred: {0}", e.Message);

}

Console.ReadKey();

}

static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)

{

lock (eventLock)

{

byte[] buffer = new byte[4096]; switch (e.EventType)

{

case SerialData.Chars:

var port = (SerialPort)sender;

int bytesToRead = port.BytesToRead; if (bytesToRead > buffer.Length)

Array.Resize(ref buffer, bytesToRead);

int bytesRead = port.Read(buffer, 0, bytesToRead); ProcessBuffer(buffer, bytesRead);

break;

case SerialData.Eof: terminateService.Set(); break;

GoalKicker.com – .NET Framework Notes for Professionals

177

}

}

}

static void ErrorReceivedHandler(object sender, SerialErrorReceivedEventArgs e)

{

lock (eventLock)

if (e.EventType == SerialError.TXFull)

{

Console.WriteLine("Error: TXFull. Can't handle this!"); terminateService.Set();

}

else

{

Console.WriteLine("Error: {0}. Resetting everything", e.EventType); var port = (SerialPort)sender;

port.DiscardInBuffer(); port.DiscardOutBuffer(); unprocessedBuffer = null; port.Write(new byte[] { NAK }, 0, 1);

}

}

static void ProcessBuffer(byte[] buffer, int length)

{

List<byte> message = unprocessedBuffer; for (int i = 0; i < length; i++)

if (buffer[i] == ETX)

{

if (message != null)

{

Console.WriteLine("MessageReceived: {0}", Encoding.ASCII.GetString(message.ToArray()));

message = null;

}

}

else if (buffer[i] == STX) message = null;

else if (message != null) message.Add(buffer[i]);

unprocessedBuffer = message;

}

}

}

This program waits for messages enclosed in STX and ETX bytes and outputs the text coming between them. Everything else is discarded. On write bu er overflow it stops. On other errors it reset input and output bu ers and waits for further messages.

The code illustrates:

Asynchronous serial port reading (see SerialPort.DataReceived usage).

Serial port error processing (see SerialPort.ErrorReceived usage).

Non-text message-based protocol implementation.

Partial message reading.

The SerialPort.DataReceived event may happen earlier than entire message (up to ETX) comes. The entire message may also not be available in the input bu er (SerialPort.Read(..., ..., port.BytesToRead) reads only a part of the message). In this case we stash the received part (unprocessedBuffer) and carry on waiting for further data.

Dealing with several messages coming in one go.

 

GoalKicker.com – .NET Framework Notes for Professionals

178

The SerialPort.DataReceived event may happen only after several messages have been sent by the other end.

GoalKicker.com – .NET Framework Notes for Professionals

179