From 5a565f7361e46f71b9ed23934848627888370c7f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E2=80=9Chsc=E2=80=9D?= <“huangsucan@kaiyili-lab.com”>
Date: Wed, 5 Aug 2026 11:53:51 +0800
Subject: [PATCH] =?UTF-8?q?Flexray,Lin=E6=B7=BB=E5=8A=A0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
ACP.sln | 12 +
TSMasterFlexRay/FlexRay.cs | 470 ++++++++++++++++++++++++
TSMasterFlexRay/FlexRayDBParse.cs | 248 +++++++++++++
TSMasterFlexRay/Interop.TSMasterAPI.dll | Bin 0 -> 109568 bytes
TSMasterFlexRay/TSMaster.dll | Bin 0 -> 1565184 bytes
TSMasterFlexRay/TSMasterFlexRay.csproj | 19 +
TSMasterLIN/Interop.TSMasterAPI.dll | Bin 0 -> 109568 bytes
TSMasterLIN/LIN.cs | 382 +++++++++++++++++++
TSMasterLIN/TSMaster.dll | Bin 0 -> 1565184 bytes
TSMasterLIN/TSMasterLIN.csproj | 19 +
UIShare/UIShare.csproj | 2 +
11 files changed, 1152 insertions(+)
create mode 100644 TSMasterFlexRay/FlexRay.cs
create mode 100644 TSMasterFlexRay/FlexRayDBParse.cs
create mode 100644 TSMasterFlexRay/Interop.TSMasterAPI.dll
create mode 100644 TSMasterFlexRay/TSMaster.dll
create mode 100644 TSMasterFlexRay/TSMasterFlexRay.csproj
create mode 100644 TSMasterLIN/Interop.TSMasterAPI.dll
create mode 100644 TSMasterLIN/LIN.cs
create mode 100644 TSMasterLIN/TSMaster.dll
create mode 100644 TSMasterLIN/TSMasterLIN.csproj
diff --git a/ACP.sln b/ACP.sln
index 34931f0..cee7287 100644
--- a/ACP.sln
+++ b/ACP.sln
@@ -45,6 +45,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ACP", "ACP\ACP.csproj", "{C
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TSMasterCAN", "TSMasterCAN\TSMasterCAN.csproj", "{B45DC94C-2CBB-4119-8787-B52A9E7EC58B}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TSMasterFlexRay", "TSMasterFlexRay\TSMasterFlexRay.csproj", "{68B228BA-52B4-4C01-B260-235F5444ADA7}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TSMasterLIN", "TSMasterLIN\TSMasterLIN.csproj", "{75F658D1-5DC4-4638-8959-2E7A87212B1D}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -131,6 +135,14 @@ Global
{B45DC94C-2CBB-4119-8787-B52A9E7EC58B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B45DC94C-2CBB-4119-8787-B52A9E7EC58B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B45DC94C-2CBB-4119-8787-B52A9E7EC58B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {68B228BA-52B4-4C01-B260-235F5444ADA7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {68B228BA-52B4-4C01-B260-235F5444ADA7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {68B228BA-52B4-4C01-B260-235F5444ADA7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {68B228BA-52B4-4C01-B260-235F5444ADA7}.Release|Any CPU.Build.0 = Release|Any CPU
+ {75F658D1-5DC4-4638-8959-2E7A87212B1D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {75F658D1-5DC4-4638-8959-2E7A87212B1D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {75F658D1-5DC4-4638-8959-2E7A87212B1D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {75F658D1-5DC4-4638-8959-2E7A87212B1D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/TSMasterFlexRay/FlexRay.cs b/TSMasterFlexRay/FlexRay.cs
new file mode 100644
index 0000000..8d3a6a7
--- /dev/null
+++ b/TSMasterFlexRay/FlexRay.cs
@@ -0,0 +1,470 @@
+
+using Common.Attributes;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Text.Json;
+using TSMaster;
+
+namespace TSMasterFlexRay
+{
+
+ [ACPCommand]
+ public class FlexRay : IDisposable
+ {
+ #region 静态成员
+
+ public static event Action? ConnectEvent;
+ public static event Action? DisConnectEvent;
+ public static bool ConnectFlag { get; set; } = false;
+
+ ///
+ /// 实时接收到的 FlexRay 报文缓存(按 SlotId 索引,保留最新帧)。
+ /// 供界面轮询读取。
+ ///
+ public static ConcurrentDictionary RealTimeMessages { get; } = new();
+
+ #endregion
+
+ #region 实例字段与属性
+
+ /// 设备类型号(TSMaster 中作为配置参考保留)
+ public uint DeviceType { get; }
+ /// 设备索引
+ public uint DeviceIndex { get; }
+ /// 最大通道数
+ public int MaxChannels { get; }
+ /// 工程路径(FlexRay 需通过 TSMaster 工程文件加载 Cluster 配置)
+ public string ProjectPath { get; }
+
+ /// 数据库解析器
+ public FlexRayDBParse DBParser => FlexRayDBParse.Instance;
+
+ ///
+ /// FlexRay 帧解码事件:当接收到帧并通过数据库解码后触发。
+ /// 参数:(通道号, 解码后的报文信息)
+ ///
+ public event Action? OnFrameDecoded;
+
+ private bool _disposed;
+ private bool _isOpened;
+ private TFlexRayQueueEvent_Win32? _instanceListener;
+ private TFlexRayQueueEvent_Win32? _preTxListener;
+
+ #endregion
+
+ #region 构造函数
+
+ /// 默认构造函数(使用默认工程路径)
+ public FlexRay() : this(43, 0, 2, "") { }
+
+ ///
+ /// 带配置参数的构造函数。
+ ///
+ /// 设备类型号
+ /// 设备索引
+ /// 最大通道数
+ /// TSMaster 工程路径(FlexRay 必须加载工程)
+ public FlexRay(uint deviceType, uint deviceIndex, int maxChannels, string projectPath)
+ {
+ DeviceType = deviceType;
+ DeviceIndex = deviceIndex;
+ MaxChannels = maxChannels;
+ ProjectPath = projectPath;
+ }
+
+ #endregion
+
+ #region 实例方法 — 设备管理
+
+ ///
+ /// 打开设备:加载工程 → 连接 → 启动 RBS → 注册监听。
+ /// FlexRay 的硬件配置(波特率、集群参数等)由 TSMaster 工程统一管理,
+ /// 代码中无法直接设置,需通过 ShowChannelMappingWindow 或工程本身配置。
+ ///
+ /// true 表示成功
+ public bool 打开设备()
+ {
+ if (_isOpened) return true;
+ if (ConnectFlag) { _isOpened = true; return true; }
+
+ try
+ {
+ // 1. 通过工程文件初始化(FlexRay 必须依赖工程)
+ var re = Init("TSMasterFlexRay", ProjectPath);
+ if (re != 0)
+ {
+ Debug.WriteLine($"TSMaster FlexRay 工程加载失败,错误代码:{re}");
+ return false;
+ }
+
+ // 2. 使能接收 FIFO(可选,用于批量拉取模式)
+ TsMasterApi.tsfifo_enable_receive_fifo();
+
+ // 3. 连接硬件
+ re = Connect();
+ if (re != 0)
+ {
+ Debug.WriteLine($"FlexRay 连接失败,错误代码:{re}");
+ return false;
+ }
+
+ // 4. 注册接收监听
+ _instanceListener = new TFlexRayQueueEvent_Win32(OnFlexRayReceived);
+ RegisterListener(_instanceListener);
+
+ _isOpened = true;
+ return true;
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine($"打开 FlexRay 设备异常:{ex.Message}");
+ return false;
+ }
+ }
+
+ ///
+ /// 关闭 FlexRay 设备:注销监听 → 停止 RBS → 断开连接。
+ ///
+ public void 关闭FlexRay设备()
+ {
+ if (!_isOpened && !ConnectFlag) return;
+
+ try
+ {
+ if (_preTxListener != null)
+ {
+ UnRegisterPreTxListener(_preTxListener);
+ _preTxListener = null;
+ }
+ if (_instanceListener != null)
+ {
+ UnRegisterListener(_instanceListener);
+ _instanceListener = null;
+ }
+ DisConnect();
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine($"关闭FlexRay设备异常:{ex.Message}");
+ }
+ finally
+ {
+ _isOpened = false;
+ }
+ }
+
+ ///
+ /// FlexRay 接收回调:接收原始帧 → 缓存 → 触发 OnFrameDecoded 事件。
+ ///
+ private void OnFlexRayReceived(ref int AObj, ref TLIBFlexRay AData)
+ {
+ if (_disposed) return;
+
+ // 始终缓存最新帧(按 SlotId)
+ RealTimeMessages[AData.FSlotId] = AData;
+
+ if (OnFrameDecoded == null) return;
+
+ try
+ {
+ var decoded = new FlexRayDBMessage
+ {
+ nSlotId = AData.FSlotId,
+ nCycleNumber = AData.FCycleNumber,
+ nChannelMask = AData.FChannelMask,
+ nDataLength = AData.FActualPayloadLength,
+ Data = new byte[AData.FActualPayloadLength]
+ };
+ Array.Copy(AData.FData, decoded.Data, AData.FActualPayloadLength);
+
+ OnFrameDecoded?.Invoke(AData.FIdxChn, decoded);
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine($"FlexRay 帧解码异常:{ex.Message}");
+ }
+ }
+
+ #endregion
+
+ #region IDisposable
+
+ public void Dispose()
+ {
+ if (_disposed) return;
+ _disposed = true;
+ 关闭FlexRay设备();
+ GC.SuppressFinalize(this);
+ }
+
+ #endregion
+
+ ///
+ /// 初始化 TSMaster FlexRay(必须加载工程文件)
+ ///
+ /// 应用名
+ /// 工程路径,为空则仅初始化库
+ ///
+ [Browsable(false)]
+ public static int Init(string ProjectName, string? filePath = null)
+ {
+ if (string.IsNullOrEmpty(filePath))
+ {
+ return TsMasterApi.initialize_lib_tsmaster(ProjectName);
+ }
+ else
+ {
+ return TsMasterApi.initialize_lib_tsmaster_with_project(ProjectName, Path.GetFullPath(filePath));
+ }
+ }
+
+ ///
+ /// 释放 TSMaster
+ ///
+ [Browsable(false)]
+ public static void Release()
+ {
+ TsMasterApi.finalize_lib_tsmaster();
+ }
+
+ [Browsable(false)]
+ public static int RegisterListener(TFlexRayQueueEvent_Win32 listenEvent)
+ {
+ int obj = 0;
+ var re = TsMasterApi.tsapp_register_event_flexray(ref obj, listenEvent);
+ Debug.Assert(re == 0);
+ return re;
+ }
+
+ [Browsable(false)]
+ public static int UnRegisterListener(TFlexRayQueueEvent_Win32 listenEvent)
+ {
+ int obj = 0;
+ var re = TsMasterApi.tsapp_unregister_event_flexray(ref obj, listenEvent);
+ Debug.Assert(re == 0);
+ return re;
+ }
+
+ ///
+ /// 注册发送前回调(FlexRay 特有,可用于发送前修改帧内容)
+ ///
+ ///
+ ///
+ [Browsable(false)]
+ public static int RegisterPreTxListener(TFlexRayQueueEvent_Win32 preTxEvent)
+ {
+ int obj = 0;
+ return TsMasterApi.tsapp_register_pretx_event_flexray(ref obj, preTxEvent);
+ }
+
+ [Browsable(false)]
+ public static int UnRegisterPreTxListener(TFlexRayQueueEvent_Win32 preTxEvent)
+ {
+ int obj = 0;
+ return TsMasterApi.tsapp_unregister_pretx_event_flexray(ref obj, preTxEvent);
+ }
+
+ ///
+ /// 连接(含 RBS 启动)
+ ///
+ ///
+ public static int Connect()
+ {
+ var re = TsMasterApi.tsapp_connect();
+ if (re == 0)
+ {
+ // FlexRay RBS 需先 enable 再 start
+ TsMasterApi.tscom_flexray_rbs_enable(true);
+ re = TsMasterApi.tscom_flexray_rbs_start();
+ if (re == 0)
+ {
+ ConnectFlag = true;
+ Task.Run(() => ConnectEvent?.Invoke());
+ }
+ else
+ {
+ Debug.WriteLine($"FlexRay RBS 启动失败,错误代码:{re}");
+ }
+ }
+ else
+ {
+ Debug.WriteLine($"FlexRay 连接失败,错误代码:{re}");
+ }
+ return re;
+ }
+
+ ///
+ /// 断开(含 RBS 停止)
+ ///
+ ///
+ public static int DisConnect()
+ {
+ var re = TsMasterApi.tsapp_disconnect();
+ if (re == 0)
+ {
+ TsMasterApi.tscom_flexray_rbs_enable(false);
+ TsMasterApi.tscom_flexray_rbs_stop();
+ ConnectFlag = false;
+ Task.Run(() => DisConnectEvent?.Invoke());
+ }
+ else
+ {
+ Debug.WriteLine($"断开 FlexRay 连接失败,错误代码:{re}");
+ }
+ return re;
+ }
+
+ ///
+ /// 获取工程中 FlexRay 数据库数量
+ ///
+ ///
+ public static int GetDBCount()
+ {
+ int count = 0;
+ TsMasterApi.tsdb_get_flexray_db_count(ref count);
+ return count;
+ }
+
+ ///
+ /// 弹出通道映射窗口(FlexRay 硬件配置推荐通过此窗口完成)
+ ///
+ ///
+ ///
+ [Browsable(false)]
+ public static int ShowChannelMappingWindow(bool isWait = false)
+ {
+ return TsMasterApi.tsapp_show_tsmaster_window("Hardware", isWait);
+ }
+
+ ///
+ /// 发送一帧 FlexRay(异步)
+ ///
+ ///
+ ///
+ [Browsable(false)]
+ public static int SendMsg(TLIBFlexRay msg)
+ {
+ return tsapp_transmit_flexray_async(ref msg);
+ }
+
+ ///
+ /// 发送一帧 FlexRay(按参数构造)
+ ///
+ /// 通道索引(0-based)
+ /// 通道掩码:1=A, 2=B, 3=AB
+ /// 有效负载长度
+ /// 基准循环号
+ /// 时隙号
+ /// 数据数组
+ ///
+ public static int SendMsg(byte AIdxChn, byte AChannelMask, byte ADLC,
+ byte ABaseCycle, ushort ASlotId, byte[] AData)
+ {
+ var send = new TLIBFlexRay(AIdxChn, AChannelMask, ADLC, ABaseCycle, ASlotId, AData);
+ return tsapp_transmit_flexray_async(ref send);
+ }
+
+ ///
+ /// 通过 FIFO 批量拉取已接收的 FlexRay 消息
+ ///
+ /// 缓冲区大小
+ /// 通道号(0-based)
+ /// true=TX, false=RX
+ ///
+ public static TLIBFlexRay[] ReceiveMsgs(ref int bufferSize, byte AChn, bool ATxRx)
+ {
+ TLIBFlexRay[] buffer = new TLIBFlexRay[bufferSize];
+ TsMasterApi.tsfifo_receive_flexray_msgs_list(ref buffer, ref bufferSize, AChn, ATxRx);
+ return buffer;
+ }
+
+ ///
+ /// 通过 RBS 地址获取信号值(地址格式:通道/Cluster/ECU/Frame/Signal)
+ ///
+ ///
+ ///
+ public static double GetSignalValue(string address)
+ {
+ double value = 0;
+ TsMasterApi.tscom_flexray_rbs_get_signal_value_by_address(address, ref value);
+ return value;
+ }
+
+ ///
+ /// 通过 RBS 地址设置信号值
+ ///
+ ///
+ ///
+ ///
+ public static int SetSignalValue(string address, double value)
+ {
+ TsMasterApi.tscom_flexray_rbs_set_signal_value_by_address(address, value);
+ return 0;
+ }
+
+ ///
+ /// 按名称激活 Cluster(RBS 仿真)
+ ///
+ /// 通道索引
+ /// true=激活
+ /// Cluster 名称
+ ///
+ public static int ActivateCluster(int chnIdx, bool enable, string clusterName)
+ {
+ return TsMasterApi.tscom_flexray_rbs_activate_cluster_by_name(chnIdx, enable, clusterName, false);
+ }
+
+ ///
+ /// 按名称激活 ECU(RBS 仿真)
+ ///
+ public static int ActivateECU(int chnIdx, bool enable, string clusterName, string ecuName)
+ {
+ return TsMasterApi.tscom_flexray_rbs_activate_ecu_by_name(chnIdx, enable, clusterName, ecuName, false);
+ }
+
+ ///
+ /// 按名称激活 Frame(RBS 仿真)
+ ///
+ public static int ActivateFrame(int chnIdx, bool enable, string clusterName, string ecuName, string frameName)
+ {
+ return TsMasterApi.tscom_flexray_rbs_activate_frame_by_name(chnIdx, enable, clusterName, ecuName, frameName);
+ }
+
+ ///
+ /// 开始记录日志
+ ///
+ public static int StartLogging(string filePath)
+ {
+ return TsMasterApi.tsapp_start_logging(Path.GetFullPath(filePath));
+ }
+
+ ///
+ /// 结束记录日志
+ ///
+ public static int StopLogging()
+ {
+ return TsMasterApi.tsapp_stop_logging();
+ }
+
+ ///
+ /// 获取错误提示
+ ///
+ public static string GetErrorDescription(int errorCode)
+ {
+ IntPtr ADesc = IntPtr.Zero;
+ TsMasterApi.tsapp_get_error_description(errorCode, ref ADesc);
+ if (ADesc == IntPtr.Zero) return $"未知错误代码: {errorCode}";
+ string? description = Marshal.PtrToStringAnsi(ADesc);
+ return description ?? $"未知错误代码: {errorCode}";
+ }
+
+ // FlexRay 发送函数(TSMaster.dll 中 StdCall 导出,需手动声明)
+ [DllImport(".\\TSMaster.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
+ public static extern int tsapp_transmit_flexray_async(ref TLIBFlexRay AMsg);
+ }
+}
diff --git a/TSMasterFlexRay/FlexRayDBParse.cs b/TSMasterFlexRay/FlexRayDBParse.cs
new file mode 100644
index 0000000..5e4300f
--- /dev/null
+++ b/TSMasterFlexRay/FlexRayDBParse.cs
@@ -0,0 +1,248 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Text.Json.Serialization;
+using TSMaster;
+
+namespace TSMasterFlexRay
+{
+ ///
+ /// FlexRay 网络(Cluster)
+ ///
+ public struct flexray_network
+ {
+ [JsonInclude]
+ public string network_name;
+ [JsonInclude]
+ public flexray_node[] flexray_nodes;
+ }
+
+ ///
+ /// FlexRay 节点(ECU)
+ ///
+ public struct flexray_node
+ {
+ [JsonInclude]
+ public string node_name;
+ [JsonInclude]
+ public flexray_message[] tx_flexray_Messages;
+ [JsonInclude]
+ public flexray_message[] rx_flexray_Messages;
+ }
+
+ ///
+ /// FlexRay 帧(Frame)
+ ///
+ public struct flexray_message
+ {
+ [JsonInclude]
+ public string message_name;
+ [JsonInclude]
+ public int slot_id;
+ [JsonInclude]
+ public int channel_mask;
+ [JsonInclude]
+ public int base_cycle;
+ [JsonInclude]
+ public int rep_cycle;
+ [JsonInclude]
+ public bool is_startup_frame;
+ [JsonInclude]
+ public int dlc;
+ [JsonInclude]
+ public string[] signals;
+ }
+
+ ///
+ /// FlexRay 解码后的信号信息
+ ///
+ public struct FlexRaySignal
+ {
+ /// 信号名称
+ public string name;
+ /// 起始位
+ public int start_bit;
+ /// 长度(bit)
+ public int length;
+ /// 因子
+ public double factor;
+ /// 偏移
+ public double offset;
+ /// 初始值
+ public double init_value;
+ /// 信号类型
+ public TSignalType signal_type;
+ /// 字节序(true=小端)
+ public bool is_intel;
+ }
+
+ ///
+ /// FlexRay 解码后的报文信息
+ ///
+ public class FlexRayDBMessage
+ {
+ /// 时隙号
+ public int nSlotId;
+ /// 周期号
+ public int nCycleNumber;
+ /// 通道掩码
+ public int nChannelMask;
+ /// 有效负载长度
+ public int nDataLength;
+ /// 数据
+ public byte[] Data = Array.Empty();
+ }
+
+ public class FlexRayDBParse
+ {
+ private static FlexRayDBParse? _instance;
+ /// 单例实例
+ public static FlexRayDBParse Instance => _instance ??= new FlexRayDBParse();
+
+ /// 最大通道数(等于 MsgDatabase 的维度)
+ public int MaxChannels => MsgDatabase.Count;
+
+ ///
+ /// FlexRay 报文数据库(按通道索引,每个通道包含该通道上所有帧)。
+ ///
+ public static List> MsgDatabase { get; set; } =
+ [.. Enumerable.Range(0, 12).Select(_ => new List())];
+
+ /// FlexRay 网络拓扑(Cluster/ECU/Frame/Signal)
+ public static flexray_network Network;
+
+ ///
+ /// 解析指定索引的 FlexRay 数据库,填充 MsgDatabase 和 Network。
+ /// FlexRay 数据库由工程加载,通过 tsdb_get_flexray_db_count 获取数量。
+ ///
+ /// 数据库索引(0-based)
+ /// 映射的通道号
+ public static void parse(int dbIndex, int channel)
+ {
+ int ASignalCount = 0;
+ int AFrameCount = 0;
+ int AECUcount = 0;
+ long ASupportMask = 0;
+ long AFlags = 0;
+ IntPtr temp1 = IntPtr.Zero;
+ IntPtr temp2 = IntPtr.Zero;
+
+ // 1. 获取 Cluster 属性
+ int ret = TsMasterApi.tsdb_get_flexray_db_properties_by_index_verbose(
+ dbIndex, ref ASignalCount, ref AFrameCount, ref AECUcount,
+ ref ASupportMask, ref AFlags, ref temp1, ref temp2);
+
+ string clusterName = Marshal.PtrToStringAnsi(temp1) ?? "";
+ Network = new flexray_network
+ {
+ network_name = clusterName,
+ flexray_nodes = new flexray_node[AECUcount]
+ };
+
+ // 2. 遍历所有 ECU
+ for (int i = 0; i < AECUcount; i++)
+ {
+ int ATXFramecount = 0;
+ int ARXFramecount = 0;
+
+ TsMasterApi.tsdb_get_flexray_ecu_properties_by_index_verbose(
+ dbIndex, i, ref ATXFramecount, ref ARXFramecount, ref temp1, ref temp2);
+
+ string ecuName = Marshal.PtrToStringAnsi(temp1) ?? "";
+ Network.flexray_nodes[i].node_name = ecuName;
+ Network.flexray_nodes[i].tx_flexray_Messages = new flexray_message[ATXFramecount];
+ Network.flexray_nodes[i].rx_flexray_Messages = new flexray_message[ARXFramecount];
+
+ // TX Frame
+ for (int tx = 0; tx < ATXFramecount; tx++)
+ {
+ var msg = ParseFrame(dbIndex, i, tx, true);
+ Network.flexray_nodes[i].tx_flexray_Messages[tx] = msg;
+ MsgDatabase[channel].Add(msg);
+ }
+
+ // RX Frame
+ for (int rx = 0; rx < ARXFramecount; rx++)
+ {
+ var msg = ParseFrame(dbIndex, i, rx, false);
+ Network.flexray_nodes[i].rx_flexray_Messages[rx] = msg;
+ }
+ }
+
+ MsgDatabase[channel].Sort((a, b) => a.slot_id.CompareTo(b.slot_id));
+ }
+
+ ///
+ /// 解析单帧属性(TX 或 RX)
+ ///
+ private static flexray_message ParseFrame(int dbIndex, int ecuIndex, int frameIndex, bool isTx)
+ {
+ int AFRChannelMask = 0;
+ int AFRBaseCycle = 0;
+ int ARepCycle = 0;
+ bool isStartupFrame = false;
+ int ASlotID = 0;
+ long CycleMask = 0;
+ int AFRSignalCount = 0;
+ int AFRDLC = 0;
+ IntPtr temp1 = IntPtr.Zero;
+ IntPtr temp2 = IntPtr.Zero;
+
+ TsMasterApi.tsdb_get_flexray_frame_properties_by_index_verbose(
+ dbIndex, ecuIndex, frameIndex, isTx,
+ ref AFRChannelMask, ref AFRBaseCycle, ref ARepCycle, ref isStartupFrame,
+ ref ASlotID, ref CycleMask, ref AFRSignalCount, ref AFRDLC,
+ ref temp1, ref temp2);
+
+ string frameName = Marshal.PtrToStringAnsi(temp1) ?? "";
+ var msg = new flexray_message
+ {
+ message_name = frameName,
+ slot_id = ASlotID,
+ channel_mask = AFRChannelMask,
+ base_cycle = AFRBaseCycle,
+ rep_cycle = ARepCycle,
+ is_startup_frame = isStartupFrame,
+ dlc = AFRDLC,
+ signals = new string[AFRSignalCount]
+ };
+
+ // 遍历信号
+ for (int s = 0; s < AFRSignalCount; s++)
+ {
+ TSignalType Asignaltype = (TSignalType)0;
+ TFlexRayCompuMethod ACompuMethod = (TFlexRayCompuMethod)0;
+ bool AIsIntel = false;
+ int AStartBit = 0;
+ int AUpdateBit = 0;
+ int ALength = 0;
+ double AFactor = 0;
+ double AOffset = 0;
+ double AInitValue = 0;
+
+ TsMasterApi.tsdb_get_flexray_signal_properties_by_index_verbose(
+ dbIndex, ecuIndex, frameIndex, s, isTx,
+ ref Asignaltype, ref ACompuMethod, ref AIsIntel,
+ ref AStartBit, ref AUpdateBit, ref ALength,
+ ref AFactor, ref AOffset, ref AInitValue,
+ ref temp1, ref temp2);
+
+ string sigName = Marshal.PtrToStringAnsi(temp1) ?? "";
+ msg.signals[s] = sigName;
+ }
+
+ return msg;
+ }
+
+ ///
+ /// 解析网络拓扑(仅填充 Network,不写入 MsgDatabase)
+ ///
+ public static void rbs_parse(int dbIndex, int channel)
+ {
+ // parse 已同时填充 Network 和 MsgDatabase,此处保持与 CAN 一致的接口
+ parse(dbIndex, channel);
+ }
+ }
+}
diff --git a/TSMasterFlexRay/Interop.TSMasterAPI.dll b/TSMasterFlexRay/Interop.TSMasterAPI.dll
new file mode 100644
index 0000000000000000000000000000000000000000..1d1400bc80851b24ccb6ebe2697231a1928b5fcf
GIT binary patch
literal 109568
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
UNS|{RoT&*3{qN8J&syOB1sqgf?EnA(
literal 0
HcmV?d00001
diff --git a/TSMasterFlexRay/TSMaster.dll b/TSMasterFlexRay/TSMaster.dll
new file mode 100644
index 0000000000000000000000000000000000000000..a34dd331f941d9f2cff9f137db3b9489357b474f
GIT binary patch
literal 1565184
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
a%VEK0b-cn?3yo0X;V^^#!E$MPBx
zcf@$+jqHyQ1)(ubds&NQJ@0xC)rX#>sUkSs!#lx>a50HtCmuVKNrzy+4np!hJn&D`
znS2iqREtC{5+vUXc{8{2do#bA5Hm!*I=VUQc)77U>G_6yZ>{vOoUI&=7aO-ndAZ0C
z@Z$LaUM`lebCvJ^9Y0S=!~9mkPhAKF{TR>8BGHvBcRO(*lfxlWMx5zKPxoHE1l<7r=BK7d{vG#f@Jto#h!PjM?JeT5XuA9D;
zhpY%a+$qZQ>qVfQYqU-Z19>D>E&}M5n#+4dxuc#(dF|wfiFyksQ{_BBQN)aJ3TEn!
z+437;ZwG1BW+8p0BHzyPMVOydp2|01sjo86A2q50ba>m^n(ms7sF)T*Ua2`To2UZ)
ztVO=n!8I^Fxs@c!g_UM?1X?#RH2Q2rm2JG8;xXy%uokH?nm`^7WK1Tjr131o6$<*K
zDi2_}h&cGesC)yjo0Z~{i@#w$up-Y2|N0tEwkYEqm8^E!bs)57M1Kl-f9dEmRV;X9
z%_ob3BNf9W7Bnjl?Rk`Uq?A))&1DP{fkcNyKMJTHuyGO1C{QqsCh!^^$*b3)QUbl2d%B$dzdu$rSBgrBx(f)L4#0>KIfgNxO^n9jvh@qPx6@^22d2iw*MTe5`+
z8im;+1&u-k3_i?<#UMF<@ggHmSg_wHbSx%Y2|>c3htET!EN`(M0Be=X`1~>z>9MZZ
zie?t&FBY>BDEU+~>e(05l(I^XX4cAEjG#;?k}NFGUo6Zi=%le8#zzBT?qXkCTPv!G
zkW{0@v6zQ#XF=&$+_-kt+SUz-FYL&|E*^Gmm5yZ=+82{bOO2h;ntd?^$!6JR<}aow
z*s~PoEv6vk3JmGeOy=j(z+5*Sq1~A!dL=3nf@@HL5#yn=BZ_Q`y=(8XN+
z5kcn88$GNjC%=Iv*u0f%TbQ;RkKAp%EI+)8k33Rb@^izhC}z4iyo#IsbS9Y>UNvWR
zYg5<}UZr=`jzlnwY<38OY&|jo8B3@(&;@irq?Q;dC