gpt4 book ai didi

c# - 串行端口轮询和数据处理

转载 作者:太空狗 更新时间:2023-10-29 22:33:04 26 4
gpt4 key购买 nike

我正在尝试通过微 Controller 从传感器的多个串行端口读取数据。每个串口会收到超过2000个测量值(每个测量值7个字节,全部为十六进制)。他们同时开火。现在我正在从 4 个串行端口进行轮询。此外,我将每个测量值转换为字符串并将其附加到 Stringbuilder。当我完成接收数据时,它们将被输出到一个文件中。问题是 CPU 消耗非常高,从 80% 到 100% 不等。

我浏览了一些文章并将 Thread.Sleep(100) 放在最后。当没有数据到来时,它减少了 CPU 时间。当 BytesToRead 小于 100 时,我还将 Thread.Sleep 放在每次轮询的末尾。它只在一定程度上有所帮助。

有人可以建议一个从串口轮询并处理我得到的数据的解决方案吗?也许每次我得到东西时附加都会导致问题?

//I use separate threads for all sensors
private void SensorThread(SerialPort mySerialPort, int bytesPerMeasurement, TextBox textBox, StringBuilder data)
{
textBox.BeginInvoke(new MethodInvoker(delegate() { textBox.Text = ""; }));

int bytesRead;
int t;
Byte[] dataIn;

while (mySerialPort.IsOpen)
{
try
{
if (mySerialPort.BytesToRead != 0)
{
//trying to read a fix number of bytes
bytesRead = 0;
t = 0;
dataIn = new Byte[bytesPerMeasurement];
t = mySerialPort.Read(dataIn, 0, bytesPerMeasurement);
bytesRead += t;
while (bytesRead != bytesPerMeasurement)
{
t = mySerialPort.Read(dataIn, bytesRead, bytesPerMeasurement - bytesRead);
bytesRead += t;
}
//convert them into hex string
StringBuilder s = new StringBuilder();
foreach (Byte b in dataIn) { s.Append(b.ToString("X") + ","); }
var line = s.ToString();

var lineString = string.Format("{0} ---- {2}",
line,
mySerialPort.BytesToRead);
data.Append(lineString + "\r\n");//append a measurement to a huge Stringbuilder...Need a solution for this.

////use delegate to change UI thread...
textBox.BeginInvoke(new MethodInvoker(delegate() { textBox.Text = line; }));

if (mySerialPort.BytesToRead <= 100) { Thread.Sleep(100); }
}
else{Thread.Sleep(100);}

}
catch (Exception ex)
{
//MessageBox.Show(ex.ToString());
}
}


}

最佳答案

这不是一个好方法,处理 DataReceived 事件要好得多。

基本上,对于串行端口,有一个运行良好的 3 阶段过程。

  • 从串口接收数据
  • 等到你有相关的数据 block
  • 解读数据

类似的东西

class DataCollector
{
private readonly Action<List<byte>> _processMeasurement;
private readonly string _port;
private SerialPort _serialPort;
private const int SizeOfMeasurement = 4;
List<byte> Data = new List<byte>();

public DataCollector(string port, Action<List<byte>> processMeasurement)
{
_processMeasurement = processMeasurement;
_serialPort = new SerialPort(port);
_serialPort.DataReceived +=SerialPortDataReceived;
}

private void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e)
{
while(_serialPort.BytesToRead > 0)
{
var count = _serialPort.BytesToRead;
var bytes = new byte[count];
_serialPort.Read(bytes, 0, count);
AddBytes(bytes);
}
}

private void AddBytes(byte[] bytes)
{
Data.AddRange(bytes);
while(Data.Count > SizeOfMeasurement)
{
var measurementData = Data.GetRange(0, SizeOfMeasurement);
Data.RemoveRange(0, SizeOfMeasurement);
if (_processMeasurement != null) _processMeasurement(measurementData);
}

}
}

注意:Add Bytes 不断收集数据,直到您有足够的数据可以算作一个测量值,或者如果您得到一连串的数据,将其分成单独的测量值……这样您一次可以获得 1 个字节,2 个接下来,再下一个,然后它将把它变成一个测量值。大多数情况下,如果您的 micro 突发发送它,它会作为一个发送,但有时它会分成 2 个。

然后在某个地方你可以做

var collector = new DataCollector("COM1", ProcessMeasurement);

  private void ProcessMeasurement(List<byte> bytes)
{
// this will get called for every measurement, so then
// put stuff into a text box.... or do whatever
}

关于c# - 串行端口轮询和数据处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15124132/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com