c#不断从串口请求和处理数据

时间:2017-08-24 13:01:12

标签: c# serial-port

经过很长一段时间我需要再次编程。 我需要经常通过串口从汽车ecu(?数据)发送命令。

然后我需要接收我将要处理的数据以显示在显示器上(思考赛车显示器具有汽车参数,如温度等)。 我需要经常这样做

我想知道在我开始之前最好的方法吗?

1个用于不断询问和接收数据的线程 用于在屏幕中显示数据的主线程。 (将数据存储在缓冲区中并保存一分钟左右)

任何人都有任何提示指南或如何开始这个。 我测试了使用终端接收数据,我收回了数据,因此配置正在运行。

发送? data =>我得到了数据。

2 个答案:

答案 0 :(得分: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...
}

答案 1 :(得分:0)

我们在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处理程序中进行更多检查,因为事件存在一些问题。使用这种方法,您可以对业务逻辑进行更多抽象。

希望这有帮助。