如何从串口获得多行结果

时间:2018-01-01 08:27:34

标签: c# .net winforms serial-port

我正在使用winform项目并尝试向串口发送命令并从中接收数据。我期待一个多行响应,但使用下面的代码我只得到响应的第一行。我不想使用ReadExisting

{
    SerialPort mySerialPort = new SerialPort("COM5");

    mySerialPort.BaudRate = 115200;
    mySerialPort.Parity = Parity.None;
    mySerialPort.StopBits = StopBits.One;
    mySerialPort.DataBits = 8;
    mySerialPort.Handshake = Handshake.None;
    mySerialPort.DtrEnable = true;
    mySerialPort.RtsEnable = true;

    mySerialPort.Open();

    var command = Command.Authentication.GetStringValue();
    mySerialPort.WriteLine(command);               

    mySerialPort.DataReceived += new SerialDataReceivedEventHandler(_serialPort_DataReceived);

    string _response = mySerialPort.ReadLine();

    mySerialPort.Close();
}       
void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    SerialPort sp = (SerialPort)sender;
    sp.ReadLine();
}

我的回答如下:

REQ: SUCCESS
REQ: MAC_ADDR:000D6F111C5DB14C
REQ: FWINFO: Build 01
REQ: HWINFO: Gen3 R0c

我试过了:

{
    _serialPort = new SerialPort(
        _currentSerialSettings.PortName = Home.PortName,
        _currentSerialSettings.BaudRate,
        _currentSerialSettings.Parity,
        _currentSerialSettings.DataBits,
        _currentSerialSettings.StopBits);

    _serialPort.Open();

    //send command
    _serialPort.WriteLine(Command.Get_Device_List.GetStringValue());

    Thread t = new Thread(ReadThread);            
    t.Start(_serialPort);
}

private void ReadThread(object context)
{
    SerialPort serialPort = context as SerialPort;

    while (serialPort.IsOpen)
    {
        string inData = serialPort.ReadLine();
        Debug.WriteLine(inData);                
    }
}

以下是两个问题:

  1. 我想在上层方法中获取数据,而不是在ReadThread中。

  2. 它没有提供最后的数据。

  3. 我错过了什么吗?

    旁注:如果我多次使用mySerialPort.ReadLine();,那么我能够捕获整个响应,但响应可能因命令而异。目前,当数据不存在时ReadLine崩溃

2 个答案:

答案 0 :(得分:1)

请尝试以下代码。使用异步读取并在处理命令之前等待行尾的返回:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            SerialPort _serialPort = new SerialPort("COM5");

            _serialPort.BaudRate = 115200;
            _serialPort.Parity = Parity.None;
            _serialPort.StopBits = StopBits.One;
            _serialPort.DataBits = 8;
            _serialPort.Handshake = Handshake.None;
            _serialPort.DtrEnable = true;
            _serialPort.RtsEnable = true;

            _serialPort.DataReceived += (AsyncRead);
            _serialPort.Open();


        }
        string inputData = "";
        private void AsyncRead(object sender, SerialDataReceivedEventArgs e)
        {
            SerialPort serialPort = sender as SerialPort;
            string inData = serialPort.ReadExisting();
            inputData += inData;

            int returnIndex = inputData.IndexOf('\n');
            if(returnIndex >= 0)
            {
                string command = inputData.Substring(0, returnIndex);
                //remove command from inputData
                inputData = inputData.Substring(returnIndex + 1);

                //test if command is just a return
                if (command.Length > 0)
                {
                    ProcessCommand(command);
                }
            }
        }
        private void ProcessCommand(string inputLine)
        {
        }

    }
}

带队列和计时器的代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;

namespace WindowsFormsApplication8
{
    public partial class Form1 : Form
    {
        static List<string> queue = new List<string>();
        public Form1()
        {
            InitializeComponent();
            Timer timer1 = new Timer();
            timer1.Tick += new EventHandler(timer1_Tick);
            timer1.Interval = 500;
            timer1.Start();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            SerialPort _serialPort = new SerialPort("COM5");

            _serialPort.BaudRate = 115200;
            _serialPort.Parity = Parity.None;
            _serialPort.StopBits = StopBits.One;
            _serialPort.DataBits = 8;
            _serialPort.Handshake = Handshake.None;
            _serialPort.DtrEnable = true;
            _serialPort.RtsEnable = true;

            _serialPort.DataReceived += (AsyncRead);
            _serialPort.Open();


        }
        string inputData = "";
        private void AsyncRead(object sender, SerialDataReceivedEventArgs e)
        {
            SerialPort serialPort = sender as SerialPort;
            string inData = serialPort.ReadExisting();
            inputData += inData;

            int returnIndex = inputData.IndexOf('\n');
            if (returnIndex >= 0)
            {
                string command = inputData.Substring(0, returnIndex);
                //remove command from inputData
                inputData = inputData.Substring(returnIndex + 1);

                //test if command is just a return
                if (command.Length > 0)
                {
                    queue.Add(command);
                }
            }
        }
        private void timer1_Tick(object sender, EventArgs e)
        {

            if (queue.Count > 0)
            {
                string command = queue[0];
                queue.RemoveAt(0);
            }
        }

    }
}

答案 1 :(得分:1)

我很少尝试

  1. 要使此异步,您希望使用DataReceived事件
  2. 您应该在发送命令之前监听DataReceived事件。
  3. DataReceived事件使用名为 ReceivedBytesThreshold 的属性。在我的示例代码中,我将其设置为1.这意味着如果串行缓冲区中有一个或多个字节,则会引发DataReceived事件。
  4. 您会注意到在DataReceived事件中,您希望尽可能快地读取缓冲区中的每个数据字节。

    @events.route('/api/v1/user')
    def getloggeduser():
        print(g)
        import pdb; pdb.set_trace()
        return g