改动8
This commit is contained in:
@@ -12,6 +12,7 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using System.Windows.Interop;
|
||||
@@ -27,7 +28,19 @@ namespace CapMachine.Wpf.CanDrive
|
||||
private readonly IContainerProvider ContainerProvider;
|
||||
private readonly object _dbcParserLock = new object();
|
||||
private readonly object _canSendLock = new object();
|
||||
private readonly object _recvBufferLock = new object();
|
||||
private const int DbcStringBufferCapacity = 256;
|
||||
private const int RecvBufferSize = 128;
|
||||
|
||||
/// <summary>
|
||||
/// 预分配的接收缓冲区指针,避免每次循环分配/释放
|
||||
/// </summary>
|
||||
private IntPtr RecvMsgBufferPtr = IntPtr.Zero;
|
||||
|
||||
/// <summary>
|
||||
/// 接收缓冲区对应的托管数组
|
||||
/// </summary>
|
||||
private readonly USB2CAN.CAN_MSG[] RecvMsgBuffer = new USB2CAN.CAN_MSG[RecvBufferSize];
|
||||
|
||||
/// <summary>
|
||||
/// 实例化函数
|
||||
@@ -508,12 +521,12 @@ namespace CapMachine.Wpf.CanDrive
|
||||
/// <summary>
|
||||
/// CycleRevice 扫描Task
|
||||
/// </summary>
|
||||
private static Task CycleReviceTask { get; set; }
|
||||
private Task? CycleReviceTask { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// CycleSend 扫描Task
|
||||
/// </summary>
|
||||
private static Task CycleSendTask { get; set; }
|
||||
private Task? CycleSendTask { get; set; }
|
||||
|
||||
StringBuilder ValueSb = new StringBuilder(16);
|
||||
|
||||
@@ -551,7 +564,7 @@ namespace CapMachine.Wpf.CanDrive
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 循环获取CAN消息
|
||||
/// 循环获取CAN消息(使用预分配缓冲区,避免每次循环内存分配/释放)
|
||||
/// </summary>
|
||||
public void StartCycleReviceCanMsg()
|
||||
{
|
||||
@@ -560,105 +573,105 @@ namespace CapMachine.Wpf.CanDrive
|
||||
return;
|
||||
}
|
||||
|
||||
// 预分配接收缓冲区(仅在首次或已释放后分配)
|
||||
EnsureRecvBufferAllocated();
|
||||
|
||||
CycleReviceTask = Task.Run(async () =>
|
||||
{
|
||||
var msgSize = Marshal.SizeOf(typeof(USB2CAN.CAN_MSG));
|
||||
double[] valueDouble = new double[1];
|
||||
|
||||
while (IsCycleRevice)
|
||||
{
|
||||
await Task.Delay(ReviceCycle);
|
||||
try
|
||||
{
|
||||
IntPtr msgPtRead = IntPtr.Zero;
|
||||
try
|
||||
int CanNum;
|
||||
lock (_recvBufferLock)
|
||||
{
|
||||
//另外一个CAN通道读取数据
|
||||
USB2CAN.CAN_MSG[] CanMsgBuffer = new USB2CAN.CAN_MSG[128];
|
||||
//申请数据缓冲区
|
||||
msgPtRead = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(USB2CAN.CAN_MSG)) * CanMsgBuffer.Length);
|
||||
int CanNum = USB2CAN.CAN_GetMsgWithSize(DevHandle, ReadCANIndex, msgPtRead, CanMsgBuffer.Length);
|
||||
if (RecvMsgBufferPtr == IntPtr.Zero) break;
|
||||
CanNum = USB2CAN.CAN_GetMsgWithSize(DevHandle, ReadCANIndex, RecvMsgBufferPtr, RecvBufferSize);
|
||||
|
||||
if (CanNum > 0)
|
||||
{
|
||||
for (int i = 0; i < CanNum; i++)
|
||||
{
|
||||
//CanMsgBuffer[i] = (USB2CAN.CAN_MSG)Marshal.PtrToStructure((IntPtr)((UInt32)msgPtRead + i * Marshal.SizeOf(typeof(USB2CAN.CAN_MSG))), typeof(USB2CAN.CAN_MSG)); //有溢出报错
|
||||
CanMsgBuffer[i] = (USB2CAN.CAN_MSG)Marshal.PtrToStructure((IntPtr)(msgPtRead + i * Marshal.SizeOf(typeof(USB2CAN.CAN_MSG))), typeof(USB2CAN.CAN_MSG));
|
||||
RecvMsgBuffer[i] = (USB2CAN.CAN_MSG)Marshal.PtrToStructure(
|
||||
(IntPtr)(RecvMsgBufferPtr + i * msgSize), typeof(USB2CAN.CAN_MSG));
|
||||
|
||||
//Console.WriteLine("CanMsg[{0}].ID = 0x{1}", i, CanMsgBuffer[i].ID.ToString("X8"));
|
||||
//Console.WriteLine("CanMsg[{0}].TimeStamp = {1}", i, CanMsgBuffer[i].TimeStamp);
|
||||
//Console.Write("CanMsg[{0}].Data = ", i);
|
||||
//Console.WriteLine("");
|
||||
|
||||
//报文给高速记录的服务
|
||||
HighSpeedDataService.AppendOrUpdateMsg(new Models.HighSpeed.CommMsg()
|
||||
{
|
||||
Category = "CAN",
|
||||
MsgInfo = "0x" + CanMsgBuffer[i].ID.ToString("X8"),
|
||||
MsgData = BitConverter.ToString(CanMsgBuffer[i].Data),
|
||||
MsgInfo = "0x" + RecvMsgBuffer[i].ID.ToString("X8"),
|
||||
MsgData = BitConverter.ToString(RecvMsgBuffer[i].Data),
|
||||
Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")
|
||||
});
|
||||
}
|
||||
}
|
||||
else if (CanNum == 0)
|
||||
{
|
||||
//Console.WriteLine("No CAN data!");
|
||||
}
|
||||
else
|
||||
{
|
||||
//Console.WriteLine("Get CAN data error!");
|
||||
}
|
||||
if (CanNum > 0)
|
||||
{
|
||||
lock (_dbcParserLock)
|
||||
{
|
||||
//将CAN消息数据填充到信号里面,用DBC解析数据
|
||||
CAN_DBCParser.DBC_SyncCANMsgToValue(DBCHandle, msgPtRead, CanNum);
|
||||
}
|
||||
|
||||
double[] valueDouble = new double[1];
|
||||
//循环获取消息的数据
|
||||
foreach (var item in ListCanDbcModel)
|
||||
{
|
||||
//有配置的名称的,认为是有用的,则需要读取数据
|
||||
//if (!string.IsNullOrEmpty(item.Name))
|
||||
//{
|
||||
valueDouble[0] = 0;
|
||||
CAN_DBCParser.DBC_GetSignalValue(DBCHandle, new StringBuilder(item.MsgName), new StringBuilder(item.SignalName), valueDouble);
|
||||
item.SignalRtValue = valueDouble[0].ToString();
|
||||
//}
|
||||
}
|
||||
if (CanNum > 0)
|
||||
{
|
||||
lock (_dbcParserLock)
|
||||
{
|
||||
lock (_recvBufferLock)
|
||||
{
|
||||
if (RecvMsgBufferPtr == IntPtr.Zero) break;
|
||||
CAN_DBCParser.DBC_SyncCANMsgToValue(DBCHandle, RecvMsgBufferPtr, CanNum);
|
||||
}
|
||||
|
||||
foreach (var item in ListCanDbcModel)
|
||||
{
|
||||
valueDouble[0] = 0;
|
||||
CAN_DBCParser.DBC_GetSignalValue(DBCHandle, new StringBuilder(item.MsgName), new StringBuilder(item.SignalName), valueDouble);
|
||||
item.SignalRtValue = valueDouble[0].ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (msgPtRead != IntPtr.Zero)
|
||||
{
|
||||
//释放数据缓冲区,必须释放,否则程序运行一段时间后会报内存不足
|
||||
Marshal.FreeHGlobal(msgPtRead);
|
||||
}
|
||||
}
|
||||
Thread.Sleep(10);
|
||||
|
||||
////获取信号值并打印出来
|
||||
//StringBuilder ValueStr = new StringBuilder(32);
|
||||
//CAN_DBCParser.DBC_GetSignalValueStr(DBCHandle, new StringBuilder("msg_moto_speed"), new StringBuilder("moto_speed"), ValueStr);
|
||||
//Console.WriteLine("moto_speed = {0}", ValueStr);
|
||||
//CAN_DBCParser.DBC_GetSignalValueStr(DBCHandle, new StringBuilder("msg_oil_pressure"), new StringBuilder("oil_pressure"), ValueStr);
|
||||
//Console.WriteLine("oil_pressure = {0}", ValueStr);
|
||||
//CAN_DBCParser.DBC_GetSignalValueStr(DBCHandle, new StringBuilder("msg_speed_can"), new StringBuilder("speed_can"), ValueStr);
|
||||
//Console.WriteLine("speed_can = {0}", ValueStr);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//LogService.Info($"时间:{DateTime.Now.ToString()}-【Meter】-{ex.Message}");
|
||||
Console.WriteLine($"CAN循环接收异常: {ex.Message}");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 确保接收缓冲区已分配
|
||||
/// </summary>
|
||||
private void EnsureRecvBufferAllocated()
|
||||
{
|
||||
lock (_recvBufferLock)
|
||||
{
|
||||
if (RecvMsgBufferPtr == IntPtr.Zero)
|
||||
{
|
||||
RecvMsgBufferPtr = Marshal.AllocHGlobal(
|
||||
Marshal.SizeOf(typeof(USB2CAN.CAN_MSG)) * RecvBufferSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 释放接收缓冲区
|
||||
/// </summary>
|
||||
private void FreeRecvBuffer()
|
||||
{
|
||||
lock (_recvBufferLock)
|
||||
{
|
||||
if (RecvMsgBufferPtr != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeHGlobal(RecvMsgBufferPtr);
|
||||
RecvMsgBufferPtr = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#region 精确发送报文数据
|
||||
|
||||
// 添加取消标记源字段用于停止任务
|
||||
private CancellationTokenSource CycleSendCts;
|
||||
private CancellationTokenSource? CycleSendCts;
|
||||
|
||||
/// <summary>
|
||||
/// 计算每毫秒对应的ticks数(只需计算一次)
|
||||
@@ -673,8 +686,6 @@ namespace CapMachine.Wpf.CanDrive
|
||||
private long DelayTicks;
|
||||
private int DelayMs;
|
||||
|
||||
private static readonly Random _random = new Random();
|
||||
|
||||
/// <summary>
|
||||
/// 精确周期发送CAN数据
|
||||
/// </summary>
|
||||
@@ -778,16 +789,13 @@ namespace CapMachine.Wpf.CanDrive
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// 确保在任何情况下(正常退出、异常、取消)都会停止计时器
|
||||
Stopwatcher.Stop();
|
||||
|
||||
// 清理其他可能的资源
|
||||
Console.WriteLine("CAN周期发送任务已结束,资源已清理");
|
||||
Console.WriteLine($"CAN精确周期发送异常: {ex.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
// 确保在任何情况下(正常退出、异常、取消)都会停止计时器
|
||||
Stopwatcher.Stop();
|
||||
Console.WriteLine("CAN周期发送任务已结束,资源已清理");
|
||||
}
|
||||
|
||||
}, token);
|
||||
@@ -807,54 +815,6 @@ namespace CapMachine.Wpf.CanDrive
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 接受CAN消息
|
||||
/// </summary>
|
||||
public void ReciveCanMsg()
|
||||
{
|
||||
//另外一个CAN通道读取数据
|
||||
USB2CAN.CAN_MSG[] CanMsgBuffer = new USB2CAN.CAN_MSG[10];
|
||||
msgPt = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(USB2CAN.CAN_MSG)) * CanMsgBuffer.Length);
|
||||
int CanNum = USB2CAN.CAN_GetMsgWithSize(DevHandle, ReadCANIndex, msgPt, CanMsgBuffer.Length);
|
||||
if (CanNum > 0)
|
||||
{
|
||||
Console.WriteLine("Read CanMsgNum = {0}", CanNum);
|
||||
for (int i = 0; i < CanNum; i++)
|
||||
{
|
||||
CanMsgBuffer[i] = (USB2CAN.CAN_MSG)Marshal.PtrToStructure((IntPtr)((UInt32)msgPt + i * Marshal.SizeOf(typeof(USB2CAN.CAN_MSG))), typeof(USB2CAN.CAN_MSG));
|
||||
Console.WriteLine("CanMsg[{0}].ID = 0x{1}", i, CanMsgBuffer[i].ID.ToString("X8"));
|
||||
//Console.WriteLine("CanMsg[{0}].TimeStamp = {1}",i,CanMsgBuffer[i].TimeStamp);
|
||||
Console.Write("CanMsg[{0}].Data = ", i);
|
||||
for (int j = 0; j < CanMsgBuffer[i].DataLen; j++)
|
||||
{
|
||||
Console.Write("{0} ", CanMsgBuffer[i].Data[j].ToString("X2"));
|
||||
}
|
||||
Console.WriteLine("");
|
||||
}
|
||||
}
|
||||
else if (CanNum == 0)
|
||||
{
|
||||
Console.WriteLine("No CAN data!");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Get CAN data error!");
|
||||
}
|
||||
Console.WriteLine("");
|
||||
|
||||
//将CAN消息数据填充到信号里面
|
||||
CAN_DBCParser.DBC_SyncCANMsgToValue(DBCHandle, msgPt, CanNum);
|
||||
//获取信号值并打印出来
|
||||
StringBuilder ValueStr = new StringBuilder(32);
|
||||
CAN_DBCParser.DBC_GetSignalValueStr(DBCHandle, new StringBuilder("msg_moto_speed"), new StringBuilder("moto_speed"), ValueStr);
|
||||
Console.WriteLine("moto_speed = {0}", ValueStr);
|
||||
CAN_DBCParser.DBC_GetSignalValueStr(DBCHandle, new StringBuilder("msg_oil_pressure"), new StringBuilder("oil_pressure"), ValueStr);
|
||||
Console.WriteLine("oil_pressure = {0}", ValueStr);
|
||||
CAN_DBCParser.DBC_GetSignalValueStr(DBCHandle, new StringBuilder("msg_speed_can"), new StringBuilder("speed_can"), ValueStr);
|
||||
Console.WriteLine("speed_can = {0}", ValueStr);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 关闭设备
|
||||
/// </summary>
|
||||
@@ -862,22 +822,54 @@ namespace CapMachine.Wpf.CanDrive
|
||||
{
|
||||
IsCycleRevice = false;
|
||||
IsCycleSend = false;
|
||||
|
||||
// 停止精确发送并释放CTS
|
||||
try
|
||||
{
|
||||
StopCycleSendMsg();
|
||||
}
|
||||
catch
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"停止CAN发送异常: {ex.Message}");
|
||||
}
|
||||
|
||||
// 等待发送任务结束
|
||||
try
|
||||
{
|
||||
var task = CycleReviceTask;
|
||||
if (task != null && !task.IsCompleted)
|
||||
var sendTask = CycleSendTask;
|
||||
if (sendTask != null && !sendTask.IsCompleted)
|
||||
{
|
||||
task.Wait(TimeSpan.FromMilliseconds(ReviceCycle + 500));
|
||||
sendTask.Wait(TimeSpan.FromMilliseconds(SendCycle * 3 + 500));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"等待CAN发送任务结束异常: {ex.Message}");
|
||||
}
|
||||
|
||||
// 等待接收任务结束
|
||||
try
|
||||
{
|
||||
var recvTask = CycleReviceTask;
|
||||
if (recvTask != null && !recvTask.IsCompleted)
|
||||
{
|
||||
recvTask.Wait(TimeSpan.FromMilliseconds(ReviceCycle + 500));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"等待CAN接收任务结束异常: {ex.Message}");
|
||||
}
|
||||
|
||||
// 释放接收缓冲区
|
||||
FreeRecvBuffer();
|
||||
|
||||
// 释放CTS资源
|
||||
try
|
||||
{
|
||||
CycleSendCts?.Dispose();
|
||||
CycleSendCts = null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
@@ -222,7 +222,7 @@ namespace CapMachine.Wpf.Services
|
||||
{
|
||||
ToomossCanDrive.IsCycleSend = true;
|
||||
ToomossCanDrive.CmdData = CmdData;
|
||||
ToomossCanDrive.StartCycleSendMsg();
|
||||
ToomossCanDrive.StartPrecisionCycleSendMsg();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -231,7 +231,7 @@ namespace CapMachine.Wpf.Services
|
||||
}
|
||||
else
|
||||
{
|
||||
ToomossCanDrive.IsCycleSend = false;
|
||||
ToomossCanDrive.StopCycleSendMsg();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user