update
This commit is contained in:
@@ -0,0 +1,181 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO.Ports;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using FundamentalLib;
|
||||
using Medulla;
|
||||
|
||||
namespace MedullaAdapter
|
||||
{
|
||||
public class EmbeddedCommunication
|
||||
{
|
||||
private SerialPort _port;
|
||||
|
||||
private byte[] _receiveBytes;
|
||||
|
||||
private byte[] _receiveData;
|
||||
|
||||
private const int BufferThreshold = 300; // 缓冲区大小阈值
|
||||
|
||||
private List<byte> _buffer = new List<byte>(); // 缓存接收到的数据
|
||||
|
||||
public bool CommunicationError = false;
|
||||
|
||||
private DateTime _lastTime = DateTime.Now;
|
||||
|
||||
private MCUInterface<DiverCartDefinition> _interface;
|
||||
|
||||
public EmbeddedCommunication(string name, int baudRate)
|
||||
{
|
||||
_interface = new MCUInterface<DiverCartDefinition>();
|
||||
_port = new SerialPort();
|
||||
_port.PortName = name; // 根据你的实际串口名称修改
|
||||
_port.BaudRate = baudRate;
|
||||
_port.Parity = Parity.None;
|
||||
_port.DataBits = 8;
|
||||
_port.StopBits = StopBits.One;
|
||||
_port.Handshake = Handshake.None;
|
||||
_port.Open();
|
||||
_port.DataReceived += OnDataReceived;
|
||||
}
|
||||
|
||||
public void SendMessage(byte[] data)
|
||||
{
|
||||
Hedingben.ToastText($"send to mcu:{BitConverter.ToString(data)}","DiverSend");
|
||||
_port.Write(data, 0, data.Length);
|
||||
}
|
||||
|
||||
public byte[] GetMessage()
|
||||
{
|
||||
return _receiveBytes;
|
||||
}
|
||||
|
||||
private void OnDataReceived(object sender, SerialDataReceivedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
int bytesToRead = _port.BytesToRead;
|
||||
byte[] buffer = new byte[bytesToRead];
|
||||
var startRead = DateTime.Now;
|
||||
_port.Read(buffer, 0, bytesToRead);
|
||||
var time = DateTime.Now - startRead;
|
||||
// 将新接收到的数据添加到缓冲区
|
||||
startRead = DateTime.Now;
|
||||
_buffer.AddRange(buffer);
|
||||
var time2 = DateTime.Now - startRead;
|
||||
Hedingben.ToastText($"buffer length:{_buffer.Count}","bufferDebug");
|
||||
DLog.Log($"buffer length:{_buffer.Count}");
|
||||
//if (_buffer.Count > BufferThreshold)
|
||||
//{
|
||||
// _buffer.Clear();
|
||||
// return;
|
||||
//}
|
||||
|
||||
// 尝试解析缓冲区中的报文
|
||||
var parseTime = DateTime.Now;
|
||||
ParseBuffer();
|
||||
var time3 = DateTime.Now - parseTime;
|
||||
Hedingben.ToastText(
|
||||
$"读取报文时间:{time.TotalMilliseconds},增加到缓存区:{time2.TotalMilliseconds},处理时间:{time3.TotalMilliseconds}",
|
||||
"timeDebug1");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"读取串口数据时发生错误: {ex.Message}"+ex.StackTrace);
|
||||
}
|
||||
}
|
||||
private void ParseBuffer()
|
||||
{
|
||||
while (_buffer.Count >= 7) // 报文的最小长度是 7
|
||||
{
|
||||
// 查找报文头部
|
||||
var findTime = DateTime.Now;
|
||||
int startIndex = _buffer.FindIndex(0, b => b == 0xBB);
|
||||
var time1 = DateTime.Now - findTime;
|
||||
if (startIndex == -1)
|
||||
{
|
||||
// 如果没有找到头部或剩余长度不足最小报文长度,结束解析
|
||||
_buffer.Clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// 确保头部后还有至少 6 个字节
|
||||
if (startIndex + 1 >= _buffer.Count || _buffer[startIndex + 1] != 0xAA)
|
||||
{
|
||||
// 如果第二字节不是 0xAA,丢弃无效字节
|
||||
_buffer.RemoveAt(startIndex);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 检查数据段长度
|
||||
if (startIndex + 4 >= _buffer.Count) break; // 数据不足,等待下次接收
|
||||
int dataLength = _buffer[startIndex + 2] | (_buffer[startIndex + 3] << 8);
|
||||
|
||||
// 计算报文总长度
|
||||
int totalLength = dataLength + 7;
|
||||
|
||||
// 检查总长度是否足够
|
||||
if (startIndex + totalLength > _buffer.Count) break; // 数据不足,等待下次接收
|
||||
|
||||
// 检查尾部是否是 0xCC 0xEE
|
||||
if (_buffer[startIndex + totalLength - 2] == 0xCC && _buffer[startIndex + totalLength - 1] == 0xEE)
|
||||
{
|
||||
var time2 = DateTime.Now - findTime;
|
||||
var copyTime = DateTime.Now;
|
||||
// 提取完整报文
|
||||
_receiveBytes = _buffer.Skip(startIndex).Take(totalLength).ToArray();
|
||||
var time3 = DateTime.Now - copyTime;
|
||||
if (_receiveBytes[5] == 0xA0)
|
||||
{
|
||||
var dataLength1 = BitConverter.ToUInt32(_receiveBytes, 6);
|
||||
var data1 = new byte[dataLength1];
|
||||
Array.Copy(_receiveBytes, 14, data1, 0, dataLength1);
|
||||
var notifyTime = DateTime.Now;
|
||||
MCUInterface<DiverCartDefinition>.NotifyLowerData("default", data1);
|
||||
var time4 = DateTime.Now - notifyTime;
|
||||
var logBytes = new byte[BitConverter.ToInt32(_receiveBytes, 10)];
|
||||
var memorySize = BitConverter.ToInt32(_receiveBytes, 6);
|
||||
if (logBytes.Length > 0)
|
||||
{
|
||||
Array.Copy(_receiveBytes, 14 + memorySize, logBytes, 0, logBytes.Length);
|
||||
string log = System.Text.Encoding.ASCII.GetString(logBytes);
|
||||
string[] result = log.Split(new[] { "\r\n", "\n" }, StringSplitOptions.None);
|
||||
for (int i = 0; i < result.Length; i++)
|
||||
{
|
||||
Hedingben.ToastText(result[i], $"mcuLog" + i);
|
||||
}
|
||||
}
|
||||
|
||||
Hedingben.ToastText(
|
||||
$"find head time:{time1.TotalMilliseconds},find total time:{time2.TotalMilliseconds},copy time:{time3.TotalMilliseconds},notify time:{time4.TotalMilliseconds}","timeDebug2");
|
||||
}
|
||||
|
||||
Hedingben.ToastText(
|
||||
$"receive from mcu:{BitConverter.ToString(_receiveBytes)},time:{(DateTime.Now - _lastTime).TotalMilliseconds}",
|
||||
"DiverReceive");
|
||||
if ((DateTime.Now - _lastTime).TotalMilliseconds > 200)
|
||||
{
|
||||
Hedingben.ToastText($"{(DateTime.Now - _lastTime).TotalMilliseconds}ms no message from diver","DiverTimeout");
|
||||
}
|
||||
_lastTime = DateTime.Now;
|
||||
// 从缓冲区中移除已解析的报文
|
||||
_buffer.RemoveRange(0, startIndex + totalLength);
|
||||
return; // 成功解析一条报文后退出本轮解析
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// 如果尾部无效,丢弃头部并继续解析
|
||||
DLog.Log("DIVER报文无效");
|
||||
Console.WriteLine("DIVER报文无效");
|
||||
var errorBytes = _buffer.Skip(startIndex).Take(totalLength).ToArray();
|
||||
DLog.Log("错误报文"+string.Join(" ",errorBytes.Select(p=>$"{p:X2}")));
|
||||
_buffer.RemoveAt(startIndex);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user