CAN作用域优化

This commit is contained in:
hsc
2026-07-06 11:37:09 +08:00
parent 6c2b975999
commit aec0044595
4 changed files with 95 additions and 57 deletions

View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace ZLGUSBCANFD
{
@@ -24,18 +23,37 @@ namespace ZLGUSBCANFD
CANFD = 1,
}
/// <summary>
/// DBC 报文解析器(实例类,每个 ZLGCANFD 拥有独立的解析器实例)。
/// 不同 CAN 卡的作用域各自维护自己的 MsgDatabase互不干扰。
/// </summary>
public class ZLGDBCParser
{
// 补齐这个属性4个通道的静态报文数据库缓存供 ViewModel 直接读取
public static List<List<_Msg_>> MsgDatabase { get; set; } =
[.. Enumerable.Range(0, 4).Select(_ => new List<_Msg_>())];
/// <summary>
/// 每个通道的报文数据库缓存,供 ViewModel 直接读取。
/// 索引 = 通道号 (0 ~ maxChannels-1)。
/// </summary>
public List<List<_Msg_>> MsgDatabase { get; private set; }
/// <summary>
/// 外部调用:解析特定通道的 DBC 并自动存入对应的 MsgDatabase 缓存中
/// 最大通道数(与所属 ZLGCANFD 一致)。
/// </summary>
/// <param name="chDbcHandle">ZDBC句柄</param>
/// <param name="channel">通道号索引 (0-11)</param>
public static void ParseAndLoadToDatabase(uint chDbcHandle, int channel)
public int MaxChannels { get; }
public ZLGDBCParser(int maxChannels = 4)
{
MaxChannels = maxChannels;
MsgDatabase = new List<List<_Msg_>>(
Enumerable.Range(0, maxChannels).Select(_ => new List<_Msg_>())
);
}
/// <summary>
/// 解析特定通道的 DBC 并自动存入对应的 MsgDatabase 缓存中。
/// </summary>
/// <param name="chDbcHandle">ZDBC 句柄</param>
/// <param name="channel">通道号索引 (0 ~ maxChannels-1)</param>
public void ParseAndLoadToDatabase(uint chDbcHandle, int channel)
{
if (channel < 0 || channel >= MsgDatabase.Count) return;
@@ -48,7 +66,7 @@ namespace ZLGUSBCANFD
}
/// <summary>
/// 全手工解析周立功 DBC 句柄下的所有消息和信号
/// 全手工解析周立功 DBC 句柄下的所有消息和信号
/// </summary>
/// <param name="chDbcHandle">对应通道的 ZDBC 句柄</param>
/// <returns>返回对齐同星业务层的自定义报文列表</returns>
@@ -56,43 +74,34 @@ namespace ZLGUSBCANFD
{
List<_Msg_> msgList = new List<_Msg_>();
// 显式指定周立功命名空间下的 INVALID_DBC_HANDLE 校验
if (chDbcHandle == 0 || chDbcHandle == ZLGUSBCANFD.ZDBC.INVALID_DBC_HANDLE)
if (chDbcHandle == 0 || chDbcHandle == ZDBC.INVALID_DBC_HANDLE)
return msgList;
// 显式指定周立功命名空间下的结构体大小
int msgSize = Marshal.SizeOf(typeof(ZLGUSBCANFD.ZDBC.DBCMessage));
int msgSize = Marshal.SizeOf(typeof(ZDBC.DBCMessage));
IntPtr pMsg = Marshal.AllocHGlobal(msgSize);
try
{
// 1. 获取周立功 DBC 的第一条报文
bool hasMessage = ZLGUSBCANFD.ZDBC.ZDBC_GetFirstMessage(chDbcHandle, pMsg);
bool hasMessage = ZDBC.ZDBC_GetFirstMessage(chDbcHandle, pMsg);
while (hasMessage)
{
// 强制指定周立功底层 DBCMessage 结构映射
var zlgMsg = (ZLGUSBCANFD.ZDBC.DBCMessage)Marshal.PtrToStructure(pMsg, typeof(ZLGUSBCANFD.ZDBC.DBCMessage));
var zlgMsg = (ZDBC.DBCMessage)Marshal.PtrToStructure(pMsg, typeof(ZDBC.DBCMessage));
// 1. 优先在字节数组中找到第一个 \0 的位置
int nullIndex = Array.IndexOf(zlgMsg.strName, (byte)0);
_Msg_ myMsg = new _Msg_
{
msg_id = (int)zlgMsg.nID,
// 2. 只翻译 \0 之前的有效字节,彻底解决乱码与规避不必要的内存开销
msg_name = nullIndex >= 0
? Encoding.Default.GetString(zlgMsg.strName, 0, nullIndex)
: Encoding.Default.GetString(zlgMsg.strName).TrimEnd('\0'),
msg_dlc = (byte)zlgMsg.nSize,
msg_cyclic = (int)zlgMsg.nCycleTime,
// 如果底层识别出是扩展帧(nExtend==1),这里对齐映射为你的业务类型
msg_type = zlgMsg.nExtend == 1 ? (int)Msg_Type.CANFD : (int)Msg_Type.CAN,
signal_Name = new string[zlgMsg.nSignalCount]
};
// 2. 提取该报文下的所有信号名称
for (int i = 0; i < zlgMsg.nSignalCount; i++)
{
var signal = zlgMsg.vSignals[i];
@@ -101,20 +110,16 @@ namespace ZLGUSBCANFD
}
msgList.Add(myMsg);
// 3. 移向下一条报文
hasMessage = ZLGUSBCANFD.ZDBC.ZDBC_GetNextMessage(chDbcHandle, pMsg);
hasMessage = ZDBC.ZDBC_GetNextMessage(chDbcHandle, pMsg);
}
}
finally
{
// 彻底释放非托管内存,避免上位机高频切换加载 DBC 时导致内存泄漏
Marshal.FreeHGlobal(pMsg);
}
// 按 ID 排序,对齐你的树状展现或者二分查找业务逻辑
msgList.Sort((a, b) => a.msg_id.CompareTo(b.msg_id));
return msgList;
}
}
}
}