.NET Framework
Последовательные порты
Поиск…
Основная операция
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();
Список доступных имен портов
string[] portNames = SerialPort.GetPortNames();
Асинхронное считывание
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;
}
};
Синхронный текстовый эхо-сервис
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);
}
serialPort.Close();
}
}
}
Асинхронный приемник сообщений
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;
}
}
}
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;
}
}
}
Эта программа ждет сообщений, заключенных в байты STX
и ETX
и выводит текст, идущий между ними. Все остальное отбрасывается. При переполнении буфера записи он останавливается. При других ошибках он перезапускает входные и выходные буферы и ждет дополнительных сообщений.
Код иллюстрирует:
- Чтение асинхронного последовательного порта (см. Использование
SerialPort.DataReceived
). - Обработка ошибок последовательного порта (см. Использование
SerialPort.ErrorReceived
). - Внеконтекстная реализация протокола.
- Чтение частичных сообщений.
- Событие
SerialPort.DataReceived
может произойти раньше всего сообщения (доETX
). Все сообщение также может быть недоступно во входном буфере (SerialPort.Read (..., ..., port.BytesToRead) читает только часть сообщения). В этом случае мы запишем полученную часть (unprocessedBuffer
) и продолжаем ждать дальнейших данных.
- Событие
- Работа с несколькими сообщениями происходит за один раз.
- Событие
SerialPort.DataReceived
может произойти только после отправки нескольких сообщений другим концом.
- Событие
Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow