如何从串口获得多行结果
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何从串口获得多行结果相关的知识,希望对你有一定的参考价值。
我正在使用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);
}
}
以下是两个问题:
- 我想在上层方法中获取数据,而不是在
ReadThread
中。 - 它没有给出最后的数据。
我错过了什么吗?
旁注:如果我多次使用mySerialPort.ReadLine();
,那么我能够捕获整个响应,但响应可能因命令而异。目前,当数据不存在时,它会在ReadLine
上崩溃
答案
我很少尝试
- 要使此异步,您希望使用DataReceived事件
- 您应该在发送命令之前监听DataReceived事件。
- DataReceived事件使用名为ReceivedBytesThreshold的属性。在我的示例代码中,我将其设置为1.这意味着如果串行缓冲区中有一个或多个字节,则会引发DataReceived事件。
您会注意到,在DataReceived事件中,您希望尽可能快地读取缓冲区中的每个数据字节。
class Program
{
static void Main(string[] args)
{
var serial = Setup();
// send your command from here
//var command = Command.Authentication.GetStringValue();
//serial.WriteLine(command);
Console.ReadLine();
}
static SerialPort Setup()
{
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.ReceivedBytesThreshold = 1;
serialport.DataReceived += serialPort_DataReceived;
serialport.Open();
return serialport;
}
private static void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
var s = (SerialPort) sender;
int n;
var data = new List<byte>();
do
{
n = s.BytesToRead;
var buffer = new byte[n];
try
{
var size = s.Read(buffer, 0, buffer.Length);
data.AddRange(buffer);
}
catch (Exception ex)
{
}
} while (n > 0);
// you should raise your own event passing your data to your ui to exit this method
// for demo only
var yourdata = Encoding.ASCII.GetString(data.ToArray());
Console.WriteLine(yourdata);
}
}
另一答案
请尝试以下代码。使用异步读取并在处理命令之前等待行尾返回:
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('
');
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('
');
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);
}
}
}
}
以上是关于如何从串口获得多行结果的主要内容,如果未能解决你的问题,请参考以下文章