Compare commits
No commits in common. "main" and "master" have entirely different histories.
6
BDU.sln
6
BDU.sln
@ -22,8 +22,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "加密狗", "加密狗\加
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BDU", "BDU\BDU.csproj", "{0C2B5CA2-D873-255B-1B76-741346ECA1BB}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BDU", "BDU\BDU.csproj", "{0C2B5CA2-D873-255B-1B76-741346ECA1BB}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZLGCANFD", "ZLGCANFD\ZLGCANFD.csproj", "{307FD972-9EFD-453F-BBF3-92ECA032DA73}"
|
|
||||||
EndProject
|
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@ -58,10 +56,6 @@ Global
|
|||||||
{0C2B5CA2-D873-255B-1B76-741346ECA1BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{0C2B5CA2-D873-255B-1B76-741346ECA1BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{0C2B5CA2-D873-255B-1B76-741346ECA1BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{0C2B5CA2-D873-255B-1B76-741346ECA1BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{0C2B5CA2-D873-255B-1B76-741346ECA1BB}.Release|Any CPU.Build.0 = Release|Any CPU
|
{0C2B5CA2-D873-255B-1B76-741346ECA1BB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{307FD972-9EFD-453F-BBF3-92ECA032DA73}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{307FD972-9EFD-453F-BBF3-92ECA032DA73}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{307FD972-9EFD-453F-BBF3-92ECA032DA73}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{307FD972-9EFD-453F-BBF3-92ECA032DA73}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|||||||
@ -27,10 +27,11 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\ATS_DBContext\ATS_DBContext.csproj" />
|
<ProjectReference Include="..\ATS_DBContext\ATS_DBContext.csproj" />
|
||||||
|
<ProjectReference Include="..\TOSUNCAN\TOSUNCAN.csproj" />
|
||||||
<ProjectReference Include="..\Command\Command.csproj" />
|
<ProjectReference Include="..\Command\Command.csproj" />
|
||||||
<ProjectReference Include="..\Common\Common.csproj" />
|
<ProjectReference Include="..\Common\Common.csproj" />
|
||||||
<ProjectReference Include="..\DeviceCommand\DeviceCommand.csproj" />
|
<ProjectReference Include="..\DeviceCommand\DeviceCommand.csproj" />
|
||||||
<ProjectReference Include="..\ZLGCANFD\ZLGCANFD.csproj" />
|
<ProjectReference Include="..\TOSUNCAN\TOSUNCAN.csproj" />
|
||||||
<ProjectReference Include="..\加密狗\加密狗.csproj" />
|
<ProjectReference Include="..\加密狗\加密狗.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,7 @@ using System.Text;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using ZLGCANFD;
|
using TSMasterCAN;
|
||||||
|
|
||||||
namespace BDU.Logic
|
namespace BDU.Logic
|
||||||
{
|
{
|
||||||
@ -102,9 +102,9 @@ namespace BDU.Logic
|
|||||||
{
|
{
|
||||||
tmpDevice.CommunicationProtocol = device.CommunicationProtocol;
|
tmpDevice.CommunicationProtocol = device.CommunicationProtocol;
|
||||||
CAN.DisConnect();
|
CAN.DisConnect();
|
||||||
var re1 = CAN.Init(ZLGCAN.ZCAN_USBCANFD_100U,0);
|
var re1 = CAN.Init("ATS测试系统");
|
||||||
var re2 = CAN.LoadDBC(SystemConfig.Instance.DBCFilePath, [0, 1, 2, 3], out _);
|
var re2 = CAN.LoadDBC(SystemConfig.Instance.DBCFilePath, [0, 1, 2, 3], out _);
|
||||||
var re3 = CAN.Connect(0,new ZLGCAN.ZCAN_CHANNEL_INIT_CONFIG());
|
var re3 = CAN.Connect();
|
||||||
if (re1 == 0 && re2 == 0 && re3 == 0)
|
if (re1 == 0 && re2 == 0 && re3 == 0)
|
||||||
{
|
{
|
||||||
tmpDevice.Connected = true;
|
tmpDevice.Connected = true;
|
||||||
@ -279,7 +279,7 @@ namespace BDU.Logic
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case "CAN":
|
case "CAN":
|
||||||
var re1 = CAN.Init(ZLGCAN.ZCAN_USBCANFD_100U, 0);
|
var re1 = CAN.Init("ATS测试系统");
|
||||||
//var re2 = CAN.LoadDBC(SystemConfig.Instance.DBCFilePath, [0, 1, 2, 3], out _);
|
//var re2 = CAN.LoadDBC(SystemConfig.Instance.DBCFilePath, [0, 1, 2, 3], out _);
|
||||||
//var re3 = CAN.Connect();
|
//var re3 = CAN.Connect();
|
||||||
if (re1 == 0 && CAN.ConnectFlag)
|
if (re1 == 0 && CAN.ConnectFlag)
|
||||||
|
|||||||
@ -15,7 +15,7 @@ using System.Windows.Input;
|
|||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
using System.Windows.Media.Imaging;
|
using System.Windows.Media.Imaging;
|
||||||
using System.Windows.Shapes;
|
using System.Windows.Shapes;
|
||||||
using ZLGCANFD;
|
using TSMasterCAN;
|
||||||
|
|
||||||
namespace BDU.Views
|
namespace BDU.Views
|
||||||
{
|
{
|
||||||
@ -57,7 +57,7 @@ namespace BDU.Views
|
|||||||
SignalName = DBCParse.MsgDatabase[通道][选中报文].signal_Name[选中信号],
|
SignalName = DBCParse.MsgDatabase[通道][选中报文].signal_Name[选中信号],
|
||||||
CatchID = Guid.NewGuid(),
|
CatchID = Guid.NewGuid(),
|
||||||
LogInterval = TimeSpan.FromMilliseconds(采集间隔),
|
LogInterval = TimeSpan.FromMilliseconds(采集间隔),
|
||||||
MessageID =(int)DBCParse.MsgDatabase[通道][选中报文].msg_id
|
MessageID = DBCParse.MsgDatabase[通道][选中报文].msg_id
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@ -22,10 +22,9 @@ using System.Windows.Media;
|
|||||||
using System.Windows.Media.Imaging;
|
using System.Windows.Media.Imaging;
|
||||||
using System.Windows.Navigation;
|
using System.Windows.Navigation;
|
||||||
using System.Windows.Shapes;
|
using System.Windows.Shapes;
|
||||||
|
using TSMasterCAN;
|
||||||
using static BDU.Models.ParameterModel;
|
using static BDU.Models.ParameterModel;
|
||||||
using Path = System.IO.Path;
|
using Path = System.IO.Path;
|
||||||
using ZLGCANFD;
|
|
||||||
|
|
||||||
namespace BDU.Views
|
namespace BDU.Views
|
||||||
{
|
{
|
||||||
@ -376,12 +375,12 @@ namespace BDU.Views
|
|||||||
|
|
||||||
private void ChannelMapping_Click(object sender, RoutedEventArgs e)
|
private void ChannelMapping_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
//var re = CAN.ShowChannelMappingWindow(true);
|
var re = CAN.ShowChannelMappingWindow(true);
|
||||||
//if (re != 0)
|
if (re != 0)
|
||||||
//{
|
{
|
||||||
// var msg = CAN.GetErrorDescription(re);
|
var msg = CAN.GetErrorDescription(re);
|
||||||
// Log.Error($"同星通道映射界面打开失败:{msg}");
|
Log.Error($"同星通道映射界面打开失败:{msg}");
|
||||||
//}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TestDataInfo_Click(object sender, RoutedEventArgs e)
|
private void TestDataInfo_Click(object sender, RoutedEventArgs e)
|
||||||
@ -451,7 +450,7 @@ namespace BDU.Views
|
|||||||
var re = CAN.LoadDBC(openFileDialog.FileName, [0, 1, 2, 3], out var DataBaseID);
|
var re = CAN.LoadDBC(openFileDialog.FileName, [0, 1, 2, 3], out var DataBaseID);
|
||||||
if (re != 0)
|
if (re != 0)
|
||||||
{
|
{
|
||||||
Log.Error("CAN数据库加载失败:");// + CAN.GetErrorDescription(re)
|
Log.Error("CAN数据库加载失败:" + CAN.GetErrorDescription(re));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -480,7 +479,7 @@ namespace BDU.Views
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var res = CAN.Connect(ZLGCAN.ZCAN_USBCANFD_100U,new ZLGCAN.ZCAN_CHANNEL_INIT_CONFIG());
|
var res = CAN.Connect();
|
||||||
if (res == 0)
|
if (res == 0)
|
||||||
{
|
{
|
||||||
Log.Success($"CAN卡连接成功,返回值:{res}");
|
Log.Success($"CAN卡连接成功,返回值:{res}");
|
||||||
@ -610,7 +609,5 @@ namespace BDU.Views
|
|||||||
{
|
{
|
||||||
new DeviceManageWindow().Show();
|
new DeviceManageWindow().Show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,10 +8,6 @@
|
|||||||
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="CanKit.Adapter.ZLG" Version="0.5.4" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Common\Common.csproj" />
|
<ProjectReference Include="..\Common\Common.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@ -1,7 +0,0 @@
|
|||||||
namespace ZLGCAN
|
|
||||||
{
|
|
||||||
public class Class1
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
419
ZLGCANFD/CAN.cs
419
ZLGCANFD/CAN.cs
@ -1,419 +0,0 @@
|
|||||||
using Common.Attributes;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using static Common.Attributes.ATSCommandAttribute;
|
|
||||||
|
|
||||||
namespace ZLGCANFD
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// ZLG CAN 驱动类 (由 TSMaster CAN 改写)
|
|
||||||
/// </summary>
|
|
||||||
[ATSCommand]
|
|
||||||
[DeviceCategory("CAN卡驱动")]
|
|
||||||
public class CAN
|
|
||||||
{
|
|
||||||
public static event Action ConnectEvent;
|
|
||||||
public static event Action DisConnectEvent;
|
|
||||||
public static bool ConnectFlag { get; set; } = false;
|
|
||||||
|
|
||||||
// 存储 ZLG 的设备句柄和多通道句柄
|
|
||||||
private static nint _deviceHandle = 0;
|
|
||||||
private static Dictionary<uint, nint> _channelHandles = new Dictionary<uint, nint>();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 用于接收 CAN FD 报文的队列
|
|
||||||
/// </summary>
|
|
||||||
private static readonly Queue<ZLGCAN.ZCAN_ReceiveFD_Data> _receivedMessages = new Queue<ZLGCAN.ZCAN_ReceiveFD_Data>();
|
|
||||||
private static readonly object _lock = new object(); // 线程安全锁
|
|
||||||
|
|
||||||
// 接收线程控制标志
|
|
||||||
private static bool _isReceiving = false;
|
|
||||||
public static Action<ZLGCAN.ZCAN_ReceiveFD_Data> listener; // ZLG 接收事件委托
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
||||||
public class ZCAN_CANFD_FRAME
|
|
||||||
{
|
|
||||||
public uint can_id; // 报文ID (包含扩展帧标志位)
|
|
||||||
public byte len; // 数据长度
|
|
||||||
public byte flags; // CANFD标志 (0x01:CANFD, 0x02:BRS, 0x04:ESI)
|
|
||||||
public byte __res0; // 保留
|
|
||||||
public byte __res1; // 保留
|
|
||||||
|
|
||||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
|
|
||||||
public byte[] data; // 数据负载
|
|
||||||
|
|
||||||
// --- 添加以下属性以解决报错并适配旧代码 ---
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 模拟 eff 字段:1表示扩展帧,0表示标准帧
|
|
||||||
/// </summary>
|
|
||||||
public uint eff
|
|
||||||
{
|
|
||||||
get { return (can_id & 0x80000000) != 0 ? 1u : 0u; }
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (value != 0)
|
|
||||||
can_id |= 0x80000000; // 将最高位置1,表示扩展帧
|
|
||||||
else
|
|
||||||
can_id &= 0x7FFFFFFF; // 将最高位清0,表示标准帧
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ZCAN_CANFD_FRAME()
|
|
||||||
{
|
|
||||||
data = new byte[64];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 初始化 CAN 驱动
|
|
||||||
/// </summary>
|
|
||||||
[Browsable(false)]
|
|
||||||
public static int Init(uint deviceType, uint deviceIndex)
|
|
||||||
{
|
|
||||||
if (_deviceHandle != 0) return 0;
|
|
||||||
|
|
||||||
_deviceHandle = ZLGCAN.ZCAN_OpenDevice(deviceType, deviceIndex, 0);
|
|
||||||
|
|
||||||
if (_deviceHandle == 0)
|
|
||||||
{
|
|
||||||
Debug.WriteLine("ZLG 设备初始化失败!");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 释放 CAN 驱动
|
|
||||||
/// </summary>
|
|
||||||
[Browsable(false)]
|
|
||||||
public static void Release()
|
|
||||||
{
|
|
||||||
DisConnect();
|
|
||||||
if (_deviceHandle != 0)
|
|
||||||
{
|
|
||||||
ZLGCAN.ZCAN_CloseDevice(_deviceHandle);
|
|
||||||
_deviceHandle = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 注册监听器
|
|
||||||
/// </summary>
|
|
||||||
[Browsable(false)]
|
|
||||||
public static int RegisterListener(Action<ZLGCAN.ZCAN_ReceiveFD_Data> listenEvent)
|
|
||||||
{
|
|
||||||
listener = listenEvent;
|
|
||||||
|
|
||||||
if (!_isReceiving)
|
|
||||||
{
|
|
||||||
_isReceiving = true;
|
|
||||||
Task.Run(ReceiveThreadProcess);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 注销监听器
|
|
||||||
/// </summary>
|
|
||||||
[Browsable(false)]
|
|
||||||
public static int UnRegisterListener()
|
|
||||||
{
|
|
||||||
listener = null;
|
|
||||||
_isReceiving = false;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void ReceiveThreadProcess()
|
|
||||||
{
|
|
||||||
while (_isReceiving)
|
|
||||||
{
|
|
||||||
bool hasData = false;
|
|
||||||
foreach (var chnHandle in _channelHandles.Values)
|
|
||||||
{
|
|
||||||
uint len = ZLGCAN.ZCAN_GetReceiveNum(chnHandle, ZDBC.FT_CANFD);
|
|
||||||
if (len > 0)
|
|
||||||
{
|
|
||||||
int size = Marshal.SizeOf(typeof(ZLGCAN.ZCAN_ReceiveFD_Data));
|
|
||||||
nint ptr = Marshal.AllocHGlobal((int)len * size);
|
|
||||||
|
|
||||||
uint readLen = ZLGCAN.ZCAN_ReceiveFD(chnHandle, ptr, len, 50);
|
|
||||||
|
|
||||||
for (int i = 0; i < readLen; i++)
|
|
||||||
{
|
|
||||||
nint pItem = ptr + i * size;
|
|
||||||
var frame = Marshal.PtrToStructure<ZLGCAN.ZCAN_ReceiveFD_Data>(pItem);
|
|
||||||
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
_receivedMessages.Enqueue(frame);
|
|
||||||
}
|
|
||||||
listener?.Invoke(frame);
|
|
||||||
}
|
|
||||||
Marshal.FreeHGlobal(ptr);
|
|
||||||
hasData = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hasData) Thread.Sleep(10);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int Connect(uint channel, ZLGCAN.ZCAN_CHANNEL_INIT_CONFIG config)
|
|
||||||
{
|
|
||||||
if (_deviceHandle == 0) return -1;
|
|
||||||
|
|
||||||
nint chnHandle = ZLGCAN.ZCAN_InitCAN(_deviceHandle, channel, ref config);
|
|
||||||
if (chnHandle == 0)
|
|
||||||
{
|
|
||||||
Debug.WriteLine($"CAN 通道 {channel} 初始化失败");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ZLGCAN.ZCAN_StartCAN(chnHandle) == 1)
|
|
||||||
{
|
|
||||||
_channelHandles[channel] = chnHandle;
|
|
||||||
ConnectFlag = true;
|
|
||||||
Task.Run(() => ConnectEvent?.Invoke());
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Debug.WriteLine($"CAN 通道 {channel} 启动失败");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int DisConnect()
|
|
||||||
{
|
|
||||||
foreach (var handle in _channelHandles.Values)
|
|
||||||
{
|
|
||||||
ZLGCAN.ZCAN_ResetCAN(handle);
|
|
||||||
}
|
|
||||||
_channelHandles.Clear();
|
|
||||||
ConnectFlag = false;
|
|
||||||
Task.Run(() => DisConnectEvent?.Invoke());
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
[Browsable(false)]
|
|
||||||
public static int LoadDBC(string filePath, int[] channel, out uint databaseID)
|
|
||||||
{
|
|
||||||
// 1. 初始化 ZDBC 模块,获取句柄
|
|
||||||
databaseID = ZDBC.ZDBC_Init(0, 1);
|
|
||||||
|
|
||||||
if (databaseID == ZDBC.INVALID_DBC_HANDLE)
|
|
||||||
{
|
|
||||||
return -1; // 初始化失败
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. 构造文件信息结构体并加载
|
|
||||||
ZDBC.FileInfo fileInfo = new ZDBC.FileInfo();
|
|
||||||
fileInfo.strFilePath = new byte[ZDBC._MAX_FILE_PATH_ + 1];
|
|
||||||
byte[] pathBytes = System.Text.Encoding.Default.GetBytes(filePath);
|
|
||||||
Array.Copy(pathBytes, fileInfo.strFilePath, Math.Min(pathBytes.Length, ZDBC._MAX_FILE_PATH_));
|
|
||||||
|
|
||||||
fileInfo.type = ZDBC.PROTOCOL_OTHER; // 默认普通 CAN/CANFD
|
|
||||||
fileInfo.merge = 0; // 清除原有数据加载新文件
|
|
||||||
|
|
||||||
// 将结构体封送到非托管内存
|
|
||||||
nint pFileInfo = Marshal.AllocHGlobal(Marshal.SizeOf(fileInfo));
|
|
||||||
Marshal.StructureToPtr(fileInfo, pFileInfo, false);
|
|
||||||
|
|
||||||
bool success = ZDBC.ZDBC_LoadFile(databaseID, pFileInfo);
|
|
||||||
Marshal.FreeHGlobal(pFileInfo); // 释放临时内存
|
|
||||||
|
|
||||||
if (!success) return -2; // 加载文件失败
|
|
||||||
|
|
||||||
// 3. 将加载的数据同步到您本地的缓存(如 MsgDatabase)
|
|
||||||
// 注意:ZLG 的加载通常是全局的,如果您的业务逻辑需要分 channel 存储,
|
|
||||||
// 需要根据您的解析类进行填充
|
|
||||||
foreach (var ch in channel)
|
|
||||||
{
|
|
||||||
// 这里的 Parse 需要您根据 ZDBC 的 API 重新实现(见下方第2点)
|
|
||||||
DBCParse.Parse(databaseID, ch);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
[Browsable(false)]
|
|
||||||
public static int UnLoadDBC(uint? databaseID = null)
|
|
||||||
{
|
|
||||||
// 1. 如果传入了句柄,释放 ZDBC 引擎资源
|
|
||||||
if (databaseID.HasValue && databaseID.Value != ZDBC.INVALID_DBC_HANDLE)
|
|
||||||
{
|
|
||||||
ZDBC.ZDBC_Release(databaseID.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. 清除本地缓存
|
|
||||||
DBCParse.MsgDatabase.Clear();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#region 信号值获取方法 (ZLG 适配版)
|
|
||||||
|
|
||||||
public static double GetSignalValue(byte channel, string AMsgName, string ASgnName)
|
|
||||||
{
|
|
||||||
double value = double.NaN;
|
|
||||||
var find = DBCParse.MsgDatabase[channel].FirstOrDefault(s => s.msg_name == AMsgName);
|
|
||||||
|
|
||||||
if (find != null)
|
|
||||||
{
|
|
||||||
int re = GetZlgSignalValue(ref find.ACANFD, AMsgName, ASgnName, ref value);
|
|
||||||
|
|
||||||
if (re != 1)
|
|
||||||
{
|
|
||||||
Debug.WriteLine($"GetSignalValue: 获取信号值失败, 消息: {AMsgName}, 信号: {ASgnName}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Debug.WriteLine($"GetSignalValue: 未找到消息定义, 消息: {AMsgName}, 通道: {channel}");
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
[Browsable(false)]
|
|
||||||
public static int GetSignalValue(byte channel, string AMsgName, string ASgnName, ref double value)
|
|
||||||
{
|
|
||||||
var find = DBCParse.MsgDatabase[channel].FirstOrDefault(s => s.msg_name == AMsgName);
|
|
||||||
if (find != null)
|
|
||||||
{
|
|
||||||
return GetZlgSignalValue(ref find.ACANFD, AMsgName, ASgnName, ref value);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Debug.WriteLine($"GetSignalValue: 未找到消息定义, 消息: {AMsgName}, 通道: {channel}");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Browsable(false)]
|
|
||||||
public static int GetSignalValue(ref ZCAN_CANFD_FRAME ACANFD, string AMsgName, string ASgnName, ref double value)
|
|
||||||
{
|
|
||||||
return GetZlgSignalValue(ref ACANFD, AMsgName, ASgnName, ref value);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region ZLG 私有解析辅助
|
|
||||||
|
|
||||||
private static int GetZlgSignalValue(ref ZCAN_CANFD_FRAME frame, string msgName, string sigName, ref double val)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// 模拟或调用 ZLG 外部 DBC 库进行信号解析
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
private static Dictionary<string, System.Timers.Timer> _cyclicTimers = new Dictionary<string, System.Timers.Timer>();
|
|
||||||
|
|
||||||
#region 信号值设置方法 (ZLG 适配版)
|
|
||||||
|
|
||||||
public static int SetSignalValue(byte channel, string AMsgName, string ASgnName, double AValue, bool isSend = false, float sendPeriod = 0)
|
|
||||||
{
|
|
||||||
var find = DBCParse.MsgDatabase[channel].FirstOrDefault(s => s.msg_name == AMsgName);
|
|
||||||
if (find == null)
|
|
||||||
{
|
|
||||||
Debug.WriteLine($"SetSignalValue: 未找到消息定义, 消息: {AMsgName}, 通道: {channel}");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int re = EncodeZlgSignal(ref find.ACANFD, AMsgName, ASgnName, AValue);
|
|
||||||
|
|
||||||
if (re != 0)
|
|
||||||
{
|
|
||||||
Debug.WriteLine($"设置信号值编码失败! 消息:{AMsgName}, 信号:{ASgnName}");
|
|
||||||
return re;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isSend)
|
|
||||||
{
|
|
||||||
return TransmitLogic(channel, find, sendPeriod);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int SetSignalValue(uint channel, string AMsgName, float sendPeriod = 0)
|
|
||||||
{
|
|
||||||
var find = DBCParse.MsgDatabase[(byte)channel].FirstOrDefault(s => s.msg_name == AMsgName);
|
|
||||||
if (find == null)
|
|
||||||
{
|
|
||||||
Debug.WriteLine($"SetSignalValue: 未找到消息定义, 消息: {AMsgName}, 通道: {channel}");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TransmitLogic((byte)channel, find, sendPeriod);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 内部辅助逻辑
|
|
||||||
|
|
||||||
private static int TransmitLogic(byte channel, ZLG_Msg msg, float period)
|
|
||||||
{
|
|
||||||
if (period <= 0)
|
|
||||||
{
|
|
||||||
return SendZlgFrame(channel, msg.ACANFD);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
string key = $"{channel}_{msg.msg_id}";
|
|
||||||
|
|
||||||
if (_cyclicTimers.ContainsKey(key))
|
|
||||||
{
|
|
||||||
_cyclicTimers[key].Stop();
|
|
||||||
_cyclicTimers[key].Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
var timer = new System.Timers.Timer(period);
|
|
||||||
timer.Elapsed += (s, e) => SendZlgFrame(channel, msg.ACANFD);
|
|
||||||
timer.AutoReset = true;
|
|
||||||
timer.Enabled = true;
|
|
||||||
_cyclicTimers[key] = timer;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int SendZlgFrame(byte channel, ZCAN_CANFD_FRAME frame)
|
|
||||||
{
|
|
||||||
if (!_channelHandles.ContainsKey(channel)) return -1;
|
|
||||||
|
|
||||||
nint ptr = Marshal.AllocHGlobal(Marshal.SizeOf(frame));
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Marshal.StructureToPtr(frame, ptr, false);
|
|
||||||
uint result = ZLGCAN.ZCAN_TransmitFD(_channelHandles[channel], ptr, 1);
|
|
||||||
return result == 1 ? 0 : -1;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
Marshal.FreeHGlobal(ptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int EncodeZlgSignal(ref ZCAN_CANFD_FRAME frame, string msgName, string sigName, double val)
|
|
||||||
{
|
|
||||||
// 信号编码逻辑实现
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,148 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace ZLGCANFD
|
|
||||||
{
|
|
||||||
public class ZLG_Msg
|
|
||||||
{
|
|
||||||
public int msg_type { get; set; }
|
|
||||||
public uint msg_id { get; set; }
|
|
||||||
public double msg_cyclic { get; set; }
|
|
||||||
public byte msg_dlc { get; set; }
|
|
||||||
public string msg_name { get; set; }
|
|
||||||
public List<ZDBC.DBCSignal> signals { get; set; } = new List<ZDBC.DBCSignal>();
|
|
||||||
public string[] signal_Name { get; set; }
|
|
||||||
|
|
||||||
// 适配 ZLG 的 CANFD 帧结构 (来自 2.txt)
|
|
||||||
public CAN.ZCAN_CANFD_FRAME ACANFD;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class DBCParse
|
|
||||||
{
|
|
||||||
// 存储多通道的消息数据库
|
|
||||||
public static List<List<ZLG_Msg>> MsgDatabase { get; set; } =
|
|
||||||
Enumerable.Range(0, 12).Select(_ => new List<ZLG_Msg>()).ToList();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// ZLG 专用解析逻辑:遍历 ZDBC 内部的消息链表并填充到 MsgDatabase
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="hDBC">ZDBC_Init 返回的句柄</param>
|
|
||||||
/// <param name="channel">目标通道索引</param>
|
|
||||||
public static void Parse(uint hDBC, int channel)
|
|
||||||
{
|
|
||||||
if (hDBC == ZDBC.INVALID_DBC_HANDLE) return;
|
|
||||||
|
|
||||||
// 1. 初始化指针空间
|
|
||||||
int msgSize = Marshal.SizeOf(typeof(ZDBC.DBCMessage));
|
|
||||||
nint pMsg = Marshal.AllocHGlobal(msgSize);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// 清空当前通道旧数据
|
|
||||||
MsgDatabase[channel].Clear();
|
|
||||||
|
|
||||||
// 2. 迭代获取所有消息
|
|
||||||
bool hasMessage = ZDBC.ZDBC_GetFirstMessage(hDBC, pMsg);
|
|
||||||
while (hasMessage)
|
|
||||||
{
|
|
||||||
ZDBC.DBCMessage dbMsg = Marshal.PtrToStructure<ZDBC.DBCMessage>(pMsg);
|
|
||||||
|
|
||||||
ZLG_Msg temp = new ZLG_Msg();
|
|
||||||
temp.msg_id = dbMsg.nID;
|
|
||||||
temp.msg_name = Encoding.Default.GetString(dbMsg.strName).TrimEnd('\0');
|
|
||||||
temp.msg_dlc = (byte)dbMsg.nSize;
|
|
||||||
temp.msg_cyclic = dbMsg.nCycleTime;
|
|
||||||
temp.msg_type = dbMsg.nExtend; // 0-标准帧, 1-扩展帧
|
|
||||||
|
|
||||||
// 3. 处理信号
|
|
||||||
int sigCount = (int)dbMsg.nSignalCount;
|
|
||||||
temp.signal_Name = new string[sigCount];
|
|
||||||
for (int i = 0; i < sigCount; i++)
|
|
||||||
{
|
|
||||||
var sig = dbMsg.vSignals[i];
|
|
||||||
temp.signals.Add(sig);
|
|
||||||
temp.signal_Name[i] = Encoding.Default.GetString(sig.strName).TrimEnd('\0');
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. 初始化对应的 ZLG 发送帧结构 (预设好 ID 和 DLC)
|
|
||||||
temp.ACANFD = new CAN.ZCAN_CANFD_FRAME();
|
|
||||||
temp.ACANFD.can_id = dbMsg.nID;
|
|
||||||
temp.ACANFD.len = (byte)dbMsg.nSize;
|
|
||||||
temp.ACANFD.eff = dbMsg.nExtend;
|
|
||||||
temp.ACANFD.data = new byte[64];
|
|
||||||
|
|
||||||
MsgDatabase[channel].Add(temp);
|
|
||||||
|
|
||||||
// 获取下一条
|
|
||||||
hasMessage = ZDBC.ZDBC_GetNextMessage(hDBC, pMsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 按 ID 排序
|
|
||||||
MsgDatabase[channel].Sort((a, b) => a.msg_id.CompareTo(b.msg_id));
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
// 释放内存
|
|
||||||
Marshal.FreeHGlobal(pMsg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 加载 DBC 的入口函数
|
|
||||||
/// </summary>
|
|
||||||
public static int LoadDBC(string filePath, int[] channels, out uint databaseID)
|
|
||||||
{
|
|
||||||
// 初始化
|
|
||||||
databaseID = ZDBC.ZDBC_Init(0, 1);
|
|
||||||
if (databaseID == ZDBC.INVALID_DBC_HANDLE) return -1;
|
|
||||||
|
|
||||||
// 准备文件信息
|
|
||||||
ZDBC.FileInfo fileInfo = new ZDBC.FileInfo();
|
|
||||||
fileInfo.strFilePath = new byte[ZDBC._MAX_FILE_PATH_ + 1];
|
|
||||||
byte[] pathBytes = Encoding.Default.GetBytes(filePath);
|
|
||||||
Array.Copy(pathBytes, fileInfo.strFilePath, Math.Min(pathBytes.Length, ZDBC._MAX_FILE_PATH_));
|
|
||||||
fileInfo.type = ZDBC.PROTOCOL_OTHER;
|
|
||||||
fileInfo.merge = 0;
|
|
||||||
|
|
||||||
// 加载文件
|
|
||||||
nint pFileInfo = Marshal.AllocHGlobal(Marshal.SizeOf(fileInfo));
|
|
||||||
Marshal.StructureToPtr(fileInfo, pFileInfo, false);
|
|
||||||
bool success = ZDBC.ZDBC_LoadFile(databaseID, pFileInfo);
|
|
||||||
Marshal.FreeHGlobal(pFileInfo);
|
|
||||||
|
|
||||||
if (!success)
|
|
||||||
{
|
|
||||||
ZDBC.ZDBC_Release(databaseID);
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 解析到各通道
|
|
||||||
foreach (var ch in channels)
|
|
||||||
{
|
|
||||||
Parse(databaseID, ch);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 卸载 DBC 并释放 ZDBC 句柄
|
|
||||||
/// </summary>
|
|
||||||
public static int UnLoadDBC(uint? databaseID = null)
|
|
||||||
{
|
|
||||||
if (databaseID.HasValue && databaseID.Value != ZDBC.INVALID_DBC_HANDLE)
|
|
||||||
{
|
|
||||||
ZDBC.ZDBC_Release(databaseID.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var list in MsgDatabase)
|
|
||||||
{
|
|
||||||
list.Clear();
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
1236
ZLGCANFD/ZLGAPI.cs
1236
ZLGCANFD/ZLGAPI.cs
File diff suppressed because it is too large
Load Diff
@ -1,19 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<OutputType>Library</OutputType>
|
|
||||||
<TargetFramework>net8.0-windows</TargetFramework>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<UseWPF>true</UseWPF>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\Common\Common.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<None Update="ZLGCANFD.dll">
|
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
||||||
Loading…
Reference in New Issue
Block a user