148 lines
5.1 KiB
C#
148 lines
5.1 KiB
C#
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;
|
|
}
|
|
}
|
|
} |