[英]c# constantly requesting and processing data from serial port
长时间后,我需要再次编程。 我需要不断从汽车ecu(?数据)通过串行端口发送命令。
然后,我需要接收将要处理的数据,以将其显示在显示器上(想想带有诸如温度等汽车参数的赛车显示器)。 我需要经常这样做
我想知道在开始之前最好的方法是什么?
1个线程,用于不断询问和接收数据。主线程用于在屏幕上显示数据。 (将数据存储在缓冲区中并每分钟保存一次)
任何人都有任何提示指南,或者如何开始。 我测试了使用终端接收数据,并获取了数据,因此配置工作正常。
发送了? 数据=>我得到了数据。
您可以只使用SerialPort类并配置BaudRate,DataBits等。然后等待DataReceived事件触发:
public class SerialPortReader
{
public SerialPortReader(string yourPortName)
{
var serialPort = new SerialPort() {
PortName = yourPortName,
BaudRate = 57600; //This will control the rate at what you receive the data
}
serialPort.DataReceived += new SerialDataReceivedEventHandler(OnDataReceived);
serialPort.Open();
}
}
public void OnDataReceived(object sender, SerialDataReceivedEventArgs e)
{
var serialPort = (SerialPort)sender;
// Process your data reading the stream with Read, ReadLine etc...
}
我们在SerialPort
处理程序中使用的方法是,使AutoResetEvent
在端口有响应时立即得到通知。
FrameWork的SerialPort
类在集成的DataReceived
事件中存在一些问题。 当没有完整的软件包可用时(如果您定义了答案长度),有时会触发该事件。 因此,您应该检查所需的答案长度。
我们的精简实施:
public class Serialport
{
private SerialPort _serialPort;
private List<byte> _buffer;
private AutoResetEvent _autoResetEvent;
private const int WriteTimeOut = 5;
private event EventHandler ReceivedDataChanged;
public Serialport()
{
_serialPort = new SerialPort();
// set PortName, BaudRate etc
_serialPort.Open();
_serialPort.DiscardInBuffer();
_serialPort.DiscardOutBuffer();
_serialPort.DataReceived += ReceiveData;
}
private void ReceiveData(object sender, SerialDataReceivedEventArgs e)
{
var bytes = _serialPort.BytesToRead;
byte[] buffer = new byte[bytes];
if (_serialPort.IsOpen)
{
_serialPort.BaseStream.Read(buffer, 0, bytes);
_buffer.AddRange(buffer);
}
ReceivedDataChanged?.Invoke(this, new ReceivedBytesEventArgs(_buffer.ToArray()));
_buffer.Clear();
}
private void SendData(byte[] message, int answerLength)
{
_serialPort.ReceivedBytesThreshold = answerLength;
_serialPort.WriteTimeout = WriteTimeOut;
_serialPort.Write(message, 0, message.Length);
}
public string SendDataCommand()
{
if (_serialPort.IsOpen)
{
ReceivedDataChanged += InterpretAnswer;
SendData(message, length);
if (_autoResetEvent.WaitOne(100))
{
ReceivedDataChanged -= InterpretAnswer;
//Data Received and interpreted and send to the caller
return _requestAnswer;
}
ReceivedDataChanged -= InterpretAnswer;
}
return "Connection not open";
}
private void InterpretAnswer(object sender, EventArgs e)
{
// handle all interpretation
// Set the event
_autoResetEvent.Set();
}
}
初始化并打开serialPort。 之后,我们连接所有需要的事件并调用SendDataCommand()
方法。 此方法是从某些任务调用的公共可见方法。 这将调用方法SendData
。 一旦有答案,便触发事件并开始解释。 如果解释是在指定的时间内完成的( _autoResetEvent.WaitOne(msToWait)
),则结果将返回给调用方法。 这应该在单独的任务中完成,因此在等待答案时,ui不会阻塞
如前所述,这是一个非常简单的示例。 您应该在收到的SerialPort处理程序中进行更多检查,因为该事件存在一些问题。 通过这种方法,您将对业务逻辑有了更多的抽象。
希望这可以帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.