Files
2026-07-21 11:11:01 +08:00

182 lines
7.5 KiB
C#

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);
}
}
}
}
}