using Common.Attributes; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; using System.Text.Json; using TSMaster; namespace CAN驱动 { [BOBCommand] public class 同星驱动类 { public static event Action ConnectEvent; public static event Action DisConnectEvent; public static bool ConnectFlag { get; set; } = false; /// /// 初始化CAN驱动 /// /// /// /// [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)); } } /// /// 释放CAN驱动 /// [Browsable(false)] public static void Release() { TsMasterApi.finalize_lib_tsmaster(); } public static int obj = 0; public static TCANFDQueueEvent_Win32 listener; [Browsable(false)] public static int RegisterListener(TCANFDQueueEvent_Win32 listenEvent) { listener = listenEvent; var re = TsMasterApi.tsapp_register_event_canfd(ref obj, listener); Debug.Assert(re == 0); return re; } [Browsable(false)] public static int UnRegisterListener(TCANFDQueueEvent_Win32 listenEvent = null) { if (listenEvent is not null) { listener = listenEvent; } var re = TsMasterApi.tsapp_unregister_event_canfd(ref obj, listener); Debug.Assert(re == 0); return re; } /// /// 连接 /// /// public static int Connect() { var re = TsMasterApi.tsapp_connect(); if (re == 0) { re = TsMasterApi.tscom_can_rbs_start(); if (re == 0) { ConnectFlag = true; Task.Run(() => ConnectEvent?.Invoke()); } else { Debug.WriteLine($"CAN_RBS启动失败,错误代码:{re}"); } } else { Debug.WriteLine($"CAN连接失败,错误代码:{re}"); return re; } return re; } /// /// 断开 /// /// public static int DisConnect() { var re = TsMasterApi.tsapp_disconnect(); //Debug.Assert(re == 0); if (re == 0) { ConnectFlag = false; Task.Run(() => DisConnectEvent?.Invoke()); } else { Debug.WriteLine($"断开CAN连接失败,错误代码:{re}"); } return re; } /// /// 加载DBC /// /// /// /// /// [Browsable(false)] public static int LoadDBC(string filePath, int[] channel, out uint databaseID) { databaseID = 0; var re = TsMasterApi.tsdb_load_can_db(Path.GetFullPath(filePath), string.Join(",", channel), ref databaseID); foreach (var item in channel) { DBCParse.parse(databaseID, item); DBCParse.rbs_parse(databaseID, item); } return re; } /// /// 卸载DBC /// /// /// [Browsable(false)] public static int UnLoadDBC(uint? databaseID = null) { if (databaseID == null) { return TsMasterApi.tsdb_unload_can_dbs(); } else { return TsMasterApi.tsdb_unload_can_db(databaseID.Value); } } /// /// 开始记录日志 /// /// /// public static int StartLogging(string filePath) { return TsMasterApi.tsapp_start_logging(Path.GetFullPath(filePath)); } /// /// 结束记录日志 /// /// public static int StopLogging() { return TsMasterApi.tsapp_stop_logging(); } /// /// 弹出通道映射窗口 /// /// /// [Browsable(false)] public static int ShowChannelMappingWindow(bool isWait = false) { return TsMasterApi.tsapp_show_tsmaster_window("Hardware", isWait); } /// /// 获取信号值 /// /// /// /// /// public static double GetSignalValue(byte channel, string AMsgName, string ASgnName) { double value = double.NaN; var find = DBCParse.MsgDatabase[channel].First(s => s.msg_name == AMsgName); var re = TsMasterApi.tsdb_get_signal_value_canfd(ref find.ACANFD, AMsgName, ASgnName, ref value); return value; } /// /// 获取信号值 /// /// /// /// /// /// [Browsable(false)] public static int GetSignalValue(byte channel, string AMsgName, string ASgnName, ref double value) { var find = DBCParse.MsgDatabase[channel].First(s => s.msg_name == AMsgName); return TsMasterApi.tsdb_get_signal_value_canfd(ref find.ACANFD, AMsgName, ASgnName, ref value); } /// /// 获取信号值 /// /// /// /// /// /// [Browsable(false)] public static int GetSignalValue(ref TLIBCANFD ACANFD, string AMsgName, string ASgnName, ref double value) { return TsMasterApi.tsdb_get_signal_value_canfd(ref ACANFD, AMsgName, ASgnName, ref value); } /// /// 设置信号值 /// /// /// /// /// /// /// /// /// public static int SetSignalValue(byte channel, string AMsgName, string ASgnName, double AValue, bool isSend = false, float sendPeriod = 0) { var find = DBCParse.MsgDatabase[channel].First(s => s.msg_name == AMsgName); find.ACANFD.FIdxChn = channel; var re = TsMasterApi.tsdb_set_signal_value_canfd(ref find.ACANFD, AMsgName, ASgnName, AValue); Debug.Assert(re == 0); if (re != 0) throw new Exception($"设置报文失败!返回代码{re}"); if (re != 0) return re; if (isSend) { if (sendPeriod == 0) { return TsMasterApi.tsapp_transmit_canfd_async(ref find.ACANFD); } else { return TsMasterApi.tsapp_add_cyclic_msg_canfd(ref find.ACANFD, sendPeriod); } } return 0; } /// /// 设置信号值 /// /// /// /// /// //public static int SetSignalValue(byte channel, string AMsgName, float sendPeriod = 0) //{ // var find = DBCParse.MsgDatabase[channel].First(s => s.msg_name == AMsgName); // find.ACANFD.FIdxChn = channel; // if (sendPeriod == 0) // { // return TsMasterApi.tsapp_transmit_canfd_async(ref find.ACANFD); // } // else // { // return TsMasterApi.tsapp_add_cyclic_msg_canfd(ref find.ACANFD, sendPeriod); // } //} /// /// 设置信号值 /// /// /// /// /// public static int SetSignalValue(APP_CHANNEL channel, string AMsgName, float sendPeriod = 0) { var find = DBCParse.MsgDatabase[(byte)channel].First(s => s.msg_name == AMsgName); find.ACANFD.FIdxChn = (byte)channel; if (sendPeriod == 0) { return TsMasterApi.tsapp_transmit_canfd_async(ref find.ACANFD); } else { return TsMasterApi.tsapp_add_cyclic_msg_canfd(ref find.ACANFD, sendPeriod); } } /// /// 发送自定义报文 /// /// [Browsable(false)] public static int SetMsg(TLIBCANFD msg) { return TsMasterApi.tsapp_transmit_canfd_async(ref msg); } /// /// 设置报文 /// /// 通道 /// DBC数据库ID /// 报文数组 public static void SetMsg(APP_CHANNEL channel, int ID, byte[] bytes) { var find = DBCParse.MsgDatabase[(byte)channel].FirstOrDefault(s => s.ACANFD.FIdentifier == ID); if (find != null) { Array.Copy(bytes, 0, find.ACANFD.FData, 0, Math.Min(bytes.Length, find.ACANFD.FData.Length)); } } /// /// 发送自定义报文 /// /// /// /// /// /// /// /// /// /// /// /// /// public static int SendMsg(APP_CHANNEL AIdxChn, int AID, bool AIsTx, bool AIsExt, bool AIsRemote, byte ADLC, byte[] ADataArray, bool AIsFD = true, bool AIsBRS = false, bool isUpdateDBCDatabase = false, float sendPeriod = 0) { var send = new TLIBCANFD { FIdxChn = (byte)AIdxChn, FProperties = 0, FIdentifier = AID, FDLC = ADLC, FTimeUS = 0uL, FData = new byte[64], FFDProperties = 0, FIsTx = AIsTx, FIsError = false, FIsExt = AIsExt, FIsRemote = AIsRemote, FIsFD = AIsFD, FIsBRS = AIsBRS }; int length = Math.Min(ADataArray.Length, 64); Array.Copy(ADataArray, 0, send.FData, 0, length); int re; if (sendPeriod == 0) { re = TsMasterApi.tsapp_transmit_canfd_async(ref send); } else { re = TsMasterApi.tsapp_add_cyclic_msg_canfd(ref send, sendPeriod); } if (isUpdateDBCDatabase) { var find = DBCParse.MsgDatabase[(byte)AIdxChn].FirstOrDefault(s => s.ACANFD.FIdentifier == send.FIdentifier); if (find != null) { Array.Copy(send.FData, 0, find.ACANFD.FData, 0, Math.Min(ADataArray.Length, find.ACANFD.FData.Length)); } } return re; } /// /// 添加循环发送报文 /// /// /// /// /// public static int AddCyclicMsg(byte channel, string AMsgName, float sendPeriod) { var find = DBCParse.MsgDatabase[channel].First(s => s.msg_name == AMsgName); find.ACANFD.FIdxChn = channel; return TsMasterApi.tsapp_add_cyclic_msg_canfd(ref find.ACANFD, sendPeriod); } /// /// 清除循环发送的报文 /// /// public static int DeleteCyclicMsgs() { return TsMasterApi.tsapp_delete_cyclic_msgs(); } /// /// 获取错误提示 /// /// 错误代码 /// public static string GetErrorDescription(int errorCode) { IntPtr ADesc = IntPtr.Zero; TsMasterApi.tsapp_get_error_description(errorCode, ref ADesc); if (ADesc == IntPtr.Zero) return $"未知错误代码: {errorCode}"; // 假设返回的是 ANSI 字符串(如 C 的 char*) string? description = Marshal.PtrToStringAnsi(ADesc); return description ?? $"未知错误代码: {errorCode}"; } #region CANFD转换相关方法 /// /// CANFD转CAN /// 注意:如果CANFD报文长度超过8字节,转换时会截断数据。 /// /// CANFD消息 /// CAN消息 public static TLIBCAN CANFDToCAN(TLIBCANFD canfdMsg) { TLIBCAN canMsg = new TLIBCAN { FIdxChn = canfdMsg.FIdxChn, FProperties = canfdMsg.FProperties, FIdentifier = canfdMsg.FIdentifier, FData = new byte[8], // CAN标准数据长度 FTimeUS = canfdMsg.FTimeUS, // 时间戳保持不变 FDLC = canfdMsg.FDLC > 8 ? (byte)8 : canfdMsg.FDLC, // DLC限制在8以内 FIsTx = canfdMsg.FIsTx, FIsError = canfdMsg.FIsError, FIsExt = canfdMsg.FIsExt, FIsRemote = canfdMsg.FIsRemote }; // 复制数据,只取前8字节 Array.Copy(canfdMsg.FData, 0, canMsg.FData, 0, Math.Min(8, canfdMsg.FData.Length)); return canMsg; } /// /// CAN转CANFD /// /// CAN消息 /// CANFD消息 public static TLIBCANFD CANToCANFD(TLIBCAN canMsg) { TLIBCANFD canfdMsg = new TLIBCANFD { FIdxChn = canMsg.FIdxChn, FProperties = canMsg.FProperties, // 保留原始属性 FIdentifier = canMsg.FIdentifier, FData = new byte[64], // CANFD最大数据长度 FTimeUS = canMsg.FTimeUS, FDLC = canMsg.FDLC, FFDProperties = 0, // 新的CANFD报文,FD属性初始化为0 FIsTx = canMsg.FIsTx, FIsError = canMsg.FIsError, FIsExt = canMsg.FIsExt, FIsRemote = canMsg.FIsRemote, FIsFD = false, // 从CAN转换,明确设置为非FD FIsBRS = false // 从CAN转换,明确设置为不支持BRS }; // 复制数据 Array.Copy(canMsg.FData, 0, canfdMsg.FData, 0, Math.Min(64, canMsg.FData.Length)); return canfdMsg; } #endregion #region CANFD报文属性获取方法 /// /// 获取CANFD报文内容 /// /// CANFD消息 /// 报文数据数组,长度为FDLC指定的长度 public static byte[] GetCANFDMsgContent(TLIBCANFD canfdMsg) { byte[] content = new byte[Math.Min(canfdMsg.FData.Length, canfdMsg.FDLC)]; Array.Copy(canfdMsg.FData, 0, content, 0, content.Length); return content; } /// /// 获取CANFD报文时间戳 (微秒) /// /// CANFD消息 /// 时间戳 (微秒) public static ulong GetCANFDMsgTimestamp(ref TLIBCANFD canfdMsg) { return canfdMsg.FTimeUS; } /// /// 获取CANFD报文数据长度 (DLC) /// /// CANFD消息 /// 数据长度 (DLC) public static byte GetCANFDMsgDataLength(ref TLIBCANFD canfdMsg) { return canfdMsg.FDLC; } /// /// 获取CANFD报文是否为错误帧 /// /// CANFD消息 /// 是否为错误帧 public static bool GetCANFDMsgIsError(ref TLIBCANFD canfdMsg) { return canfdMsg.FIsError; } /// /// 获取CANFD报文通道 /// /// CANFD消息 /// 通道号 public static byte GetCANFDMsgChannel(ref TLIBCANFD canfdMsg) { return canfdMsg.FIdxChn; } /// /// 获取CANFD报文FD相关属性 (具体含义需参考TSMaster文档) /// /// CANFD消息 /// FD属性 public static uint GetCANFDMsgFDProperties(ref TLIBCANFD canfdMsg) { return canfdMsg.FFDProperties; } /// /// 获取CANFD报文基础属性 (具体含义需参考TSMaster文档) /// /// CANFD消息 /// 基础属性 public static uint GetCANFDMsgProperties(ref TLIBCANFD canfdMsg) { return canfdMsg.FProperties; } /// /// 获取CANFD报文标识符 (ID) /// /// CANFD消息 /// 标识符 (ID) public static uint GetCANFDMsgIdentifier(ref TLIBCANFD canfdMsg) { return (uint)canfdMsg.FIdentifier; } /// /// 获取CANFD报文是否为FD帧 /// /// CANFD消息 /// 是否为FD帧 public static bool GetCANFDMsgIsFD(ref TLIBCANFD canfdMsg) { return canfdMsg.FIsFD; } /// /// 获取CANFD报文是否为远程帧 /// /// CANFD消息 /// 是否为远程帧 public static bool GetCANFDMsgIsRemote(ref TLIBCANFD canfdMsg) { return canfdMsg.FIsRemote; } /// /// 获取CANFD报文是否为扩展帧 /// /// CANFD消息 /// 是否为扩展帧 public static bool GetCANFDMsgIsExt(ref TLIBCANFD canfdMsg) { return canfdMsg.FIsExt; } /// /// 获取CANFD报文是否为BRS (Bit Rate Switch) /// /// CANFD消息 /// 是否为BRS public static bool GetCANFDMsgIsBRS(ref TLIBCANFD canfdMsg) { return canfdMsg.FIsBRS; } /// /// 获取CANFD报文是否为发送帧 /// /// CANFD消息 /// 是否为发送帧 public static bool GetCANFDMsgIsTx(ref TLIBCANFD canfdMsg) { return canfdMsg.FIsTx; } /// /// 获取CANFD报文是否为ESI (Error State Indicator) /// 注意:此API接口可能无法直接从TLIBCANFD结构获取ESI值。 /// ESI通常由总线决定,接收时反映发送节点的错误状态。 /// 当前实现返回FFDProperties的最低位,但这可能不准确。 /// 实际使用中可能需要通过其他方式或API获取。 /// /// CANFD消息 /// 是否为ESI (当前实现仅供参考) public static bool GetCANFDMsgIsESI(ref TLIBCANFD canfdMsg) { // API文档未明确提供直接获取ESI的字段。 // 在CANFD协议中,ESI是报文中的一个位,由发送节点根据自身状态设置。 // TSMaster的TLIBCANFD结构体可能没有直接暴露这个原始位。 // FFDProperties可能包含相关信息,但具体哪一位是ESI需要查阅更详细的文档。 // 目前根据结构体字段推测,这可能不准确。 // 假设ESI信息可能隐含在FFDProperties中,但这种假设通常是错误的。 // 更可能的是,ESI信息在硬件层面处理,或通过其他方式反映。 // 因此,当前返回值可能不准确,需要根据实际API文档确认。 // 这里保留原实现,但加上说明。 return (canfdMsg.FFDProperties & 0x01) != 0; // 警告:此实现可能不正确 } #endregion #region CANFD报文设置方法 /// /// 设置CANFD报文内容 /// /// CANFD消息 /// 要设置的数据 /// 设置结果 (0为成功) public static int SetCANFDMsgContent(ref TLIBCANFD canfdMsg, byte[] data) { if (data == null || data.Length == 0) return -1; // 错误代码 int length = Math.Min(data.Length, canfdMsg.FData.Length); Array.Copy(data, 0, canfdMsg.FData, 0, length); canfdMsg.FDLC = (byte)length; // 同时更新DLC return 0; } /// /// 设置CANFD报文时间戳 (微秒) /// 注意:此时间戳通常由硬件/驱动在接收时设置,发送时设置可能无效或有特殊用途。 /// /// CANFD消息 /// 时间戳 (微秒) /// 设置结果 (0为成功) public static int SetCANFDMsgTimestamp(ref TLIBCANFD canfdMsg, ulong timestamp) { canfdMsg.FTimeUS = timestamp; return 0; } /// /// 设置CANFD报文数据长度 (DLC) /// /// CANFD消息 /// 数据长度 (DLC) /// 设置结果 (0为成功) public static int SetCANFDMsgDataLength(ref TLIBCANFD canfdMsg, byte length) { if (length > canfdMsg.FData.Length) return -1; // 错误代码,长度超出数组大小 canfdMsg.FDLC = length; return 0; } /// /// 设置CANFD报文是否为错误帧 /// /// CANFD消息 /// 是否为错误帧 /// 设置结果 (0为成功) public static int SetCANFDMsgIsError(ref TLIBCANFD canfdMsg, bool isError) { canfdMsg.FIsError = isError; return 0; } /// /// 设置CANFD报文通道 /// /// CANFD消息 /// 通道号 /// 设置结果 (0为成功) public static int SetCANFDMsgChannel(ref TLIBCANFD canfdMsg, byte channel) { canfdMsg.FIdxChn = channel; return 0; } /// /// 设置CANFD报文FD相关属性 /// /// CANFD消息 /// FD属性 /// 设置结果 (0为成功) public static int SetCANFDMsgFDProperties(ref TLIBCANFD canfdMsg, uint fdProperties) { canfdMsg.FFDProperties = (byte)fdProperties; return 0; } /// /// 设置CANFD报文基础属性 /// /// CANFD消息 /// 基础属性 /// 设置结果 (0为成功) public static int SetCANFDMsgProperties(ref TLIBCANFD canfdMsg, uint properties) { canfdMsg.FProperties = (byte)properties; return 0; } /// /// 设置CANFD报文标识符 (ID) /// /// CANFD消息 /// 标识符 (ID) /// 设置结果 (0为成功) public static int SetCANFDMsgIdentifier(ref TLIBCANFD canfdMsg, uint identifier) { canfdMsg.FIdentifier = (int)identifier; return 0; } /// /// 设置CANFD报文是否为FD帧 /// /// CANFD消息 /// 是否为FD帧 /// 设置结果 (0为成功) public static int SetCANFDMsgIsFD(ref TLIBCANFD canfdMsg, bool isFD) { canfdMsg.FIsFD = isFD; return 0; } /// /// 设置CANFD报文是否为远程帧 /// /// CANFD消息 /// 是否为远程帧 /// 设置结果 (0为成功) public static int SetCANFDMsgIsRemote(ref TLIBCANFD canfdMsg, bool isRemote) { canfdMsg.FIsRemote = isRemote; return 0; } /// /// 设置CANFD报文是否为扩展帧 /// /// CANFD消息 /// 是否为扩展帧 /// 设置结果 (0为成功) public static int SetCANFDMsgIsExt(ref TLIBCANFD canfdMsg, bool isExt) { canfdMsg.FIsExt = isExt; return 0; } /// /// 设置CANFD报文是否为BRS (Bit Rate Switch) /// /// CANFD消息 /// 是否为BRS /// 设置结果 (0为成功) public static int SetCANFDMsgIsBRS(ref TLIBCANFD canfdMsg, bool isBRS) { canfdMsg.FIsBRS = isBRS; return 0; } /// /// 设置CANFD报文是否为发送帧 /// /// CANFD消息 /// 是否为发送帧 /// 设置结果 (0为成功) public static int SetCANFDMsgIsTx(ref TLIBCANFD canfdMsg, bool isTx) { canfdMsg.FIsTx = isTx; return 0; } /// /// 设置CANFD报文是否为ESI (Error State Indicator) /// 注意:此API接口可能无法直接设置TLIBCANFD结构中的ESI值。 /// ESI通常由硬件根据发送节点的错误状态自动设置。 /// 当前实现通过操作FFDProperties的最低位来模拟,但这可能无效或不正确。 /// 实际使用中可能无法或不应通过这种方式设置。 /// /// CANFD消息 /// 是否为ESI (当前实现仅供参考,可能无效) /// 设置结果 (0为成功) public static int SetCANFDMsgIsESI(ref TLIBCANFD canfdMsg, bool isESI) { // 使用 byte 类型的掩码进行位操作 byte mask = 0x01; // 最低位 if (isESI) canfdMsg.FFDProperties |= mask; // 设置最低位 else canfdMsg.FFDProperties &= (byte)~mask; // 清除最低位 (注意:~mask 会得到 -2,所以需要强制转换为 byte) return 0; } #endregion /// /// 获取CANFD报文指定字节的指定位的值 (0 或 1) /// /// CANFD消息 /// 字节索引 (0-63 for CANFD) /// 位索引 (0-7) /// 位的值 (0 或 1),如果索引无效则返回 -1 public static int GetCANFDMsgBitValue(ref TLIBCANFD canfdMsg, int byteIndex, int bitIndex) { if (byteIndex < 0 || byteIndex >= canfdMsg.FData.Length || bitIndex < 0 || bitIndex > 7) { Debug.WriteLine($"GetCANFDMsgBitValue: Invalid index - byteIndex: {byteIndex}, bitIndex: {bitIndex}"); return -1; // 或者抛出异常 } byte mask = (byte)(1 << bitIndex); return (canfdMsg.FData[byteIndex] & mask) != 0 ? 1 : 0; } /// /// 设置CANFD报文指定字节的指定位的值 /// /// CANFD消息 /// 字节索引 (0-63 for CANFD) /// 位索引 (0-7) /// 要设置的值 (0 或 1) /// 操作结果 (0为成功, -1为失败) public static int SetCANFDMsgBitValue(ref TLIBCANFD canfdMsg, int byteIndex, int bitIndex, int value) { if (byteIndex < 0 || byteIndex >= canfdMsg.FData.Length || bitIndex < 0 || bitIndex > 7 || (value != 0 && value != 1)) { Debug.WriteLine($"SetCANFDMsgBitValue: Invalid input - byteIndex: {byteIndex}, bitIndex: {bitIndex}, value: {value}"); return -1; // 或者抛出异常 } byte mask = (byte)(1 << bitIndex); if (value == 1) { canfdMsg.FData[byteIndex] |= mask; // 设置该位 } else { canfdMsg.FData[byteIndex] &= (byte)~mask; // 清除该位 } return 0; } /// /// 对CANFD报文指定字节执行按位与(&)操作 /// /// CANFD消息 /// 字节索引 (0-63 for CANFD) /// 要与的掩码值 (byte) /// 操作结果 (0为成功, -1为失败) public static int BitwiseAndCANFDMsgByte(ref TLIBCANFD canfdMsg, int byteIndex, byte mask) { if (byteIndex < 0 || byteIndex >= canfdMsg.FData.Length) { Debug.WriteLine($"BitwiseAndCANFDMsgByte: Invalid byteIndex - {byteIndex}"); return -1; } canfdMsg.FData[byteIndex] &= mask; return 0; } /// /// 对CANFD报文指定字节执行按位或(|)操作 /// /// CANFD消息 /// 字节索引 (0-63 for CANFD) /// 要或的掩码值 (byte) /// 操作结果 (0为成功, -1为失败) public static int BitwiseOrCANFDMsgByte(ref TLIBCANFD canfdMsg, int byteIndex, byte mask) { if (byteIndex < 0 || byteIndex >= canfdMsg.FData.Length) { Debug.WriteLine($"BitwiseOrCANFDMsgByte: Invalid byteIndex - {byteIndex}"); return -1; } canfdMsg.FData[byteIndex] |= mask; return 0; } /// /// 对CANFD报文指定字节执行按位异或(^)操作 /// /// CANFD消息 /// 字节索引 (0-63 for CANFD) /// 要异或的掩码值 (byte) /// 操作结果 (0为成功, -1为失败) public static int BitwiseXorCANFDMsgByte(ref TLIBCANFD canfdMsg, int byteIndex, byte mask) { if (byteIndex < 0 || byteIndex >= canfdMsg.FData.Length) { Debug.WriteLine($"BitwiseXorCANFDMsgByte: Invalid byteIndex - {byteIndex}"); return -1; } canfdMsg.FData[byteIndex] ^= mask; return 0; } #region CAN Message Handling (为CAN添加位操作方法) /// /// 获取CAN报文指定字节的指定位的值 (0 或 1) /// /// CAN消息 /// 字节索引 (0-7 for CAN) /// 位索引 (0-7) /// 位的值 (0 或 1),如果索引无效则返回 -1 public static int GetCANMsgBitValue(ref TLIBCAN canMsg, int byteIndex, int bitIndex) { if (byteIndex < 0 || byteIndex >= canMsg.FData.Length || bitIndex < 0 || bitIndex > 7) { Debug.WriteLine($"GetCANMsgBitValue: Invalid index - byteIndex: {byteIndex}, bitIndex: {bitIndex}"); return -1; } byte mask = (byte)(1 << bitIndex); return (canMsg.FData[byteIndex] & mask) != 0 ? 1 : 0; } /// /// 设置CAN报文指定字节的指定位的值 /// /// CAN消息 /// 字节索引 (0-7 for CAN) /// 位索引 (0-7) /// 要设置的值 (0 或 1) /// 操作结果 (0为成功, -1为失败) public static int SetCANMsgBitValue(ref TLIBCAN canMsg, int byteIndex, int bitIndex, int value) { if (byteIndex < 0 || byteIndex >= canMsg.FData.Length || bitIndex < 0 || bitIndex > 7 || (value != 0 && value != 1)) { Debug.WriteLine($"SetCANMsgBitValue: Invalid input - byteIndex: {byteIndex}, bitIndex: {bitIndex}, value: {value}"); return -1; } byte mask = (byte)(1 << bitIndex); if (value == 1) { canMsg.FData[byteIndex] |= mask; } else { canMsg.FData[byteIndex] &= (byte)~mask; } return 0; } /// /// 对CAN报文指定字节执行按位与(&)操作 /// /// CAN消息 /// 字节索引 (0-7 for CAN) /// 要与的掩码值 (byte) /// 操作结果 (0为成功, -1为失败) public static int BitwiseAndCANMsgByte(ref TLIBCAN canMsg, int byteIndex, byte mask) { if (byteIndex < 0 || byteIndex >= canMsg.FData.Length) { Debug.WriteLine($"BitwiseAndCANMsgByte: Invalid byteIndex - {byteIndex}"); return -1; } canMsg.FData[byteIndex] &= mask; return 0; } /// /// 对CAN报文指定字节执行按位或(|)操作 /// /// CAN消息 /// 字节索引 (0-7 for CAN) /// 要或的掩码值 (byte) /// 操作结果 (0为成功, -1为失败) public static int BitwiseOrCANMsgByte(ref TLIBCAN canMsg, int byteIndex, byte mask) { if (byteIndex < 0 || byteIndex >= canMsg.FData.Length) { Debug.WriteLine($"BitwiseOrCANMsgByte: Invalid byteIndex - {byteIndex}"); return -1; } canMsg.FData[byteIndex] |= mask; return 0; } /// /// 对CAN报文指定字节执行按位异或(^)操作 /// /// CAN消息 /// 字节索引 (0-7 for CAN) /// 要异或的掩码值 (byte) /// 操作结果 (0为成功, -1为失败) public static int BitwiseXorCANMsgByte(ref TLIBCAN canMsg, int byteIndex, byte mask) { if (byteIndex < 0 || byteIndex >= canMsg.FData.Length) { Debug.WriteLine($"BitwiseXorCANMsgByte: Invalid byteIndex - {byteIndex}"); return -1; } canMsg.FData[byteIndex] ^= mask; return 0; } #endregion } }