BOB/CAN驱动/同星驱动类.cs
2025-12-04 17:11:48 +08:00

1049 lines
38 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
/// <summary>
/// 初始化CAN驱动
/// </summary>
/// <param name="ProjectName"></param>
/// <param name="filePath"></param>
/// <returns></returns>
[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));
}
}
/// <summary>
/// 释放CAN驱动
/// </summary>
[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;
}
/// <summary>
/// 连接
/// </summary>
/// <returns></returns>
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;
}
/// <summary>
/// 断开
/// </summary>
/// <returns></returns>
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;
}
/// <summary>
/// 加载DBC
/// </summary>
/// <param name="filePath"></param>
/// <param name="channel"></param>
/// <param name="databaseID"></param>
/// <returns></returns>
[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;
}
/// <summary>
/// 卸载DBC
/// </summary>
/// <param name="databaseID"></param>
/// <returns></returns>
[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);
}
}
/// <summary>
/// 开始记录日志
/// </summary>
/// <param name="filePath"></param>
/// <returns></returns>
public static int StartLogging(string filePath)
{
return TsMasterApi.tsapp_start_logging(Path.GetFullPath(filePath));
}
/// <summary>
/// 结束记录日志
/// </summary>
/// <returns></returns>
public static int StopLogging()
{
return TsMasterApi.tsapp_stop_logging();
}
/// <summary>
/// 弹出通道映射窗口
/// </summary>
/// <param name="isWait"></param>
/// <returns></returns>
[Browsable(false)]
public static int ShowChannelMappingWindow(bool isWait = false)
{
return TsMasterApi.tsapp_show_tsmaster_window("Hardware", isWait);
}
/// <summary>
/// 获取信号值
/// </summary>
/// <param name="channel"></param>
/// <param name="AMsgName"></param>
/// <param name="ASgnName"></param>
/// <returns></returns>
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;
}
/// <summary>
/// 获取信号值
/// </summary>
/// <param name="channel"></param>
/// <param name="AMsgName"></param>
/// <param name="ASgnName"></param>
/// <param name="value"></param>
/// <returns></returns>
[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);
}
/// <summary>
/// 获取信号值
/// </summary>
/// <param name="ACANFD"></param>
/// <param name="AMsgName"></param>
/// <param name="ASgnName"></param>
/// <param name="value"></param>
/// <returns></returns>
[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);
}
/// <summary>
/// 设置信号值
/// </summary>
/// <param name="channel"></param>
/// <param name="AMsgName"></param>
/// <param name="ASgnName"></param>
/// <param name="AValue"></param>
/// <param name="isSend"></param>
/// <param name="sendPeriod"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
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;
}
/// <summary>
/// 设置信号值
/// </summary>
/// <param name="channel"></param>
/// <param name="AMsgName"></param>
/// <param name="sendPeriod"></param>
/// <returns></returns>
//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);
// }
//}
/// <summary>
/// 设置信号值
/// </summary>
/// <param name="channel"></param>
/// <param name="AMsgName"></param>
/// <param name="sendPeriod"></param>
/// <returns></returns>
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);
}
}
/// <summary>
/// 发送自定义报文
/// </summary>
/// <returns></returns>
[Browsable(false)]
public static int SetMsg(TLIBCANFD msg)
{
return TsMasterApi.tsapp_transmit_canfd_async(ref msg);
}
/// <summary>
/// 设置报文
/// </summary>
/// <param name="channel">通道</param>
/// <param name="ID">DBC数据库ID</param>
/// <param name="bytes">报文数组</param>
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));
}
}
/// <summary>
/// 发送自定义报文
/// </summary>
/// <param name="AIdxChn"></param>
/// <param name="AID"></param>
/// <param name="AIsTx"></param>
/// <param name="AIsExt"></param>
/// <param name="AIsRemote"></param>
/// <param name="ADLC"></param>
/// <param name="ADataArray"></param>
/// <param name="AIsFD"></param>
/// <param name="AIsBRS"></param>
/// <param name="isUpdateDBCDatabase"></param>
/// <param name="sendPeriod"></param>
/// <returns></returns>
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;
}
/// <summary>
/// 添加循环发送报文
/// </summary>
/// <param name="channel"></param>
/// <param name="AMsgName"></param>
/// <param name="sendPeriod"></param>
/// <returns></returns>
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);
}
/// <summary>
/// 清除循环发送的报文
/// </summary>
/// <returns></returns>
public static int DeleteCyclicMsgs()
{
return TsMasterApi.tsapp_delete_cyclic_msgs();
}
/// <summary>
/// 获取错误提示
/// </summary>
/// <param name="errorCode">错误代码</param>
/// <returns></returns>
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转换相关方法
/// <summary>
/// CANFD转CAN
/// 注意如果CANFD报文长度超过8字节转换时会截断数据。
/// </summary>
/// <param name="canfdMsg">CANFD消息</param>
/// <returns>CAN消息</returns>
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;
}
/// <summary>
/// CAN转CANFD
/// </summary>
/// <param name="canMsg">CAN消息</param>
/// <returns>CANFD消息</returns>
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报文属性获取方法
/// <summary>
/// 获取CANFD报文内容
/// </summary>
/// <param name="canfdMsg">CANFD消息</param>
/// <returns>报文数据数组长度为FDLC指定的长度</returns>
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;
}
/// <summary>
/// 获取CANFD报文时间戳 (微秒)
/// </summary>
/// <param name="canfdMsg">CANFD消息</param>
/// <returns>时间戳 (微秒)</returns>
public static ulong GetCANFDMsgTimestamp(ref TLIBCANFD canfdMsg)
{
return canfdMsg.FTimeUS;
}
/// <summary>
/// 获取CANFD报文数据长度 (DLC)
/// </summary>
/// <param name="canfdMsg">CANFD消息</param>
/// <returns>数据长度 (DLC)</returns>
public static byte GetCANFDMsgDataLength(ref TLIBCANFD canfdMsg)
{
return canfdMsg.FDLC;
}
/// <summary>
/// 获取CANFD报文是否为错误帧
/// </summary>
/// <param name="canfdMsg">CANFD消息</param>
/// <returns>是否为错误帧</returns>
public static bool GetCANFDMsgIsError(ref TLIBCANFD canfdMsg)
{
return canfdMsg.FIsError;
}
/// <summary>
/// 获取CANFD报文通道
/// </summary>
/// <param name="canfdMsg">CANFD消息</param>
/// <returns>通道号</returns>
public static byte GetCANFDMsgChannel(ref TLIBCANFD canfdMsg)
{
return canfdMsg.FIdxChn;
}
/// <summary>
/// 获取CANFD报文FD相关属性 (具体含义需参考TSMaster文档)
/// </summary>
/// <param name="canfdMsg">CANFD消息</param>
/// <returns>FD属性</returns>
public static uint GetCANFDMsgFDProperties(ref TLIBCANFD canfdMsg)
{
return canfdMsg.FFDProperties;
}
/// <summary>
/// 获取CANFD报文基础属性 (具体含义需参考TSMaster文档)
/// </summary>
/// <param name="canfdMsg">CANFD消息</param>
/// <returns>基础属性</returns>
public static uint GetCANFDMsgProperties(ref TLIBCANFD canfdMsg)
{
return canfdMsg.FProperties;
}
/// <summary>
/// 获取CANFD报文标识符 (ID)
/// </summary>
/// <param name="canfdMsg">CANFD消息</param>
/// <returns>标识符 (ID)</returns>
public static uint GetCANFDMsgIdentifier(ref TLIBCANFD canfdMsg)
{
return (uint)canfdMsg.FIdentifier;
}
/// <summary>
/// 获取CANFD报文是否为FD帧
/// </summary>
/// <param name="canfdMsg">CANFD消息</param>
/// <returns>是否为FD帧</returns>
public static bool GetCANFDMsgIsFD(ref TLIBCANFD canfdMsg)
{
return canfdMsg.FIsFD;
}
/// <summary>
/// 获取CANFD报文是否为远程帧
/// </summary>
/// <param name="canfdMsg">CANFD消息</param>
/// <returns>是否为远程帧</returns>
public static bool GetCANFDMsgIsRemote(ref TLIBCANFD canfdMsg)
{
return canfdMsg.FIsRemote;
}
/// <summary>
/// 获取CANFD报文是否为扩展帧
/// </summary>
/// <param name="canfdMsg">CANFD消息</param>
/// <returns>是否为扩展帧</returns>
public static bool GetCANFDMsgIsExt(ref TLIBCANFD canfdMsg)
{
return canfdMsg.FIsExt;
}
/// <summary>
/// 获取CANFD报文是否为BRS (Bit Rate Switch)
/// </summary>
/// <param name="canfdMsg">CANFD消息</param>
/// <returns>是否为BRS</returns>
public static bool GetCANFDMsgIsBRS(ref TLIBCANFD canfdMsg)
{
return canfdMsg.FIsBRS;
}
/// <summary>
/// 获取CANFD报文是否为发送帧
/// </summary>
/// <param name="canfdMsg">CANFD消息</param>
/// <returns>是否为发送帧</returns>
public static bool GetCANFDMsgIsTx(ref TLIBCANFD canfdMsg)
{
return canfdMsg.FIsTx;
}
/// <summary>
/// 获取CANFD报文是否为ESI (Error State Indicator)
/// 注意此API接口可能无法直接从TLIBCANFD结构获取ESI值。
/// ESI通常由总线决定接收时反映发送节点的错误状态。
/// 当前实现返回FFDProperties的最低位但这可能不准确。
/// 实际使用中可能需要通过其他方式或API获取。
/// </summary>
/// <param name="canfdMsg">CANFD消息</param>
/// <returns>是否为ESI (当前实现仅供参考)</returns>
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报文设置方法
/// <summary>
/// 设置CANFD报文内容
/// </summary>
/// <param name="canfdMsg">CANFD消息</param>
/// <param name="data">要设置的数据</param>
/// <returns>设置结果 (0为成功)</returns>
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;
}
/// <summary>
/// 设置CANFD报文时间戳 (微秒)
/// 注意:此时间戳通常由硬件/驱动在接收时设置,发送时设置可能无效或有特殊用途。
/// </summary>
/// <param name="canfdMsg">CANFD消息</param>
/// <param name="timestamp">时间戳 (微秒)</param>
/// <returns>设置结果 (0为成功)</returns>
public static int SetCANFDMsgTimestamp(ref TLIBCANFD canfdMsg, ulong timestamp)
{
canfdMsg.FTimeUS = timestamp;
return 0;
}
/// <summary>
/// 设置CANFD报文数据长度 (DLC)
/// </summary>
/// <param name="canfdMsg">CANFD消息</param>
/// <param name="length">数据长度 (DLC)</param>
/// <returns>设置结果 (0为成功)</returns>
public static int SetCANFDMsgDataLength(ref TLIBCANFD canfdMsg, byte length)
{
if (length > canfdMsg.FData.Length)
return -1; // 错误代码,长度超出数组大小
canfdMsg.FDLC = length;
return 0;
}
/// <summary>
/// 设置CANFD报文是否为错误帧
/// </summary>
/// <param name="canfdMsg">CANFD消息</param>
/// <param name="isError">是否为错误帧</param>
/// <returns>设置结果 (0为成功)</returns>
public static int SetCANFDMsgIsError(ref TLIBCANFD canfdMsg, bool isError)
{
canfdMsg.FIsError = isError;
return 0;
}
/// <summary>
/// 设置CANFD报文通道
/// </summary>
/// <param name="canfdMsg">CANFD消息</param>
/// <param name="channel">通道号</param>
/// <returns>设置结果 (0为成功)</returns>
public static int SetCANFDMsgChannel(ref TLIBCANFD canfdMsg, byte channel)
{
canfdMsg.FIdxChn = channel;
return 0;
}
/// <summary>
/// 设置CANFD报文FD相关属性
/// </summary>
/// <param name="canfdMsg">CANFD消息</param>
/// <param name="fdProperties">FD属性</param>
/// <returns>设置结果 (0为成功)</returns>
public static int SetCANFDMsgFDProperties(ref TLIBCANFD canfdMsg, uint fdProperties)
{
canfdMsg.FFDProperties = (byte)fdProperties;
return 0;
}
/// <summary>
/// 设置CANFD报文基础属性
/// </summary>
/// <param name="canfdMsg">CANFD消息</param>
/// <param name="properties">基础属性</param>
/// <returns>设置结果 (0为成功)</returns>
public static int SetCANFDMsgProperties(ref TLIBCANFD canfdMsg, uint properties)
{
canfdMsg.FProperties = (byte)properties;
return 0;
}
/// <summary>
/// 设置CANFD报文标识符 (ID)
/// </summary>
/// <param name="canfdMsg">CANFD消息</param>
/// <param name="identifier">标识符 (ID)</param>
/// <returns>设置结果 (0为成功)</returns>
public static int SetCANFDMsgIdentifier(ref TLIBCANFD canfdMsg, uint identifier)
{
canfdMsg.FIdentifier = (int)identifier;
return 0;
}
/// <summary>
/// 设置CANFD报文是否为FD帧
/// </summary>
/// <param name="canfdMsg">CANFD消息</param>
/// <param name="isFD">是否为FD帧</param>
/// <returns>设置结果 (0为成功)</returns>
public static int SetCANFDMsgIsFD(ref TLIBCANFD canfdMsg, bool isFD)
{
canfdMsg.FIsFD = isFD;
return 0;
}
/// <summary>
/// 设置CANFD报文是否为远程帧
/// </summary>
/// <param name="canfdMsg">CANFD消息</param>
/// <param name="isRemote">是否为远程帧</param>
/// <returns>设置结果 (0为成功)</returns>
public static int SetCANFDMsgIsRemote(ref TLIBCANFD canfdMsg, bool isRemote)
{
canfdMsg.FIsRemote = isRemote;
return 0;
}
/// <summary>
/// 设置CANFD报文是否为扩展帧
/// </summary>
/// <param name="canfdMsg">CANFD消息</param>
/// <param name="isExt">是否为扩展帧</param>
/// <returns>设置结果 (0为成功)</returns>
public static int SetCANFDMsgIsExt(ref TLIBCANFD canfdMsg, bool isExt)
{
canfdMsg.FIsExt = isExt;
return 0;
}
/// <summary>
/// 设置CANFD报文是否为BRS (Bit Rate Switch)
/// </summary>
/// <param name="canfdMsg">CANFD消息</param>
/// <param name="isBRS">是否为BRS</param>
/// <returns>设置结果 (0为成功)</returns>
public static int SetCANFDMsgIsBRS(ref TLIBCANFD canfdMsg, bool isBRS)
{
canfdMsg.FIsBRS = isBRS;
return 0;
}
/// <summary>
/// 设置CANFD报文是否为发送帧
/// </summary>
/// <param name="canfdMsg">CANFD消息</param>
/// <param name="isTx">是否为发送帧</param>
/// <returns>设置结果 (0为成功)</returns>
public static int SetCANFDMsgIsTx(ref TLIBCANFD canfdMsg, bool isTx)
{
canfdMsg.FIsTx = isTx;
return 0;
}
/// <summary>
/// 设置CANFD报文是否为ESI (Error State Indicator)
/// 注意此API接口可能无法直接设置TLIBCANFD结构中的ESI值。
/// ESI通常由硬件根据发送节点的错误状态自动设置。
/// 当前实现通过操作FFDProperties的最低位来模拟但这可能无效或不正确。
/// 实际使用中可能无法或不应通过这种方式设置。
/// </summary>
/// <param name="canfdMsg">CANFD消息</param>
/// <param name="isESI">是否为ESI (当前实现仅供参考,可能无效)</param>
/// <returns>设置结果 (0为成功)</returns>
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
/// <summary>
/// 获取CANFD报文指定字节的指定位的值 (0 或 1)
/// </summary>
/// <param name="canfdMsg">CANFD消息</param>
/// <param name="byteIndex">字节索引 (0-63 for CANFD)</param>
/// <param name="bitIndex">位索引 (0-7)</param>
/// <returns>位的值 (0 或 1),如果索引无效则返回 -1</returns>
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;
}
/// <summary>
/// 设置CANFD报文指定字节的指定位的值
/// </summary>
/// <param name="canfdMsg">CANFD消息</param>
/// <param name="byteIndex">字节索引 (0-63 for CANFD)</param>
/// <param name="bitIndex">位索引 (0-7)</param>
/// <param name="value">要设置的值 (0 或 1)</param>
/// <returns>操作结果 (0为成功, -1为失败)</returns>
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;
}
/// <summary>
/// 对CANFD报文指定字节执行按位与(&)操作
/// </summary>
/// <param name="canfdMsg">CANFD消息</param>
/// <param name="byteIndex">字节索引 (0-63 for CANFD)</param>
/// <param name="mask">要与的掩码值 (byte)</param>
/// <returns>操作结果 (0为成功, -1为失败)</returns>
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;
}
/// <summary>
/// 对CANFD报文指定字节执行按位或(|)操作
/// </summary>
/// <param name="canfdMsg">CANFD消息</param>
/// <param name="byteIndex">字节索引 (0-63 for CANFD)</param>
/// <param name="mask">要或的掩码值 (byte)</param>
/// <returns>操作结果 (0为成功, -1为失败)</returns>
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;
}
/// <summary>
/// 对CANFD报文指定字节执行按位异或(^)操作
/// </summary>
/// <param name="canfdMsg">CANFD消息</param>
/// <param name="byteIndex">字节索引 (0-63 for CANFD)</param>
/// <param name="mask">要异或的掩码值 (byte)</param>
/// <returns>操作结果 (0为成功, -1为失败)</returns>
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添加位操作方法)
/// <summary>
/// 获取CAN报文指定字节的指定位的值 (0 或 1)
/// </summary>
/// <param name="canMsg">CAN消息</param>
/// <param name="byteIndex">字节索引 (0-7 for CAN)</param>
/// <param name="bitIndex">位索引 (0-7)</param>
/// <returns>位的值 (0 或 1),如果索引无效则返回 -1</returns>
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;
}
/// <summary>
/// 设置CAN报文指定字节的指定位的值
/// </summary>
/// <param name="canMsg">CAN消息</param>
/// <param name="byteIndex">字节索引 (0-7 for CAN)</param>
/// <param name="bitIndex">位索引 (0-7)</param>
/// <param name="value">要设置的值 (0 或 1)</param>
/// <returns>操作结果 (0为成功, -1为失败)</returns>
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;
}
/// <summary>
/// 对CAN报文指定字节执行按位与(&)操作
/// </summary>
/// <param name="canMsg">CAN消息</param>
/// <param name="byteIndex">字节索引 (0-7 for CAN)</param>
/// <param name="mask">要与的掩码值 (byte)</param>
/// <returns>操作结果 (0为成功, -1为失败)</returns>
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;
}
/// <summary>
/// 对CAN报文指定字节执行按位或(|)操作
/// </summary>
/// <param name="canMsg">CAN消息</param>
/// <param name="byteIndex">字节索引 (0-7 for CAN)</param>
/// <param name="mask">要或的掩码值 (byte)</param>
/// <returns>操作结果 (0为成功, -1为失败)</returns>
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;
}
/// <summary>
/// 对CAN报文指定字节执行按位异或(^)操作
/// </summary>
/// <param name="canMsg">CAN消息</param>
/// <param name="byteIndex">字节索引 (0-7 for CAN)</param>
/// <param name="mask">要异或的掩码值 (byte)</param>
/// <returns>操作结果 (0为成功, -1为失败)</returns>
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
}
}