Tim*_*ang 5 c# serial-port polling
我试图从传感器到微控制器的几个串口读取.每个串口将接收超过2000个测量值(每个测量值为7个字节,全部为十六进制).他们同时开枪.现在我正在从4个串口进行轮询.此外,我将每个测量值转换为String并将其附加到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());
}
}
}
Run Code Online (Sandbox Code Playgroud)
这不是一个好方法,它可以更好地处理DataReceived事件.
基本上有串口,有一个3阶段的过程,运作良好.
所以像
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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
注意:添加字节会一直收集数据,直到您有足够的数据作为测量值,或者如果您获得数据突发,则将其分成单独的测量值....这样您就可以获得1个字节一次,2个下一个,以及接下来再做1个,然后将它转变为测量值.大多数情况下,如果你的微型发送它一个爆发,它将作为一个进来,但有时它将被分成2.
然后你可以做的地方
var collector = new DataCollector("COM1", ProcessMeasurement);
Run Code Online (Sandbox Code Playgroud)
和
private void ProcessMeasurement(List<byte> bytes)
{
// this will get called for every measurement, so then
// put stuff into a text box.... or do whatever
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9729 次 |
| 最近记录: |