diff --git a/ADP/ViewModels/ShellViewModel.cs b/ADP/ViewModels/ShellViewModel.cs
index a4aaaf8..d415a2b 100644
--- a/ADP/ViewModels/ShellViewModel.cs
+++ b/ADP/ViewModels/ShellViewModel.cs
@@ -1,6 +1,7 @@
using Logger;
using MaterialDesignThemes.Wpf;
+using Microsoft.Win32;
using Model.Models;
using Notifications.Wpf.Core;
using System.Collections.Concurrent;
@@ -147,7 +148,9 @@ namespace ADP.ViewModels
public ICommand NewCommand { get; set; }
public ICommand SetDefaultCommand { get; set; }
public ICommand ShowDialogManagerViewCommand { get; set; }
+ public ICommand SelectCANSignalMonitorCommand { get; set; }
public ICommand SelectCANMessageCommand { get; set; }
+ public ICommand GetFileStringCommand { get; set; }
#endregion
public ShellViewModel(IContainerProvider containerProvider)
@@ -177,7 +180,9 @@ namespace ADP.ViewModels
SaveAsCommand = new DelegateCommand(SaveAs);
SaveCommand = new DelegateCommand(Save);
SetDefaultCommand = new DelegateCommand(SetDefault);
+ SelectCANSignalMonitorCommand = new DelegateCommand(SelectCANSignalMonitor);
SelectCANMessageCommand = new DelegateCommand(SelectCANMessage);
+ GetFileStringCommand = new DelegateCommand(GetFileString);
_globalInfo.ContextDic.Add("default", new ScopedContext());
@@ -200,7 +205,7 @@ namespace ADP.ViewModels
_uiRefreshTimer.Start();
}
-
+
private void RefreshAllContextProperties()
{
RaisePropertyChanged(nameof(RunState));
@@ -211,6 +216,37 @@ namespace ADP.ViewModels
}
#region 命令处理与事件
+ private void GetFileString()
+ {
+ var openFileDialog = new OpenFileDialog
+ {
+ Title = "选择文件",
+ Filter = "所有文件 (*.*)|*.*",
+ };
+ if (openFileDialog.ShowDialog() == true)
+ {
+ string filePath = openFileDialog.FileName;
+ Application.Current.Dispatcher.Invoke(() =>
+ {
+ Clipboard.SetDataObject(filePath);
+ });
+ }
+ }
+ private void SelectCANSignalMonitor()
+ {
+ var canfd = CurrentConfig?.CANFD;
+ if (canfd == null || _globalInfo.CurrentScope == "default")
+ {
+ LoggerHelper.Warn("当前作用域未配置 CAN 设备,无法打开报文选择窗口。");
+ return;
+ }
+
+ _dialogService.ShowDialog("CollectCANSignalSettingView", new DialogParameters
+ {
+ { "SystemConfig", CurrentConfig }
+ }, _ => { });
+ }
+
private void SelectCANMessage()
{
var canfd = CurrentConfig?.CANFD;
diff --git a/ADP/Views/ShellView.xaml b/ADP/Views/ShellView.xaml
index 0084fad..52d0df6 100644
--- a/ADP/Views/ShellView.xaml
+++ b/ADP/Views/ShellView.xaml
@@ -158,13 +158,30 @@
Foreground="Black" />
-
+
+
+
+
diff --git a/CANModule/UpdateInfoModule.cs b/CANModule/CANModule.cs
similarity index 66%
rename from CANModule/UpdateInfoModule.cs
rename to CANModule/CANModule.cs
index aa035ac..9944f14 100644
--- a/CANModule/UpdateInfoModule.cs
+++ b/CANModule/CANModule.cs
@@ -1,4 +1,3 @@
-using System.Reflection;
using CANModule.Views;
namespace CANModule
@@ -12,6 +11,8 @@ namespace CANModule
public void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterDialog("SelectCanMessageView");
+ containerRegistry.RegisterDialog("CollectCANSignalSettingView");
+ containerRegistry.RegisterForNavigation("ZLGCANFDView");
}
}
}
diff --git a/CANModule/ViewModels/CollectCANSingalSettingViewModel.cs b/CANModule/ViewModels/CollectCANSingalSettingViewModel.cs
new file mode 100644
index 0000000..d5eff53
--- /dev/null
+++ b/CANModule/ViewModels/CollectCANSingalSettingViewModel.cs
@@ -0,0 +1,249 @@
+using System;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Windows.Input;
+using UIShare.GlobalVariable;
+using UIShare.PubEvent;
+using UIShare.UIViewModel;
+using UIShare.ViewModelBase;
+using ZLGUSBCANFD;
+
+namespace CANModule.ViewModels
+{
+ public class CollectCANSignalSettingViewModel : DialogViewModelBase
+ {
+ #region 字段
+ private ZLGCANFD? _canfd;
+ private SystemConfig? _systemConfig;
+ #endregion
+
+ #region 属性
+ public ObservableCollection ConfigurationList
+ {
+ get => _systemConfig?.ConfigurationList ?? new ObservableCollection();
+ }
+
+
+
+ private ObservableCollection _messageList;
+ public ObservableCollection MessageList
+ {
+ get => _messageList;
+ set => SetProperty(ref _messageList, value);
+ }
+
+ private ObservableCollection _signalList;
+ public ObservableCollection SignalList
+ {
+ get => _signalList;
+ set => SetProperty(ref _signalList, value);
+ }
+
+ private string _title = "信号采集设置";
+ public string Title
+ {
+ get => _title;
+ set => SetProperty(ref _title, value);
+ }
+
+ private string _selectedMessage;
+ public string SelectedMessage
+ {
+ get => _selectedMessage;
+ set
+ {
+ if (SetProperty(ref _selectedMessage, value))
+ {
+ if (!string.IsNullOrEmpty(value) && _canfd != null)
+ {
+ var db = _canfd.DBCParser.MsgDatabase;
+ if (MessageChannel >= 0 && MessageChannel < db.Count)
+ {
+ var targetMsg = db[MessageChannel]
+ .FirstOrDefault(x => $"[0x{x.msg_id:X}]{x.msg_name}" == value);
+
+ if (targetMsg != null && targetMsg.signal_Name != null)
+ {
+ SignalList = new ObservableCollection(targetMsg.signal_Name);
+ }
+ else
+ {
+ SignalList = new ObservableCollection();
+ }
+ }
+ }
+ else
+ {
+ SignalList = new ObservableCollection();
+ }
+ }
+ }
+ }
+
+ private CANSignalConfig _SelectedItem;
+ public CANSignalConfig SelectedItem
+ {
+ get => _SelectedItem;
+ set => SetProperty(ref _SelectedItem, value);
+ }
+
+ private string _selectedSignal;
+ public string SelectedSignal
+ {
+ get => _selectedSignal;
+ set => SetProperty(ref _selectedSignal, value);
+ }
+
+ private int _MessageChannel=-1;
+ public int MessageChannel
+ {
+ get => _MessageChannel;
+ set
+ {
+ if (_MessageChannel != value)
+ {
+ _MessageChannel = value;
+
+ SelectedMessage = null;
+ SelectedSignal = null;
+ SignalList = new ObservableCollection();
+
+ if (_canfd != null)
+ {
+ var db = _canfd.DBCParser.MsgDatabase;
+ if (db != null && value >= 0 && value < db.Count)
+ {
+ MessageList = new ObservableCollection(
+ db[value].Select(s => $"[0x{s.msg_id:X}]{s.msg_name}")
+ );
+ }
+ else
+ {
+ MessageList = new ObservableCollection();
+ }
+ }
+ else
+ {
+ MessageList = new ObservableCollection();
+ }
+
+ RaisePropertyChanged();
+ }
+ }
+ }
+
+ private int _collectionInterval = 1000;
+ public int CollectionInterval
+ {
+ get => _collectionInterval;
+ set => SetProperty(ref _collectionInterval, value);
+ }
+ #endregion
+
+ #region 命令
+ public ICommand AddCommand { get; set; }
+ public ICommand CloseCommand { get; set; }
+ public ICommand SaveCommand { get; set; }
+ public ICommand DeleteCommand { get; set; }
+ #endregion
+
+ public CollectCANSignalSettingViewModel(IContainerProvider containerProvider) : base(containerProvider)
+ {
+ CloseCommand = new DelegateCommand(Close);
+ AddCommand = new DelegateCommand(Add);
+ SaveCommand = new DelegateCommand(Save);
+ DeleteCommand = new DelegateCommand(Delete);
+ }
+
+ #region Dialog 生命周期
+ public override void OnDialogOpened(IDialogParameters parameters)
+ {
+ _systemConfig = parameters.GetValue("SystemConfig");
+ _canfd = _systemConfig?.CANFD;
+ string title = _systemConfig.Title;
+ char lastChar = title[title.Length - 1];
+ // 3. "TestCellX"转int
+ MessageChannel = int.Parse(lastChar.ToString())-1;
+ RaisePropertyChanged(nameof(ConfigurationList));
+ }
+ #endregion
+
+ #region 命令处理
+ private void Delete()
+ {
+ if (SelectedItem != null)
+ {
+ _systemConfig?.ConfigurationList.Remove(SelectedItem);
+ }
+ }
+
+ private void Save()
+ {
+ ConfigService.Save(_systemConfig);
+ }
+
+
+ private void Add()
+ {
+ if (string.IsNullOrEmpty(SelectedSignal) || string.IsNullOrEmpty(SelectedMessage) || CollectionInterval < 100)
+ {
+ return;
+ }
+ if (_systemConfig == null) return;
+
+ string hexString = ExtractHex(SelectedMessage);
+ if (string.IsNullOrEmpty(hexString)) return;
+
+ int decimalValue = ConvertHexToDecimal(hexString);
+ if (_systemConfig.ConfigurationList.Any(x => x.SignalName == SelectedSignal && x.Channel == MessageChannel))
+ {
+ return;
+ }
+
+ _systemConfig.ConfigurationList.Add(new CANSignalConfig
+ {
+ CollectionID = Guid.NewGuid(),
+ Channel = MessageChannel,
+ MessageName = ExtractMessageName(SelectedMessage),
+ SignalName = SelectedSignal,
+ MessageID = decimalValue,
+ CollectionInterval = CollectionInterval
+ });
+ }
+
+ private string ExtractHex(string input)
+ {
+ int startIndex = input.IndexOf("0x") + 2;
+ int endIndex = input.IndexOf("]", startIndex);
+ if (startIndex >= 2 && endIndex > startIndex)
+ {
+ return input.Substring(startIndex, endIndex - startIndex);
+ }
+ return string.Empty;
+ }
+
+ private int ConvertHexToDecimal(string hex)
+ {
+ try
+ {
+ return Convert.ToInt32(hex, 16);
+ }
+ catch (FormatException)
+ {
+ return -1;
+ }
+ }
+
+ private string ExtractMessageName(string input)
+ {
+ var parts = input.Split(']');
+ return parts.Length > 1 ? parts[1] : string.Empty;
+ }
+
+ private void Close()
+ {
+ RequestClose.Invoke();
+ }
+ #endregion
+ }
+}
diff --git a/CANModule/ViewModels/ZLGCANFDViewModel.cs b/CANModule/ViewModels/ZLGCANFDViewModel.cs
new file mode 100644
index 0000000..9688c8a
--- /dev/null
+++ b/CANModule/ViewModels/ZLGCANFDViewModel.cs
@@ -0,0 +1,649 @@
+using Microsoft.Win32;
+using System;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Input;
+using UIShare.GlobalVariable;
+using UIShare.UIViewModel;
+using UIShare.ViewModelBase;
+using ZLGUSBCANFD;
+
+namespace CANModule.ViewModels
+{
+ public class ZLGCANFDViewModel : NavigateViewModelBase
+ {
+ #region 字段
+ private ZLGCANFD? _canfd;
+ private SystemConfig? _systemConfig;
+ private CancellationTokenSource? _refreshCts;
+ private readonly DeviceManager _deviceManager;
+ #endregion
+
+ #region 属性
+ private string _Title = "周立功CAN";
+ public string Title
+ {
+ get => _Title;
+ set => SetProperty(ref _Title, value);
+ }
+
+ private ObservableCollection _CanMessageList = new();
+ public ObservableCollection CanMessageList
+ {
+ get => _CanMessageList;
+ set => SetProperty(ref _CanMessageList, value);
+ }
+
+ private int _DBCChannel = 0;
+ public int DBCChannel
+ {
+ get => _DBCChannel;
+ set => SetProperty(ref _DBCChannel, value);
+ }
+
+ private bool _IsDirectlySend = false;
+ public bool IsDirectlySend
+ {
+ get => _IsDirectlySend;
+ set => SetProperty(ref _IsDirectlySend, value);
+ }
+
+ private ObservableCollection _Message;
+ public ObservableCollection Message
+ {
+ get => _Message;
+ set => SetProperty(ref _Message, value);
+ }
+
+ private ObservableCollection _Signal;
+ public ObservableCollection Signal
+ {
+ get => _Signal;
+ set => SetProperty(ref _Signal, value);
+ }
+
+ private byte _channel;
+ private string _selectedMessage;
+ public string SelectedMessage
+ {
+ get => _selectedMessage;
+ set
+ {
+ if (_selectedMessage != value)
+ {
+ if (!string.IsNullOrEmpty(value) && _canfd != null)
+ {
+ var db = _canfd.DBCParser.MsgDatabase;
+ if (_channel >= 0 && _channel < db.Count)
+ {
+ var targetMsg = db[(int)_channel]
+ .FirstOrDefault(x => $"[0x{x.msg_id:X}]{x.msg_name}" == value);
+
+ if (targetMsg != null && targetMsg.signal_Name != null)
+ {
+ Signal = new ObservableCollection(targetMsg.signal_Name);
+ }
+ else
+ {
+ Signal = new ObservableCollection();
+ }
+ }
+ }
+ else
+ {
+ Signal = new ObservableCollection();
+ }
+ _selectedMessage = value;
+ RaisePropertyChanged();
+ }
+ }
+ }
+
+ private string _selectedSignal;
+ public string SelectedSignal
+ {
+ get => _selectedSignal;
+ set => SetProperty(ref _selectedSignal, value);
+ }
+
+ private string _signalValue;
+ public string SignalValue
+ {
+ get => _signalValue;
+ set => SetProperty(ref _signalValue, value);
+ }
+
+ private string _cycleSendInterval;
+ public string CycleSendInterval
+ {
+ get => _cycleSendInterval;
+ set => SetProperty(ref _cycleSendInterval, value);
+ }
+
+ private int _messageSendChannel = 0;
+ public int MessageSendChannel
+ {
+ get => _messageSendChannel;
+ set => SetProperty(ref _messageSendChannel, value);
+ }
+
+ public string BLFPath
+ {
+ get => _systemConfig?.DefaultBLFFilePath ?? "";
+ set
+ {
+ if (_systemConfig != null && _systemConfig.DefaultBLFFilePath != value)
+ {
+ _systemConfig.DefaultBLFFilePath = value;
+ RaisePropertyChanged();
+ }
+ }
+ }
+
+ public string DBCPath
+ {
+ get => _systemConfig?.DefaultDBCFilePath ?? "";
+ set
+ {
+ if (_systemConfig != null && _systemConfig.DefaultDBCFilePath != value)
+ {
+ _systemConfig.DefaultDBCFilePath = value;
+ RaisePropertyChanged();
+ }
+ }
+ }
+
+ private bool _IsSaved;
+ public bool IsSaved
+ {
+ get => _IsSaved;
+ set => SetProperty(ref _IsSaved, value);
+ }
+
+ public ObservableCollection dbcAutoLoadList
+ {
+ get => _systemConfig?.dbcAutoLoadList ?? new ObservableCollection();
+ }
+
+ private AutoDBCLoadItem _SelectedDcAutoLoad;
+ public AutoDBCLoadItem SelectedDcAutoLoad
+ {
+ get => _SelectedDcAutoLoad;
+ set => SetProperty(ref _SelectedDcAutoLoad, value);
+ }
+
+ // ===== 自定义报文发送属性 =====
+ private APP_CHANNEL[] _appChannelNames = Enum.GetValues();
+ public APP_CHANNEL[] APP_CHANNEL
+ {
+ get => _appChannelNames;
+ set => SetProperty(ref _appChannelNames, value);
+ }
+
+ private APP_CHANNEL _aIdxChn;
+ public APP_CHANNEL AIdxChn
+ {
+ get => _aIdxChn;
+ set => SetProperty(ref _aIdxChn, value);
+ }
+
+ private int _aID;
+ public int AID
+ {
+ get => _aID;
+ set => SetProperty(ref _aID, value);
+ }
+
+ private bool _aIsTx;
+ public bool AIsTx
+ {
+ get => _aIsTx;
+ set => SetProperty(ref _aIsTx, value);
+ }
+
+ private bool _aIsExt;
+ public bool AIsExt
+ {
+ get => _aIsExt;
+ set => SetProperty(ref _aIsExt, value);
+ }
+
+ private bool _aIsRemote;
+ public bool AIsRemote
+ {
+ get => _aIsRemote;
+ set => SetProperty(ref _aIsRemote, value);
+ }
+
+ private byte _aDlc;
+ public byte ADLC
+ {
+ get => _aDlc;
+ set => SetProperty(ref _aDlc, value);
+ }
+
+ private byte[] _aDataArray;
+ public byte[] ADataArray
+ {
+ get => _aDataArray;
+ set => SetProperty(ref _aDataArray, value);
+ }
+
+ private bool _aIsFD = true;
+ public bool AIsFD
+ {
+ get => _aIsFD;
+ set => SetProperty(ref _aIsFD, value);
+ }
+
+ private bool _aIsBRS = false;
+ public bool AIsBRS
+ {
+ get => _aIsBRS;
+ set => SetProperty(ref _aIsBRS, value);
+ }
+
+ private bool _AutoSetting = true;
+ public bool AutoSetting
+ {
+ get => _AutoSetting;
+ set => SetProperty(ref _AutoSetting, value);
+ }
+
+ private string _CustomMessage = "[00,11,22,33,AA,BB,CC,DD]";
+ public string CustomMessage
+ {
+ get => _CustomMessage;
+ set => SetProperty(ref _CustomMessage, value);
+ }
+
+ private float _CustomSendCycleInterval = 0.0f;
+ public float CustomSendCycleInterval
+ {
+ get => _CustomSendCycleInterval;
+ set => SetProperty(ref _CustomSendCycleInterval, value);
+ }
+
+ //private bool _UpdateToDB;
+ //public bool UpdateToDB
+ //{
+ // get => _UpdateToDB;
+ // set => SetProperty(ref _UpdateToDB, value);
+ //}
+
+ // ===== 连接状态 =====
+ private bool _IsDeviceOpened;
+ public bool IsDeviceOpened
+ {
+ get => _IsDeviceOpened;
+ set => SetProperty(ref _IsDeviceOpened, value);
+ }
+
+ private ObservableCollection _ChannelList;
+ public ObservableCollection ChannelList
+ {
+ get => _ChannelList;
+ set => SetProperty(ref _ChannelList, value);
+ }
+
+ private int _SelectedChannel = -1;
+ public int SelectedChannel
+ {
+ get => _SelectedChannel;
+ set
+ {
+ if (_SelectedChannel != value)
+ {
+ _SelectedChannel = value;
+ if (value >= 0 && _canfd != null)
+ {
+ _canfd.初始化并启动通道((uint)value);
+ }
+ RaisePropertyChanged();
+ }
+ }
+ }
+ #endregion
+
+ #region 命令
+ public ICommand SelectBLFPathCommand { get; set; }
+ public ICommand SaveBLFPathCommand { get; set; }
+ public ICommand StartTranscribeCommand { get; set; }
+ public ICommand EndTranscribeCommand { get; set; }
+ public ICommand ConnectCanCommand { get; set; }
+ public ICommand CloseCanCommand { get; set; }
+ public ICommand ClearCycleCommand { get; set; }
+ public ICommand UpLoadDBCCommand { get; set; }
+ public ICommand ChangeDBCCommand { get; set; }
+ public ICommand LoadDBCCommand { get; set; }
+ public ICommand LoadMessageCommand { get; set; }
+ public ICommand SetAndSendMessageCommand { get; set; }
+ public ICommand DeleteDcAutoLoadCommand { get; set; }
+ public ICommand SendCustomMessageCommand { get; set; }
+ public ICommand LoadCommand { get; set; }
+ #endregion
+
+ public ZLGCANFDViewModel(IContainerProvider containerProvider) : base(containerProvider)
+ {
+ _systemConfig = containerProvider.Resolve();
+ _deviceManager = containerProvider.Resolve();
+ _canfd = _deviceManager.CANFD;
+ SelectBLFPathCommand = new DelegateCommand(SelectBLFPath);
+ SaveBLFPathCommand = new DelegateCommand(SaveBLFPath);
+ StartTranscribeCommand = new DelegateCommand(StartTranscribe);
+ EndTranscribeCommand = new DelegateCommand(EndTranscribe);
+ ConnectCanCommand = new DelegateCommand(ConnectCan);
+ CloseCanCommand = new DelegateCommand(CloseCan);
+ ClearCycleCommand = new DelegateCommand(ClearCycle);
+ UpLoadDBCCommand = new DelegateCommand(UpLoadDBC);
+ ChangeDBCCommand = new DelegateCommand(ChangeDBC);
+ LoadDBCCommand = new DelegateCommand(LoadDBC);
+ SetAndSendMessageCommand = new DelegateCommand(SetAndSendMessage);
+ LoadMessageCommand = new DelegateCommand(LoadMessage);
+ DeleteDcAutoLoadCommand = new DelegateCommand(DeleteDcAutoLoad);
+ SendCustomMessageCommand = new DelegateCommand(SendCustomMessage);
+ _canfd.OnDbcMessageDecoded += OnDbcMessageDecoded;
+ LoadCommand = new DelegateCommand(Load);
+ }
+
+ #region Dialog 生命周期
+ public override void OnNavigatedTo(NavigationContext navigationContext)
+ {
+ if (_canfd != null)
+ {
+
+ }
+
+ RaisePropertyChanged(nameof(BLFPath));
+ RaisePropertyChanged(nameof(DBCPath));
+ RaisePropertyChanged(nameof(dbcAutoLoadList));
+ }
+
+ public override void OnNavigatedFrom(NavigationContext navigationContext)
+ {
+ if (_canfd != null)
+ {
+ _canfd.OnDbcMessageDecoded -= OnDbcMessageDecoded;
+ }
+ _refreshCts?.Cancel();
+ }
+ #endregion
+
+ #region 命令处理
+ private void Load()
+ {
+ int maxCh = _canfd?.DBCParser.MaxChannels ?? 4;
+ ChannelList = new ObservableCollection(Enumerable.Range(0, maxCh));
+ }
+
+ private void SendCustomMessage()
+ {
+ if (_canfd == null) return;
+
+ try
+ {
+ ADataArray = 报文转换(CustomMessage);
+ if (ADataArray.Length > byte.MaxValue) throw new Exception("报文数量超过上限!");
+ if (AutoSetting)
+ {
+ ADLC = (byte)ADataArray.Length;
+ }
+ }
+ catch (Exception ex)
+ {
+ ShowErrorMessageBox($"报文转换失败:{ex.Message}", () => { });
+ return;
+ }
+
+ _canfd.发送自定义报文(
+ (uint)AIdxChn,
+ AID.ToString(),
+ ADataArray,
+ ADLC,
+ AIsExt,
+ AIsFD,
+ AIsBRS);
+ }
+
+ private void DeleteDcAutoLoad()
+ {
+ if (SelectedDcAutoLoad != null)
+ {
+ dbcAutoLoadList.Remove(SelectedDcAutoLoad);
+ }
+ }
+
+ private void LoadMessage()
+ {
+ if (_canfd == null) return;
+
+ if (MessageSendChannel >= 0)
+ {
+ var db = _canfd.DBCParser.MsgDatabase;
+ if (MessageSendChannel < db.Count)
+ {
+ Message = new ObservableCollection(
+ db[MessageSendChannel].Select(s => $"[0x{s.msg_id:X}]{s.msg_name}"));
+ }
+ }
+ }
+
+ private void SetAndSendMessage()
+ {
+ if (_canfd == null) return;
+
+ if (int.TryParse(CycleSendInterval, out int sendPeriod) &&
+ double.TryParse(SignalValue, out double SValue) &&
+ MessageSendChannel >= 0)
+ {
+ _channel = (byte)MessageSendChannel;
+ var message = SelectedMessage.Split(']')[1];
+
+ // 通过 DBC 查找帧 ID
+ var db = _canfd.DBCParser.MsgDatabase;
+ if (MessageSendChannel < db.Count)
+ {
+ var targetMsg = db[MessageSendChannel]
+ .FirstOrDefault(x => $"[0x{x.msg_id:X}]{x.msg_name}" == SelectedMessage);
+
+ if (targetMsg != null)
+ {
+ _canfd.设置报文((uint)MessageSendChannel, targetMsg.msg_id.ToString(), SelectedSignal, SValue, sendPeriod);
+ }
+ }
+ }
+ }
+
+ private void UpLoadDBC()
+ {
+ if (_canfd == null) return;
+
+ // 释放当前通道的 DBC
+ if (DBCChannel >= 0)
+ {
+ _canfd.释放通道DBC((uint)DBCChannel);
+ }
+ }
+
+ private void ChangeDBC()
+ {
+ var dialog = new OpenFileDialog
+ {
+ Title = "更换DBC文件",
+ Filter = "DBC 文件 (*.dbc)|*.dbc|所有文件 (*.*)|*.*",
+ DefaultExt = ".dbc",
+ };
+ if (dialog.ShowDialog() == true)
+ {
+ DBCPath = System.IO.Path.GetFullPath(dialog.FileName);
+ }
+ }
+
+ private void LoadDBC()
+ {
+ if (_canfd == null || DBCChannel < 0) return;
+
+ bool re = _canfd.加载通道DBC文件((uint)DBCChannel, DBCPath);
+
+ if (re && IsSaved)
+ {
+ var item = dbcAutoLoadList.FirstOrDefault(s => s.DBCChannel == DBCChannel);
+ if (item == null)
+ {
+ dbcAutoLoadList.Add(new AutoDBCLoadItem
+ {
+ DBCFilePath = DBCPath,
+ DBCChannel = DBCChannel
+ });
+ }
+ else
+ {
+ dbcAutoLoadList.Remove(item);
+ dbcAutoLoadList.Add(new AutoDBCLoadItem
+ {
+ DBCFilePath = DBCPath,
+ DBCChannel = DBCChannel
+ });
+ }
+ ConfigService.Save(_systemConfig);
+ }
+ }
+ private void ClearCycle()
+ {
+ _canfd?.停止所有循环发送();
+ }
+
+ private void CloseCan()
+ {
+ if (_canfd == null) return;
+
+ _canfd.关闭CAN卡设备();
+ IsDeviceOpened = false;
+ _refreshCts?.Cancel();
+ }
+
+ private void ConnectCan()
+ {
+ if (_canfd == null) return;
+
+ bool re = _canfd.打开设备();
+ IsDeviceOpened = re;
+
+ if (re)
+ {
+ // 启动实时报文刷新
+ _refreshCts?.Cancel();
+ _refreshCts = new CancellationTokenSource();
+ _ = Refresh(_refreshCts.Token);
+ }
+ }
+
+ private void EndTranscribe()
+ {
+ // TODO: BLF 录制功能在 ZLGCANFD 中未实现,暂不支持
+ ShowInfoMessageBox("BLF 录制功能尚未在此硬件驱动中实现。", () => { });
+ }
+
+ private void StartTranscribe()
+ {
+ // TODO: BLF 录制功能在 ZLGCANFD 中未实现,暂不支持
+ ShowInfoMessageBox("BLF 录制功能尚未在此硬件驱动中实现。", () => { });
+ }
+
+ private void SaveBLFPath()
+ {
+ // 路径已直接绑定到 SystemConfig,无需额外操作
+ }
+
+ private void SelectBLFPath()
+ {
+ var dialog = new SaveFileDialog
+ {
+ Title = "保存 CAN报文回放 BLF 文件",
+ Filter = "BLF 文件 (*.blf)|*.blf|所有文件 (*.*)|*.*",
+ DefaultExt = ".blf",
+ FileName = "log.blf",
+ OverwritePrompt = true
+ };
+ if (dialog.ShowDialog() == true)
+ {
+ BLFPath = System.IO.Path.GetFullPath(dialog.FileName);
+ }
+ }
+
+ #endregion
+
+ #region 辅助方法
+ public byte[] 报文转换(string s)
+ {
+ s = s.Replace("[", string.Empty).Replace("]", string.Empty);
+ var strs = s.Split(',', StringSplitOptions.RemoveEmptyEntries);
+ byte[] bytes = new byte[strs.Length];
+ for (int i = 0; i < strs.Length; i++)
+ {
+ bytes[i] = Convert.ToByte(strs[i], 16);
+ }
+ return bytes;
+ }
+
+ private async Task Refresh(CancellationToken ct = default)
+ {
+ while (!ct.IsCancellationRequested)
+ {
+ // 通过 OnDbcMessageDecoded 事件已实时更新 CanMessageList
+ // 此处仅做周期性 UI 刷新触发
+ await Task.Delay(50, ct);
+ }
+ }
+
+ private void OnDbcMessageDecoded(uint channel, ZDBC.DBCMessage msg)
+ {
+ // DBC 解码后的报文回调
+ Application.Current.Dispatcher.Invoke(() =>
+ {
+ var msgName = System.Text.Encoding.Default.GetString(msg.strName).TrimEnd('\0');
+ var find = CanMessageList.FirstOrDefault(s => s.报文ID == (int)msg.nID);
+ if (find != null)
+ {
+ find.通道 = (byte)channel;
+ find.报文ID = (int)msg.nID;
+ find.时间戳 = (ulong)DateTimeOffset.Now.ToUnixTimeMilliseconds(); ;
+ find.长度 = (byte)msg.nSize;
+ }
+ else
+ {
+ CanMessageList.Add(new CanMessageShowVM
+ {
+ 通道 = (byte)channel,
+ 报文ID = (int)msg.nID,
+ 时间戳 = (ulong)DateTimeOffset.Now.ToUnixTimeMilliseconds(),
+ 长度 = (byte)msg.nSize
+ });
+ }
+ });
+ }
+
+ private string 十六进制字符串转换(System.Span s)
+ {
+ if (s == null || s.Length == 0)
+ return "[]";
+
+ var sb = new StringBuilder();
+ sb.Append('[');
+ for (int i = 0; i < s.Length; i++)
+ {
+ sb.Append("0x");
+ sb.Append(s[i].ToString("X2"));
+ if (i < s.Length - 1)
+ sb.Append(", ");
+ }
+ sb.Append(']');
+ return sb.ToString();
+ }
+ #endregion
+ }
+}
diff --git a/CANModule/Views/CollectCANSignalSettingView.xaml b/CANModule/Views/CollectCANSignalSettingView.xaml
new file mode 100644
index 0000000..dfb3fa9
--- /dev/null
+++ b/CANModule/Views/CollectCANSignalSettingView.xaml
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/CANModule/Views/CollectCANSignalSettingView.xaml.cs b/CANModule/Views/CollectCANSignalSettingView.xaml.cs
new file mode 100644
index 0000000..5bd739e
--- /dev/null
+++ b/CANModule/Views/CollectCANSignalSettingView.xaml.cs
@@ -0,0 +1,25 @@
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Input;
+
+namespace CANModule.Views
+{
+ ///
+ /// CollectCANSignalSettingView.xaml 的交互逻辑
+ ///
+ public partial class CollectCANSignalSettingView : UserControl
+ {
+ public CollectCANSignalSettingView()
+ {
+ InitializeComponent();
+ }
+
+ private void MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
+ {
+ if (e.LeftButton == MouseButtonState.Pressed)
+ {
+ Window.GetWindow(this)?.DragMove();
+ }
+ }
+ }
+}
diff --git a/CANModule/Views/ZLGCANFDView.xaml b/CANModule/Views/ZLGCANFDView.xaml
new file mode 100644
index 0000000..3c5a562
--- /dev/null
+++ b/CANModule/Views/ZLGCANFDView.xaml
@@ -0,0 +1,286 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/CANModule/Views/ZLGCANFDView.xaml.cs b/CANModule/Views/ZLGCANFDView.xaml.cs
new file mode 100644
index 0000000..2e4e7f6
--- /dev/null
+++ b/CANModule/Views/ZLGCANFDView.xaml.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace CANModule.Views
+{
+ ///
+ /// ZLGCANFDView.xaml 的交互逻辑
+ ///
+ public partial class ZLGCANFDView : UserControl
+ {
+ public ZLGCANFDView()
+ {
+ InitializeComponent();
+ }
+ private void MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
+ {
+ if (e.LeftButton == MouseButtonState.Pressed)
+ {
+ Window.GetWindow(this)?.DragMove();
+ }
+ }
+ }
+}
diff --git a/UIShare/GlobalVariable/DeviceManager.cs b/UIShare/GlobalVariable/DeviceManager.cs
index 1eeab02..4aa642b 100644
--- a/UIShare/GlobalVariable/DeviceManager.cs
+++ b/UIShare/GlobalVariable/DeviceManager.cs
@@ -96,8 +96,10 @@ namespace UIShare.GlobalVariable
try
{
// 按指纹全局唯一创建 ZLGCANFD 实例(maxChannels 默认 4,对应 USBCANFD-400U)
+ // 波特率与终端电阻从 CANConfigVM 传入,初始化并启动通道 时直接使用
var canLazy = _globalInfo.CanPool.GetOrAdd(fingerprint, key => new Lazy(() =>
- new ZLGCANFD(config.CANConfig.DeviceType, config.CANConfig.DeviceIndex, 4)));
+ new ZLGCANFD(config.CANConfig.DeviceType, config.CANConfig.DeviceIndex, 4,
+ config.CANConfig.ABitBaud, config.CANConfig.DBitBaud, config.CANConfig.EnableTerminalResistance)));
_systemConfig.CANFD = canLazy.Value;
CANFD = canLazy.Value;
@@ -190,15 +192,22 @@ namespace UIShare.GlobalVariable
public async Task ConnectAllDevices(CancellationToken ct = default)
{
- if (_systemConfig?.DeviceList == null || DeviceMap.Count == 0) return;
+ if (_systemConfig?.DeviceList == null) return;
var tasks = new List();
foreach (var info in _systemConfig.DeviceList)
{
if (info == null || !info.IsEnabled) continue;
if (string.IsNullOrWhiteSpace(info.DeviceName)) continue;
- if (!DeviceMap.TryGetValue(info.DeviceName, out var device)) continue;
+ // CAN 设备:直接打开 CAN 卡
+ if (string.Equals(info.ConnectionType, "CAN", StringComparison.OrdinalIgnoreCase))
+ {
+ tasks.Add(ConnectCanAsync(info));
+ continue;
+ }
+
+ if (!DeviceMap.TryGetValue(info.DeviceName, out var device)) continue;
tasks.Add(ConnectInternalAsync(info, device, ct));
}
@@ -214,15 +223,28 @@ namespace UIShare.GlobalVariable
return;
}
+ var info = _systemConfig?.DeviceList?
+ .FirstOrDefault(d => d != null && string.Equals(d.DeviceName, deviceName, StringComparison.OrdinalIgnoreCase));
+
+ if (info == null)
+ {
+ LoggerHelper.Warn($"ConnectSpecifiedDevice:未找到设备配置 [{deviceName}]。");
+ return;
+ }
+
+ // CAN 设备:直接打开 CAN 卡
+ if (string.Equals(info.ConnectionType, "CAN", StringComparison.OrdinalIgnoreCase))
+ {
+ await ConnectCanAsync(info);
+ return;
+ }
+
if (!DeviceMap.TryGetValue(deviceName, out var device))
{
LoggerHelper.Warn($"ConnectSpecifiedDevice:未找到设备 [{deviceName}]。");
return;
}
- var info = _systemConfig?.DeviceList?
- .FirstOrDefault(d => d != null && string.Equals(d.DeviceName, deviceName, StringComparison.OrdinalIgnoreCase));
-
await ConnectInternalAsync(info, device, ct);
}
@@ -233,15 +255,21 @@ namespace UIShare.GlobalVariable
{
if (string.IsNullOrWhiteSpace(deviceName)) return;
+ var info = _systemConfig?.DeviceList?
+ .FirstOrDefault(d => d != null && string.Equals(d.DeviceName, deviceName, StringComparison.OrdinalIgnoreCase));
+
+ // CAN 设备:直接关闭 CAN 卡
+ if (info != null && string.Equals(info.ConnectionType, "CAN", StringComparison.OrdinalIgnoreCase))
+ {
+ await CloseCanAsync(info);
+ return;
+ }
+
IBaseInterface? device;
- DeviceInfoVM? info;
lock (_lockObj)
{
if (!DeviceMap.TryGetValue(deviceName, out device)) return;
-
- info = _systemConfig?.DeviceList?
- .FirstOrDefault(d => d != null && string.Equals(d.DeviceName, deviceName, StringComparison.OrdinalIgnoreCase));
}
await CloseInternalAsync(info, device);
@@ -256,7 +284,7 @@ namespace UIShare.GlobalVariable
lock (_lockObj)
{
- if (DeviceMap.Count == 0) return;
+ if (DeviceMap.Count == 0 && (CANFD == null)) return;
foreach (var kvp in DeviceMap)
{
@@ -269,6 +297,17 @@ namespace UIShare.GlobalVariable
}
}
+ // CAN 设备:直接关闭 CAN 卡
+ if (CANFD != null)
+ {
+ var canInfo = _systemConfig?.DeviceList?
+ .FirstOrDefault(d => d != null && string.Equals(d.ConnectionType, "CAN", StringComparison.OrdinalIgnoreCase));
+ if (canInfo != null)
+ {
+ tasks.Add(CloseCanAsync(canInfo));
+ }
+ }
+
await Task.WhenAll(tasks);
LoggerHelper.Info("所有设备已执行关闭操作。");
}
@@ -366,6 +405,88 @@ namespace UIShare.GlobalVariable
}
return await sp.ConnectAsync(ct);
}
+
+ ///
+ /// 打开 CAN 卡:打开设备 + 初始化并启动所有通道
+ ///
+ private async Task ConnectCanAsync(DeviceInfoVM info)
+ {
+ string name = info.DeviceName ?? "CAN";
+
+ try
+ {
+ if (CANFD == null)
+ {
+ LoggerHelper.Warn($"CAN 设备 [{name}] 尚未实例化,无法连接。");
+ info.IsConnected = false;
+ return false;
+ }
+
+ if (info.IsConnected)
+ {
+ LoggerHelper.Info($"CAN 设备 [{name}] 已连接,跳过。");
+ return true;
+ }
+
+ bool ok = await Task.Run(() =>
+ {
+ if (!CANFD.打开设备()) return false;
+ return true;
+ });
+
+ info.IsConnected = ok;
+
+ if (ok)
+ LoggerHelper.Info($"CAN 设备 [{name}] 连接成功,已初始化 {CANFD.DBCParser.MaxChannels} 个通道。");
+ else
+ LoggerHelper.Warn($"CAN 设备 [{name}] 连接失败。");
+
+ return ok;
+ }
+ catch (Exception ex)
+ {
+ info.IsConnected = false;
+ var inner = ex.InnerException?.Message ?? ex.Message;
+ LoggerHelper.ErrorWithNotify(_scopeName, $"CAN 设备 [{name}] 连接异常:{inner}");
+ return false;
+ }
+ }
+
+ ///
+ /// 关闭 CAN 卡
+ ///
+ private async Task CloseCanAsync(DeviceInfoVM info)
+ {
+ string name = info.DeviceName ?? "CAN";
+
+ try
+ {
+ if (CANFD == null)
+ {
+ info.IsConnected = false;
+ return;
+ }
+
+ if (!info.IsConnected)
+ {
+ LoggerHelper.Info($"CAN 设备 [{name}] 本就处于断开状态。");
+ return;
+ }
+
+ await Task.Run(() => CANFD.关闭CAN卡设备());
+ LoggerHelper.Info($"CAN 设备 [{name}] 已成功关闭连接。");
+ }
+ catch (Exception ex)
+ {
+ var inner = ex.InnerException?.Message ?? ex.Message;
+ LoggerHelper.Error($"CAN 设备 [{name}] 关闭连接时出现异常: {inner}");
+ }
+ finally
+ {
+ info.IsConnected = false;
+ }
+ }
+
private static IReadOnlyDictionary BuildDeviceTypeMap()
{
try
diff --git a/UIShare/GlobalVariable/SystemConfig.cs b/UIShare/GlobalVariable/SystemConfig.cs
index a120d3f..15fae0d 100644
--- a/UIShare/GlobalVariable/SystemConfig.cs
+++ b/UIShare/GlobalVariable/SystemConfig.cs
@@ -30,6 +30,8 @@ namespace UIShare.GlobalVariable
public string DefaultDBCFilePath { get; set; } = "";
public ObservableCollection DeviceList = new();
public ObservableCollection SharedParameterList = new();
+ public ObservableCollection ConfigurationList = new();
+ public ObservableCollection dbcAutoLoadList = new();
public ZLGCANFD CANFD = new();
[JsonIgnore]
public ObservableCollection ParameterList = new()
diff --git a/UIShare/UIViewModel/AutoDBCLoadItemVM.cs b/UIShare/UIViewModel/AutoDBCLoadItemVM.cs
new file mode 100644
index 0000000..b977ec3
--- /dev/null
+++ b/UIShare/UIViewModel/AutoDBCLoadItemVM.cs
@@ -0,0 +1,33 @@
+namespace UIShare.UIViewModel
+{
+ ///
+ /// CAN 通道枚举(对应 ZLGCANFD 通道选择)
+ ///
+ public enum APP_CHANNEL
+ {
+ CH0 = 0,
+ CH1 = 1,
+ CH2 = 2,
+ CH3 = 3
+ }
+
+ ///
+ /// DBC 自动加载配置项
+ ///
+ public class AutoDBCLoadItem : BindableBase
+ {
+ private int _dbcChannel;
+ public int DBCChannel
+ {
+ get => _dbcChannel;
+ set => SetProperty(ref _dbcChannel, value);
+ }
+
+ private string _dbcFilePath;
+ public string DBCFilePath
+ {
+ get => _dbcFilePath;
+ set => SetProperty(ref _dbcFilePath, value);
+ }
+ }
+}
diff --git a/UIShare/UIViewModel/CANSignalConfigVM.cs b/UIShare/UIViewModel/CANSignalConfigVM.cs
new file mode 100644
index 0000000..2fa8093
--- /dev/null
+++ b/UIShare/UIViewModel/CANSignalConfigVM.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace UIShare.UIViewModel
+{
+ public class CANSignalConfig
+ {
+ public int Channel { get; set; }
+ public int MessageID { get; set; }
+ public string MessageName { get; set; }
+ public string SignalName { get; set; }
+ public int CollectionInterval { get; set; }
+ public Guid CollectionID { get; set; }
+ }
+}
diff --git a/UIShare/UIViewModel/CanMessageShowVM.cs b/UIShare/UIViewModel/CanMessageShowVM.cs
index 5c226a1..d406b6c 100644
--- a/UIShare/UIViewModel/CanMessageShowVM.cs
+++ b/UIShare/UIViewModel/CanMessageShowVM.cs
@@ -5,12 +5,9 @@
// 字段声明
private byte _通道;
private int _报文ID;
- private ulong _时间戳;
+ private double _时间戳;
private byte _长度;
- private bool _fd;
- private bool _isTx;
- private byte[] _bytes = new byte[64];
- private string _报文;
+
// 通道属性
public byte 通道
@@ -27,7 +24,7 @@
}
// 时间戳属性
- public ulong 时间戳
+ public double 时间戳
{
get { return _时间戳; }
set { SetProperty(ref _时间戳, value); }
@@ -40,32 +37,6 @@
set { SetProperty(ref _长度, value); }
}
- // FD属性
- public bool FD
- {
- get { return _fd; }
- set { SetProperty(ref _fd, value); }
- }
-
- // IsTx属性
- public bool IsTx
- {
- get { return _isTx; }
- set { SetProperty(ref _isTx, value); }
- }
-
- // Bytes属性
- public byte[] Bytes
- {
- get { return _bytes; }
- set { SetProperty(ref _bytes, value); }
- }
-
- // 报文属性
- public string 报文
- {
- get { return _报文; }
- set { SetProperty(ref _报文, value); }
- }
+
}
}
diff --git a/UIShare/ViewModelBase/DialogViewModelBase.cs b/UIShare/ViewModelBase/DialogViewModelBase.cs
index a6c15bd..261afc2 100644
--- a/UIShare/ViewModelBase/DialogViewModelBase.cs
+++ b/UIShare/ViewModelBase/DialogViewModelBase.cs
@@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using Prism.Dialogs;
namespace UIShare.ViewModelBase
{
@@ -11,12 +12,41 @@ namespace UIShare.ViewModelBase
{
public DialogCloseListener RequestClose { get; set; }
public IEventAggregator _eventAggregator;
+ public IDialogService _dialogService;
private INotificationManager _notificationManager;
public DialogViewModelBase(IContainerProvider containerProvider)
{
_eventAggregator = containerProvider.Resolve();
+ _dialogService = containerProvider.Resolve();
_notificationManager = containerProvider.Resolve();
}
+
+ protected void ShowInfoMessageBox(string Message, Action callback)
+ {
+ var dialogParams = new DialogParameters();
+ dialogParams.Add("Title", "提示");
+ dialogParams.Add("Message", Message);
+ dialogParams.Add("Icon", "info");
+ dialogParams.Add("ShowOk", true);
+ _dialogService.ShowDialog("MessageBoxView", dialogParams, result =>
+ {
+ callback();
+ });
+ }
+
+ protected void ShowErrorMessageBox(string Message, Action callback)
+ {
+ var dialogParams = new DialogParameters();
+ dialogParams.Add("Title", "错误");
+ dialogParams.Add("Message", Message);
+ dialogParams.Add("Icon", "info");
+ dialogParams.Add("ShowOk", true);
+ _dialogService.ShowDialog("MessageBoxView", dialogParams, result =>
+ {
+ callback();
+ });
+ }
+
#region Dialog
public virtual bool CanCloseDialog() => true;
diff --git a/ZLGUSBCANFD/USBCANFD.cs b/ZLGUSBCANFD/USBCANFD.cs
index 1862831..0e6beeb 100644
--- a/ZLGUSBCANFD/USBCANFD.cs
+++ b/ZLGUSBCANFD/USBCANFD.cs
@@ -34,6 +34,11 @@ namespace ZLGUSBCANFD
private readonly uint _deviceIndex; // 设备索引
private readonly int _maxChannels; // 动态通道数
+ // 通道波特率与终端电阻配置(构造时传入,所有通道共用)
+ private readonly string _abitBaud;
+ private readonly string _dbitBaud;
+ private readonly bool _enableTerminalResistance;
+
///
/// 当前 CAN 卡专属的 DBC 解析器,按通道隔离报文数据库。
///
@@ -45,11 +50,15 @@ namespace ZLGUSBCANFD
///
public event Action? OnDbcMessageDecoded;
- public ZLGCANFD(uint deviceType = 76, uint deviceIndex = 0, int maxChannels = 4)
+ public ZLGCANFD(uint deviceType = 76, uint deviceIndex = 0, int maxChannels = 4,
+ string abitBaud = "500000", string dbitBaud = "2000000", bool enableTerminalResistance = true)
{
_deviceType = deviceType;
_deviceIndex = deviceIndex;
_maxChannels = maxChannels;
+ _abitBaud = abitBaud;
+ _dbitBaud = dbitBaud;
+ _enableTerminalResistance = enableTerminalResistance;
// 初始化通道相关状态数组
_channelHandles = new IntPtr[_maxChannels];
@@ -80,9 +89,9 @@ namespace ZLGUSBCANFD
}
///
- /// 针对特定通道进行参数初始化并启动
+ /// 针对特定通道进行参数初始化并启动(使用构造时传入的波特率与终端电阻配置)
///
- public virtual bool 初始化并启动通道(uint 通道号, string abitBaud = "500000", string dbitBaud = "2000000", bool 开启终端电阻 = true)
+ public virtual bool 初始化并启动通道(uint 通道号)
{
if (_deviceHandle == IntPtr.Zero) throw new InvalidOperationException("请先调用 '打开设备()' 才能初始化通道。");
if (通道号 >= _maxChannels) return false;
@@ -96,11 +105,11 @@ namespace ZLGUSBCANFD
}
// 1. 设置该通道专属的仲裁域与数据域波特率
- if (ZLGCAN.ZCAN_SetValue(_deviceHandle, $"{通道号}/canfd_abit_baud_rate", abitBaud) != 1) return false;
- if (ZLGCAN.ZCAN_SetValue(_deviceHandle, $"{通道号}/canfd_dbit_baud_rate", dbitBaud) != 1) return false;
+ if (ZLGCAN.ZCAN_SetValue(_deviceHandle, $"{通道号}/canfd_abit_baud_rate", _abitBaud) != 1) return false;
+ if (ZLGCAN.ZCAN_SetValue(_deviceHandle, $"{通道号}/canfd_dbit_baud_rate", _dbitBaud) != 1) return false;
// 2. 设置该通道专属内部终端电阻状态
- string resistanceStr = 开启终端电阻 ? "1" : "0";
+ string resistanceStr = _enableTerminalResistance ? "1" : "0";
if (ZLGCAN.ZCAN_SetValue(_deviceHandle, $"{通道号}/initenal_resistance", resistanceStr) != 1) return false;
// 3. 规范配置通道结构体
@@ -179,7 +188,8 @@ namespace ZLGUSBCANFD
try
{
if (_isDbcLoadedArray[通道号]) return true;
-
+ //加载前先卸载
+ 释放通道DBC(通道号);
uint chDbcHandle = ZDBC.ZDBC_Init();
if (chDbcHandle == 0) return false;
@@ -217,6 +227,7 @@ namespace ZLGUSBCANFD
ZDBC.ZDBC_Release(_dbcHandles[通道号]);
_dbcHandles[通道号] = 0;
_isDbcLoadedArray[通道号] = false;
+ DBCParser.MsgDatabase[(int)通道号].Clear();
}
}
}
@@ -440,7 +451,7 @@ namespace ZLGUSBCANFD
ZLGCAN.can_frame canFrame = (ZLGCAN.can_frame)Marshal.PtrToStructure(ptrCanFrame, typeof(ZLGCAN.can_frame));
canFrame.__pad |= 0x20;
- ZLGCAN.ZCAN_Transmit_Data txData = new ZLGCAN.ZCAN_Transmit_Data { frame = canFrame, transmit_type = 0 };
+ ZLGCAN.ZCAN_Transmit_Data txData = new ZLGCAN.ZCAN_Transmit_Data { frame = canFrame, transmit_type = 2 };
IntPtr pTx = Marshal.AllocHGlobal(Marshal.SizeOf(txData));
try
{
@@ -467,7 +478,7 @@ namespace ZLGUSBCANFD
ZLGCAN.canfd_frame canfdFrame = (ZLGCAN.canfd_frame)Marshal.PtrToStructure(ptrCanFDFrame, typeof(ZLGCAN.canfd_frame));
canfdFrame.flags |= 0x20;
- ZLGCAN.ZCAN_TransmitFD_Data txFdData = new ZLGCAN.ZCAN_TransmitFD_Data { frame = canfdFrame, transmit_type = 0 };
+ ZLGCAN.ZCAN_TransmitFD_Data txFdData = new ZLGCAN.ZCAN_TransmitFD_Data { frame = canfdFrame, transmit_type = 2 };
IntPtr pTxFd = Marshal.AllocHGlobal(Marshal.SizeOf(txFdData));
try
{
@@ -617,7 +628,7 @@ namespace ZLGUSBCANFD
};
Array.Copy(原始数据, 0, fdFrame.data, 0, Math.Min(原始数据.Length, 64));
- ZLGCAN.ZCAN_TransmitFD_Data txFdData = new ZLGCAN.ZCAN_TransmitFD_Data { frame = fdFrame, transmit_type = 0 };
+ ZLGCAN.ZCAN_TransmitFD_Data txFdData = new ZLGCAN.ZCAN_TransmitFD_Data { frame = fdFrame, transmit_type = 2 };
IntPtr pTxFd = Marshal.AllocHGlobal(Marshal.SizeOf(txFdData));
try
{
@@ -637,7 +648,7 @@ namespace ZLGUSBCANFD
};
Array.Copy(原始数据, 0, standardFrame.data, 0, Math.Min(原始数据.Length, 8));
- ZLGCAN.ZCAN_Transmit_Data txData = new ZLGCAN.ZCAN_Transmit_Data { frame = standardFrame, transmit_type = 0 };
+ ZLGCAN.ZCAN_Transmit_Data txData = new ZLGCAN.ZCAN_Transmit_Data { frame = standardFrame, transmit_type = 2 };
IntPtr pTx = Marshal.AllocHGlobal(Marshal.SizeOf(txData));
try
{