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