同星CAN卡驱动
This commit is contained in:
417
CAN驱动/CAN.cs
Normal file
417
CAN驱动/CAN.cs
Normal file
@@ -0,0 +1,417 @@
|
||||
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驱动
|
||||
{
|
||||
[ADPCommand]
|
||||
public class CAN
|
||||
{
|
||||
|
||||
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(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}";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user