C#GUIを使用してハードウェアからデータを送受信する方法を学び始めたところです。
誰もがシリアルポートからのデータをreadする方法の詳細を書いていただけますか?
C#.NET)のSerialPort(RS-232シリアルCOMポート
この記事では、.NETで SerialPort
クラスを使用してデータを読み書きする方法、マシンで使用可能なシリアルポートを判別する方法、およびファイルを送信する方法について説明します。 。ポート自体のピン割り当てもカバーしています。
サンプルコード:
using System;
using System.IO.Ports;
using System.Windows.Forms;
namespace SerialPortExample
{
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 class
new SerialPortProgram();
}
private 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
Application.Run();
}
private void port_DataReceived(object sender,
SerialDataReceivedEventArgs e)
{
// Show all the incoming data in the port's buffer
Console.WriteLine(port.ReadExisting());
}
}
}
SerialPort クラスを使用するのに多くの時間を費やし、代わりに SerialPort.BaseStream クラスを使用すると結論付けました。ソースコードを見ることができます: SerialPort-source および SerialPort.BaseStream-source を深く理解してください。以下に示すコードを作成して使用します。
コア関数public int Recv(byte[] buffer, int maxLen)
には名前があり、「よく知られている」ソケットのrecv()
のように機能します。
だということだ
TimeoutException
がスローされます。maxLen
バイトまでデータを受信します。
public class Uart : SerialPort
{
private int _receiveTimeout;
public int ReceiveTimeout { get => _receiveTimeout; set => _receiveTimeout = value; }
static private string ComPortName = "";
/// <summary>
/// It builds PortName using ComPortNum parameter and opens SerialPort.
/// </summary>
/// <param name="ComPortNum"></param>
public Uart(int ComPortNum) : base()
{
base.BaudRate = 115200; // default value
_receiveTimeout = 2000;
ComPortName = "COM" + ComPortNum;
try
{
base.PortName = ComPortName;
base.Open();
}
catch (UnauthorizedAccessException ex)
{
Console.WriteLine("Error: Port {0} is in use", ComPortName);
}
catch (Exception ex)
{
Console.WriteLine("Uart exception: " + ex);
}
} //Uart()
/// <summary>
/// Private property returning positive only Environment.TickCount
/// </summary>
private int _tickCount { get => Environment.TickCount & Int32.MaxValue; }
/// <summary>
/// It uses SerialPort.BaseStream rather SerialPort functionality .
/// It Receives up to maxLen number bytes of data,
/// Or throws TimeoutException if no any data arrived during ReceiveTimeout.
/// It works likes socket-recv routine (explanation in body).
/// Returns:
/// totalReceived - bytes,
/// TimeoutException,
/// -1 in non-ComPortNum Exception
/// </summary>
/// <param name="buffer"></param>
/// <param name="maxLen"></param>
/// <returns></returns>
public int Recv(byte[] buffer, int maxLen)
{
/// The routine works in "pseudo-blocking" mode. It cycles up to first
/// data received using BaseStream.ReadTimeout = TimeOutSpan (2 ms).
/// If no any message received during ReceiveTimeout property,
/// the routine throws TimeoutException
/// In other hand, if any data has received, first no-data cycle
/// causes to exit from routine.
int TimeOutSpan = 2;
// counts delay in TimeOutSpan-s after end of data to break receive
int EndOfDataCnt;
// pseudo-blocking timeout counter
int TimeOutCnt = _tickCount + _receiveTimeout;
//number of currently received data bytes
int justReceived = 0;
//number of total received data bytes
int totalReceived = 0;
BaseStream.ReadTimeout = TimeOutSpan;
//causes (2+1)*TimeOutSpan delay after end of data in UART stream
EndOfDataCnt = 2;
while (_tickCount < TimeOutCnt && EndOfDataCnt > 0)
{
try
{
justReceived = 0;
justReceived = base.BaseStream.Read(buffer, totalReceived, maxLen - totalReceived);
totalReceived += justReceived;
if (totalReceived >= maxLen)
break;
}
catch (TimeoutException)
{
if (totalReceived > 0)
EndOfDataCnt--;
}
catch (Exception ex)
{
totalReceived = -1;
base.Close();
Console.WriteLine("Recv exception: " + ex);
break;
}
} //while
if (totalReceived == 0)
{
throw new TimeoutException();
}
else
{
return totalReceived;
}
} // Recv()
} // Uart
_SerialPort.DataReceived
_ イベントの使用はオプションです。 _SerialPort.ReadTimeout
_を使用して適切なタイムアウトを設定し、ポートに何かを書き込んだ後、完全に応答するまで継続的に SerialPort.Read()
を呼び出すことができます。
さらに、 _SerialPort.BaseStream
_ プロパティを使用して、基になる Stream
インスタンスを抽出できます。 Stream
を使用する利点は、さまざまなデコレータを簡単に使用できることです。
_var port = new SerialPort();
// LoggingStream inherits Stream, implements IDisposable, needen abstract methods and
// overrides needen virtual methods.
Stream portStream = new LoggingStream(port.BaseStream);
portStream.Write(...); // Logs write buffer.
portStream.Read(...); // Logs read buffer.
_
詳細については、次を確認してください。