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 _buffer = new List(); // 缓存接收到的数据 public bool CommunicationError = false; private DateTime _lastTime = DateTime.Now; private MCUInterface _interface; public EmbeddedCommunication(string name, int baudRate) { _interface = new MCUInterface(); _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.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); } } } } }