CAN驱动修改优化
This commit is contained in:
+7
-267
@@ -11,275 +11,15 @@ using TSMaster;
|
||||
namespace TSMasterCAN
|
||||
{
|
||||
[ACPCommand]
|
||||
public class CAN : IDisposable
|
||||
public class CAN
|
||||
{
|
||||
#region 静态成员
|
||||
|
||||
public static event Action? ConnectEvent;
|
||||
public static event Action? DisConnectEvent;
|
||||
public static event Action ConnectEvent;
|
||||
public static event Action DisConnectEvent;
|
||||
public static bool ConnectFlag { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 实时接收到的 CAN 报文缓存(按报文 ID 索引,保留最新帧)。
|
||||
/// 供 CANViewModel.Refresh 等界面轮询读取。
|
||||
/// </summary>
|
||||
public static ConcurrentDictionary<int, TLIBCANFD> RealTimeMessages { get; } = new();
|
||||
|
||||
#endregion
|
||||
|
||||
#region 实例字段与属性
|
||||
|
||||
/// <summary>设备类型号(43 = USBCANFD-400U 等,TSMaster 中作为配置参考保留)</summary>
|
||||
public uint DeviceType { get; }
|
||||
/// <summary>设备索引</summary>
|
||||
public uint DeviceIndex { get; }
|
||||
/// <summary>最大通道数</summary>
|
||||
public int MaxChannels { get; }
|
||||
/// <summary>仲裁域波特率</summary>
|
||||
public string ABitBaud { get; }
|
||||
/// <summary>数据域波特率</summary>
|
||||
public string DBitBaud { get; }
|
||||
/// <summary>是否开启终端电阻</summary>
|
||||
public bool EnableTerminalResistance { get; }
|
||||
|
||||
/// <summary>DBC 解析器(提供 MsgDatabase、MaxChannels 等访问)</summary>
|
||||
public DBCParse DBCParser => DBCParse.Instance;
|
||||
|
||||
/// <summary>
|
||||
/// DBC 报文解码事件:当接收到 CAN 帧并通过 DBC 解码后触发。
|
||||
/// 参数:(通道号, 解码后的报文信息)
|
||||
/// </summary>
|
||||
public event Action<uint, DBCMessage>? OnDbcMessageDecoded;
|
||||
|
||||
private bool _disposed;
|
||||
private bool _isOpened;
|
||||
private TCANFDQueueEvent_Win32? _instanceListener;
|
||||
|
||||
#endregion
|
||||
|
||||
#region 构造函数
|
||||
|
||||
/// <summary>默认构造函数(兼容 SystemConfig.CANFD = new() 等场景)</summary>
|
||||
public CAN() : this(43, 0, 4, "500000", "2000000", true) { }
|
||||
|
||||
/// <summary>
|
||||
/// 带配置参数的构造函数(兼容原 ZLG 设备管理流程)。
|
||||
/// </summary>
|
||||
/// <param name="deviceType">设备类型号</param>
|
||||
/// <param name="deviceIndex">设备索引</param>
|
||||
/// <param name="maxChannels">最大通道数</param>
|
||||
/// <param name="aBitBaud">仲裁域波特率</param>
|
||||
/// <param name="dBitBaud">数据域波特率</param>
|
||||
/// <param name="enableTerminalResistance">是否开启终端电阻</param>
|
||||
public CAN(uint deviceType, uint deviceIndex, int maxChannels, string aBitBaud, string dBitBaud, bool enableTerminalResistance)
|
||||
{
|
||||
DeviceType = deviceType;
|
||||
DeviceIndex = deviceIndex;
|
||||
MaxChannels = maxChannels;
|
||||
ABitBaud = aBitBaud;
|
||||
DBitBaud = dBitBaud;
|
||||
EnableTerminalResistance = enableTerminalResistance;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 实例方法 — 设备管理(替代原 ZLG 实例方法)
|
||||
|
||||
/// <summary>
|
||||
/// 打开设备:初始化 TSMaster 库 → 设置通道数 → 配置波特率 → 连接 → 启动 RBS → 注册监听。
|
||||
/// </summary>
|
||||
/// <returns>true 表示成功</returns>
|
||||
public bool 打开设备()
|
||||
{
|
||||
if (_isOpened) return true;
|
||||
if (ConnectFlag) { _isOpened = true; return true; }
|
||||
|
||||
try
|
||||
{
|
||||
// 1. 初始化 TSMaster 库
|
||||
var re = Init("ACP");
|
||||
if (re != 0)
|
||||
{
|
||||
Debug.WriteLine($"TSMaster 初始化失败,错误代码:{re}");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. 设置通道数
|
||||
TsMasterApi.tsapp_set_can_channel_count(MaxChannels);
|
||||
|
||||
// 3. 配置各通道波特率
|
||||
float arbKbps = float.Parse(ABitBaud) / 1000f;
|
||||
float dataKbps = float.Parse(DBitBaud) / 1000f;
|
||||
for (int ch = 0; ch < MaxChannels; ch++)
|
||||
{
|
||||
TsMasterApi.tsapp_configure_baudrate_canfd(
|
||||
ch, arbKbps, dataKbps,
|
||||
TLIBCANFDControllerType.lfdtISOCAN,
|
||||
TLIBCANFDControllerMode.lfdmNormal,
|
||||
EnableTerminalResistance);
|
||||
}
|
||||
|
||||
// 4. 连接硬件
|
||||
re = Connect();
|
||||
if (re != 0)
|
||||
{
|
||||
Debug.WriteLine($"CAN 连接失败,错误代码:{re}");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 5. 注册接收监听(用于 DBC 信号解码广播)
|
||||
_instanceListener = new TCANFDQueueEvent_Win32(OnCanFdReceived);
|
||||
RegisterListener(_instanceListener);
|
||||
|
||||
_isOpened = true;
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"打开设备异常:{ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 关闭 CAN 卡设备:注销监听 → 断开连接。
|
||||
/// </summary>
|
||||
public void 关闭CAN卡设备()
|
||||
{
|
||||
if (!_isOpened && !ConnectFlag) return;
|
||||
|
||||
try
|
||||
{
|
||||
if (_instanceListener != null)
|
||||
{
|
||||
UnRegisterListener(_instanceListener);
|
||||
_instanceListener = null;
|
||||
}
|
||||
DisConnect();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"关闭CAN卡设备异常:{ex.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isOpened = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化并启动指定通道(配置波特率,TSMaster 在 Connect 时已自动启动所有通道)。
|
||||
/// </summary>
|
||||
/// <param name="channel">通道号</param>
|
||||
public void 初始化并启动通道(uint channel)
|
||||
{
|
||||
if (channel >= MaxChannels) return;
|
||||
try
|
||||
{
|
||||
float arbKbps = float.Parse(ABitBaud) / 1000f;
|
||||
float dataKbps = float.Parse(DBitBaud) / 1000f;
|
||||
TsMasterApi.tsapp_configure_baudrate_canfd(
|
||||
(int)channel, arbKbps, dataKbps,
|
||||
TLIBCANFDControllerType.lfdtISOCAN,
|
||||
TLIBCANFDControllerMode.lfdmNormal,
|
||||
EnableTerminalResistance);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"初始化通道 {channel} 异常:{ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载通道 DBC 文件。
|
||||
/// </summary>
|
||||
/// <param name="channel">通道号</param>
|
||||
/// <param name="filePath">DBC 文件路径</param>
|
||||
/// <returns>true 表示加载成功</returns>
|
||||
public bool 加载通道DBC文件(uint channel, string filePath)
|
||||
{
|
||||
try
|
||||
{
|
||||
var re = LoadDBC(filePath, [(int)channel], out _);
|
||||
return re == 0;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"加载通道 {channel} DBC 文件异常:{ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// CAN FD 接收回调:接收原始帧 → 查找 DBC → 解码信号 → 触发 OnDbcMessageDecoded 事件。
|
||||
/// </summary>
|
||||
private void OnCanFdReceived(ref int AObj, ref TLIBCANFD AData)
|
||||
{
|
||||
if (_disposed) return;
|
||||
|
||||
// 始终缓存最新报文,供界面轮询刷新
|
||||
int identifier = AData.FIdentifier;
|
||||
var canfdCopy = AData;
|
||||
RealTimeMessages[identifier] = canfdCopy;
|
||||
|
||||
if (OnDbcMessageDecoded == null) return;
|
||||
|
||||
try
|
||||
{
|
||||
uint channel = AData.FIdxChn;
|
||||
if (channel >= DBCParse.MsgDatabase.Count) return;
|
||||
|
||||
// 在 DBC 数据库中查找匹配的报文
|
||||
var msgList = DBCParse.MsgDatabase[(int)channel];
|
||||
var match = msgList.FirstOrDefault(m => m.msg_id == identifier);
|
||||
if (match == null || match.signal_Name == null || match.signal_Name.Length == 0) return;
|
||||
|
||||
// 解码各信号值
|
||||
var signals = new DBCSignal[match.signal_Name.Length];
|
||||
for (int i = 0; i < match.signal_Name.Length; i++)
|
||||
{
|
||||
double value = 0;
|
||||
TsMasterApi.tsdb_get_signal_value_canfd(ref canfdCopy, match.msg_name, match.signal_Name[i], ref value);
|
||||
signals[i] = new DBCSignal
|
||||
{
|
||||
strName = Encoding.Default.GetBytes(match.signal_Name[i]),
|
||||
nRawvalue = value,
|
||||
nFactor = 1,
|
||||
nOffset = 0
|
||||
};
|
||||
}
|
||||
|
||||
var decoded = new DBCMessage
|
||||
{
|
||||
nID = (uint)identifier,
|
||||
nSignalCount = signals.Length,
|
||||
vSignals = signals
|
||||
};
|
||||
|
||||
OnDbcMessageDecoded?.Invoke(channel, decoded);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"DBC 信号解码异常:{ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IDisposable
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed) return;
|
||||
_disposed = true;
|
||||
关闭CAN卡设备();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 初始化TSMasterCAN
|
||||
/// 初始化CAN驱动
|
||||
/// </summary>
|
||||
/// <param name="ProjectName"></param>
|
||||
/// <param name="filePath"></param>
|
||||
@@ -298,7 +38,7 @@ namespace TSMasterCAN
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 释放TSMasterCAN
|
||||
/// 释放CAN驱动
|
||||
/// </summary>
|
||||
[Browsable(false)]
|
||||
public static void Release()
|
||||
@@ -391,7 +131,7 @@ namespace TSMasterCAN
|
||||
public static int LoadDBC(string filePath, int[] channel, out uint databaseID)
|
||||
{
|
||||
databaseID = 0;
|
||||
|
||||
if (!Path.Exists(filePath)) return -1;
|
||||
var re = TsMasterApi.tsdb_load_can_db(Path.GetFullPath(filePath), string.Join(",", channel), ref databaseID);
|
||||
foreach (var item in channel)
|
||||
{
|
||||
@@ -529,7 +269,7 @@ namespace TSMasterCAN
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 设置信号值
|
||||
/// </summary>
|
||||
|
||||
@@ -120,44 +120,8 @@ namespace TSMasterCAN
|
||||
NODE_RX_CANFD_MESSAGE_INDEX = 110,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DBC 解码后的信号信息(替代原 ZLG ZDBC.DBCSignal)。
|
||||
/// </summary>
|
||||
public struct DBCSignal
|
||||
{
|
||||
/// <summary>信号名称(原始字节,兼容 Encoding.Default 解码)</summary>
|
||||
public byte[] strName;
|
||||
/// <summary>原始值(TSMaster tsdb_get_signal_value_canfd 返回的物理值)</summary>
|
||||
public double nRawvalue;
|
||||
/// <summary>因子(TSMaster 返回物理值,因子固定为 1)</summary>
|
||||
public double nFactor;
|
||||
/// <summary>偏移(TSMaster 返回物理值,偏移固定为 0)</summary>
|
||||
public double nOffset;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DBC 解码后的报文信息(替代原 ZLG ZDBC.DBCMessage)。
|
||||
/// 在 CAN 接收回调中对原始 TLIBCANFD 帧解码后构建此对象并触发 OnDbcMessageDecoded 事件。
|
||||
/// </summary>
|
||||
public class DBCMessage
|
||||
{
|
||||
/// <summary>报文 ID</summary>
|
||||
public uint nID;
|
||||
/// <summary>信号数量</summary>
|
||||
public int nSignalCount;
|
||||
/// <summary>信号数组</summary>
|
||||
public DBCSignal[] vSignals;
|
||||
}
|
||||
|
||||
public class DBCParse
|
||||
{
|
||||
private static DBCParse? _instance;
|
||||
/// <summary>单例实例,供 CAN.DBCParser 属性使用(MsgDatabase 等成员为 static,实例仅用于属性访问兼容)。</summary>
|
||||
public static DBCParse Instance => _instance ??= new DBCParse();
|
||||
|
||||
/// <summary>最大通道数(等于 MsgDatabase 的维度)</summary>
|
||||
public int MaxChannels => MsgDatabase.Count;
|
||||
|
||||
public static List<List<_Msg_>> MsgDatabase { get; set; } =
|
||||
[.. Enumerable.Range(0, 12).Select(_ => new List<_Msg_>())];
|
||||
public static can_network can_Network;
|
||||
|
||||
Reference in New Issue
Block a user