CAN修复

This commit is contained in:
“hsc”
2026-10-26 10:46:44 +08:00
parent e877dc9a90
commit 9cb139b208
12 changed files with 1462 additions and 167 deletions
@@ -1,9 +1,11 @@
using Prism.Commands;
using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Win32;
using TSMasterCAN;
using UIShare.ViewModelBase;
using XCPCore;
@@ -50,6 +52,52 @@ namespace TSMasterXCPModule.ViewModels
/// <summary>TSMaster 总线是否已连接(tsapp_connect + rbs_start 成功)</summary>
public bool IsBusConnected { get => _isBusConnected; set => SetProperty(ref _isBusConnected, value); }
// ---------- A2L 描述文件 ----------
private string _a2lFilePath = string.Empty;
/// <summary>A2L 文件路径</summary>
public string A2lFilePath { get => _a2lFilePath; set => SetProperty(ref _a2lFilePath, value); }
private string _a2lSummaryText = "未加载 A2L 文件";
/// <summary>A2L 解析结果摘要</summary>
public string A2lSummaryText { get => _a2lSummaryText; set => SetProperty(ref _a2lSummaryText, value); }
/// <summary>解析出的测量量列表(选中后自动填入 DAQ 地址与长度)</summary>
public ObservableCollection<A2lMeasurement> A2lMeasurements { get; } = new ObservableCollection<A2lMeasurement>();
/// <summary>解析出的标定量列表(选中后自动填入内存读写地址与长度)</summary>
public ObservableCollection<A2lCharacteristic> A2lCharacteristics { get; } = new ObservableCollection<A2lCharacteristic>();
private A2lMeasurement? _selectedMeasurement;
/// <summary>当前选中的测量量:自动带入 DAQ 的 ODT 地址与长度</summary>
public A2lMeasurement? SelectedMeasurement
{
get => _selectedMeasurement;
set
{
if (!SetProperty(ref _selectedMeasurement, value) || value == null) return;
OdtAddressText = value.AddressText;
if (value.SizeBytes > 0) OdtLength = value.SizeBytes.ToString();
Log($"A2L 测量量 {value.Name}:地址 {value.AddressText},长度 {value.SizeText}(已填入 DAQ 配置)");
}
}
private A2lCharacteristic? _selectedCharacteristic;
/// <summary>当前选中的标定量:自动带入内存读写的地址与长度</summary>
public A2lCharacteristic? SelectedCharacteristic
{
get => _selectedCharacteristic;
set
{
if (!SetProperty(ref _selectedCharacteristic, value) || value == null) return;
MemAddressText = value.AddressText;
if (value.SizeBytes > 0 && value.SizeBytes <= 200) MemReadLength = value.SizeBytes.ToString();
Log($"A2L 标定量 {value.Name}({value.CharacteristicType}):地址 {value.AddressText},长度 {value.SizeText}(已填入内存读写)");
}
}
// ---------- XCP 连接配置 ----------
private string _canChannel = "0";
@@ -136,6 +184,11 @@ namespace TSMasterXCPModule.ViewModels
#region 命令
/// <summary>浏览并加载 A2L 描述文件</summary>
public DelegateCommand BrowseA2lCommand { get; }
/// <summary>按当前路径重新解析 A2L 描述文件</summary>
public DelegateCommand ReloadA2lCommand { get; }
/// <summary>初始化 TSMaster 驱动(可选加载工程)</summary>
public DelegateCommand InitDriverCommand { get; }
/// <summary>释放 TSMaster 驱动</summary>
@@ -170,6 +223,8 @@ namespace TSMasterXCPModule.ViewModels
/// <summary>创建视图模型</summary>
public TSMasterXCPViewModel(IContainerProvider containerProvider) : base(containerProvider)
{
BrowseA2lCommand = new DelegateCommand(BrowseA2l);
ReloadA2lCommand = new DelegateCommand(ReloadA2l);
InitDriverCommand = new DelegateCommand(() => RunGuarded(InitDriverAsync, "初始化驱动"));
ReleaseDriverCommand = new DelegateCommand(() => RunGuarded(ReleaseDriverAsync, "释放驱动"));
ConnectBusCommand = new DelegateCommand(() => RunGuarded(ConnectBusAsync, "连接总线"));
@@ -192,6 +247,80 @@ namespace TSMasterXCPModule.ViewModels
Log("TSMaster XCP 测试界面就绪。使用顺序:初始化驱动 → 连接总线 → XCP 连接 → 内存读写 / DAQ。");
}
#region 命令处理 —— A2L 描述文件
/// <summary>浏览选择 A2L 文件并解析</summary>
private void BrowseA2l()
{
var dialog = new OpenFileDialog
{
Title = "选择 A2L 描述文件",
Filter = "A2L 描述文件 (*.a2l)|*.a2l|所有文件 (*.*)|*.*",
CheckFileExists = true,
Multiselect = false
};
var currentDir = Path.GetDirectoryName(A2lFilePath);
if (!string.IsNullOrEmpty(currentDir) && Directory.Exists(currentDir))
dialog.InitialDirectory = currentDir;
if (dialog.ShowDialog() != true) return;
LoadA2l(dialog.FileName);
}
/// <summary>按当前路径重新解析 A2L</summary>
private void ReloadA2l()
{
var path = A2lFilePath?.Trim() ?? string.Empty;
if (path.Length == 0)
{
Log("[提示] 请先选择 A2L 文件(点击「浏览...」)。");
return;
}
LoadA2l(path);
}
/// <summary>解析并刷新测量量 / 标定量列表</summary>
private void LoadA2l(string filePath)
{
if (!File.Exists(filePath))
{
A2lSummaryText = "A2L 文件不存在";
Log($"[错误] A2L 文件不存在: {filePath}");
return;
}
try
{
var db = A2lParser.LoadFile(filePath);
A2lFilePath = filePath;
A2lMeasurements.Clear();
foreach (var item in db.Measurements) A2lMeasurements.Add(item);
A2lCharacteristics.Clear();
foreach (var item in db.Characteristics) A2lCharacteristics.Add(item);
SelectedMeasurement = null;
SelectedCharacteristic = null;
A2lSummaryText = $"{db.Summary} · {Path.GetFileName(filePath)}";
Log($"已加载 A2L:{filePath}({db.Summary})");
if (db.Measurements.Count == 0 && db.Characteristics.Count == 0)
Log("[警告] 未解析出可用条目,请确认该文件是 A2L(ASAM MCD-2 MC)描述文件。");
}
catch (Exception ex)
{
A2lMeasurements.Clear();
A2lCharacteristics.Clear();
A2lSummaryText = "A2L 解析失败";
Log($"[错误] 解析 A2L 失败:{ex.Message}");
}
}
#endregion
#region 命令处理 —— TSMaster 总线
private async Task InitDriverAsync()
@@ -122,6 +122,98 @@
</StackPanel>
</GroupBox>
<!-- ============ A2L 描述文件 ============ -->
<GroupBox Header="A2L 描述文件(测量量 / 标定量)" Margin="0,0,0,8"
materialDesign:ColorZoneAssist.Mode="PrimaryLight">
<StackPanel Margin="4">
<StackPanel Orientation="Horizontal" Margin="0,4">
<TextBlock Text="A2L文件" Style="{StaticResource ParamLabel}" />
<TextBox Style="{StaticResource NumInput}" Width="460"
ToolTip="ECU 描述文件(.a2l)。加载后可从下方列表选择测量量/标定量,自动带入地址与长度"
Text="{Binding A2lFilePath, UpdateSourceTrigger=PropertyChanged}" />
<Button Content="浏览..." Command="{Binding BrowseA2lCommand}"
Style="{StaticResource CmdBtn}"
Background="#1565C0" Foreground="White"
ToolTip="选择 A2L 文件并解析" />
<Button Content="重新解析" Command="{Binding ReloadA2lCommand}"
Style="{StaticResource CmdBtn}"
ToolTip="按当前路径重新解析(A2L 被工具重新生成后使用)" />
<TextBlock Text="{Binding A2lSummaryText}"
VerticalAlignment="Center" Margin="12,0,0,0"
FontSize="12" Foreground="#616161"
TextTrimming="CharacterEllipsis" MaxWidth="360" />
</StackPanel>
<Grid Margin="0,6,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="10" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<DockPanel Grid.Column="0">
<TextBlock DockPanel.Dock="Top" Text="测量量 MEASUREMENT → DAQ 地址/长度"
FontSize="12" FontWeight="SemiBold"
Foreground="#1565C0" Margin="2,0,0,4" />
<ListBox Height="180"
ItemsSource="{Binding A2lMeasurements}"
SelectedItem="{Binding SelectedMeasurement}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid ToolTip="{Binding Detail}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Name}" FontSize="12"
TextTrimming="CharacterEllipsis" />
<TextBlock Grid.Column="1" Text="{Binding AddressText}"
FontFamily="Consolas" FontSize="11"
Foreground="#616161" Margin="8,0,0,0" />
<TextBlock Grid.Column="2" Text="{Binding SizeText}"
FontSize="11" Foreground="#9E9E9E"
Margin="8,0,0,0" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DockPanel>
<DockPanel Grid.Column="2">
<TextBlock DockPanel.Dock="Top" Text="标定量 CHARACTERISTIC → 内存读写"
FontSize="12" FontWeight="SemiBold"
Foreground="#1565C0" Margin="2,0,0,4" />
<ListBox Height="180"
ItemsSource="{Binding A2lCharacteristics}"
SelectedItem="{Binding SelectedCharacteristic}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid ToolTip="{Binding Detail}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Name}" FontSize="12"
TextTrimming="CharacterEllipsis" />
<TextBlock Grid.Column="1" Text="{Binding CharacteristicType}"
FontSize="11" Foreground="#9E9E9E"
Margin="8,0,0,0" />
<TextBlock Grid.Column="2" Text="{Binding AddressText}"
FontFamily="Consolas" FontSize="11"
Foreground="#616161" Margin="8,0,0,0" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DockPanel>
</Grid>
</StackPanel>
</GroupBox>
<!-- ============ XCP 连接配置 ============ -->
<GroupBox Header="XCP 连接配置" Margin="0,0,0,8"
materialDesign:ColorZoneAssist.Mode="PrimaryLight">