其他程序的CAN CANFD LIN的移植

This commit is contained in:
2025-09-07 22:08:21 +08:00
parent 566a3d2ca6
commit e2e28935d1
55 changed files with 9087 additions and 677 deletions

View File

@@ -1,4 +1,5 @@
using System;
using CapMachine.Wpf.Dtos;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -31,5 +32,17 @@ namespace CapMachine.Wpf.CanDrive
/// 没有的话,则给默认值
/// </summary>
public double SignalCmdValue { get; set; }
///// <summary>
///// 逻辑规则Id
///// </summary>
//public long LogicRuleId { get; set; }
/// <summary>
/// CanLinConfig的逻辑转换规则
/// 比如速度下发的数据SV是4000但是下发到CAN的值是40可能是其他的逻辑转换规则这里就是保存其中的逻辑规则
/// </summary>
public LogicRuleDto? LogicRuleDto { get; set; }
}
}

View File

@@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace CapMachine.Wpf.CanDrive.CanFD
{
/// <summary>
/// 和DBCParser一样但用于处理USB设备的DBC文件解析。
/// DBCParserByFD类用于处理USB设备的DBC文件解析。
/// </summary>
public class DBCParserByFD
{
public const Int32 DBC_PARSER_OK = 0;//没有错误
public const Int32 DBC_PARSER_FILE_OPEN = (-1);//打开文件出错
public const Int32 DBC_PARSER_FILE_FORMAT = (-2);//文件格式错误
public const Int32 DBC_PARSER_DEV_DISCONNECT = (-3);//设备未连接
public const Int32 DBC_PARSER_HANDLE_ERROR = (-4);//LDF Handle错误
public const Int32 DBC_PARSER_GET_INFO_ERROR = (-5);//获取解析后的数据出错
public const Int32 DBC_PARSER_DATA_ERROR = (-6);//数据处理错误
public const Int32 DBC_PARSER_SLAVE_NACK = (-7);//从机未响应数据
[DllImport("USB2XXX.dll")]
public static extern UInt64 DBC_ParserFile(int DevHandle, StringBuilder pDBCFileName);
[DllImport("USB2XXX.dll")]
public static extern Int32 DBC_GetMsgQuantity(UInt64 DBCHandle);
[DllImport("USB2XXX.dll")]
public static extern Int32 DBC_GetMsgName(UInt64 DBCHandle, int index, StringBuilder pMsgName);
[DllImport("USB2XXX.dll")]
public static extern Int32 DBC_GetMsgSignalQuantity(UInt64 DBCHandle, StringBuilder pMsgName);
[DllImport("USB2XXX.dll")]
public static extern Int32 DBC_GetMsgSignalName(UInt64 DBCHandle, StringBuilder pMsgName, int index, StringBuilder pSignalName);
[DllImport("USB2XXX.dll")]
public static extern Int32 DBC_GetMsgPublisher(UInt64 DBCHandle, StringBuilder pMsgName, StringBuilder pPublisher);
//设置信号值
[DllImport("USB2XXX.dll")]
public static extern Int32 DBC_SetSignalValue(UInt64 DBCHandle, StringBuilder pMsgName, StringBuilder pSignalName, double Value);
//获取信号值
[DllImport("USB2XXX.dll")]
public static extern Int32 DBC_GetSignalValue(UInt64 DBCHandle, StringBuilder pMsgName, StringBuilder pSignalName, double[] pValue);
[DllImport("USB2XXX.dll")]
public static extern Int32 DBC_GetSignalValueStr(UInt64 DBCHandle, StringBuilder pMsgName, StringBuilder pSignalName, StringBuilder pValueStr);
//将CAN消息数据填充到信号里面
[DllImport("USB2XXX.dll")]
public static extern Int32 DBC_SyncCANMsgToValue(UInt64 DBCHandle, IntPtr pCANMsg, int MsgLen);
[DllImport("USB2XXX.dll")]
public static extern Int32 DBC_SyncCANFDMsgToValue(UInt64 DBCHandle, IntPtr pCANFDMsg, int MsgLen);
//将信号数据填充到CAN消息里面
[DllImport("USB2XXX.dll")]
public static extern Int32 DBC_SyncValueToCANMsg(UInt64 DBCHandle, StringBuilder pMsgName, IntPtr pCANMsg);
[DllImport("USB2XXX.dll")]
public static extern Int32 DBC_SyncValueToCANFDMsg(UInt64 DBCHandle, StringBuilder pMsgName, IntPtr pCANFDMsg);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -119,16 +119,24 @@ namespace CapMachine.Wpf.CanDrive
[DllImport("USB2XXX.dll")]
public static extern Int32 CANFD_Init(Int32 DevHandle, Byte CANIndex, ref CANFD_INIT_CONFIG pCanConfig);
[DllImport("USB2XXX.dll")]
public static extern Int32 CANFD_Init2(Int32 DevHandle, Byte CANIndex, Int32 BaudRateNBTBps, Int32 BaudRateDBTBps, Byte EnResistor, Byte ISOCRCEnable);
[DllImport("USB2XXX.dll")]
public static extern Int32 CANFD_StartGetMsg(Int32 DevHandle, Byte CANIndex);
[DllImport("USB2XXX.dll")]
public static extern Int32 CANFD_StopGetMsg(Int32 DevHandle, Byte CANIndex);
[DllImport("USB2XXX.dll")]
public static extern Int32 CANFD_SendMsg(Int32 DevHandle, Byte CANIndex, CANFD_MSG[] pCanSendMsg, Int32 SendMsgNum);
[DllImport("USB2XXX.dll")]
public static extern Int32 CANFD_SendMsgWithTime(Int32 DevHandle, Byte CANIndex, CANFD_MSG[] pCanSendMsg, Int32 SendMsgNum);
[DllImport("USB2XXX.dll")]
public static extern Int32 CANFD_GetMsg(Int32 DevHandle, Byte CANIndex, IntPtr pCanGetMsg, Int32 BufferSize);
[DllImport("USB2XXX.dll")]
public static extern Int32 CANFD_ClearMsg(Int32 DevHandle, Byte CANIndex);
[DllImport("USB2XXX.dll")]
public static extern Int32 CANFD_SetFilter(Int32 DevHandle, Byte CANIndex, ref CANFD_FILTER_CONFIG pCanFilter, Byte Len);
[DllImport("USB2XXX.dll")]
public static extern Int32 CANFD_FilterList_Init(Int32 DevHandle, Byte CANIndex, UInt32[] pIDList, Byte IDListLen);
[DllImport("USB2XXX.dll")]
public static extern Int32 CANFD_GetDiagnostic(Int32 DevHandle, Byte CANIndex, ref CANFD_DIAGNOSTIC pCanDiagnostic);
[DllImport("USB2XXX.dll")]
public static extern Int32 CANFD_GetBusError(Int32 DevHandle, Byte CANIndex, ref CANFD_BUS_ERROR pCanBusError);
@@ -139,7 +147,13 @@ namespace CapMachine.Wpf.CanDrive
[DllImport("USB2XXX.dll")]
public static extern Int32 CANFD_StartSchedule(Int32 DevHandle, Byte CANIndex, Byte MsgTabIndex, Byte TimePrecMs, Byte OrderSend);
[DllImport("USB2XXX.dll")]
public static extern Int32 CANFD_UpdateSchedule(Int32 DevHandle, Byte CANIndex, Byte MsgTabIndex, Byte MsgIndex, CANFD_MSG[] pCanMsg, Byte MsgNum);
[DllImport("USB2XXX.dll")]
public static extern Int32 CANFD_StopSchedule(Int32 DevHandle, Byte CANIndex);
[DllImport("USB2XXX.dll")]
public static extern Int64 CANFD_GetStartTime(Int32 DevHandle, Byte CANIndex);
[DllImport("USB2XXX.dll")]
public static extern Int32 CANFD_ResetStartTime(Int32 DevHandle, Byte CANIndex);
[DllImport("USB2XXX.dll")]
public static extern Int32 CANFD_SetRelay(Int32 DevHandle, Byte RelayState);

View File

@@ -0,0 +1,143 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace CapMachine.Wpf.CanDrive.CanFD
{
/// <summary>
/// 和USB_DEVICE一样但用于处理USB设备的CAN FD协议。
/// </summary>
public class USB_DEVICEByFD
{
//定义电压输出值
public const Byte POWER_LEVEL_NONE = 0; //不输出
public const Byte POWER_LEVEL_1V8 = 1; //输出1.8V
public const Byte POWER_LEVEL_2V5 = 2; //输出2.5V
public const Byte POWER_LEVEL_3V3 = 3; //输出3.3V
public const Byte POWER_LEVEL_5V0 = 4; //输出5.0V
//设备信息定义
public struct DEVICE_INFO
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public Byte[] FirmwareName; //固件名称字符串
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public Byte[] BuildDate; //固件编译时间字符串
public UInt32 HardwareVersion;//硬件版本号
public UInt32 FirmwareVersion;//固件版本号
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public UInt32[] SerialNumber; //适配器序列号
public UInt32 Functions; //适配器当前具备的功能
}
//方法定义
/**
* @brief 初始化USB设备并扫描设备连接数必须调用
* @param pDevHandle 每个设备的设备号存储地址
* @retval 扫描到的设备数量
*/
[DllImport("USB2XXX.dll")]
public static extern Int32 USB_ScanDevice(Int32[] pDevHandle);
/**
* @brief 打开设备,必须调用
* @param DevHandle 设备索引号
* @retval 打开设备的状态
*/
[DllImport("USB2XXX.dll")]
public static extern bool USB_OpenDevice(Int32 DevHandle);
/**
* @brief 关闭设备
* @param DevHandle 设备索引号
* @retval 关闭设备的状态
*/
[DllImport("USB2XXX.dll")]
public static extern bool USB_CloseDevice(Int32 DevHandle);
/**
* @brief 复位设备程序复位后需要重新调用USB_ScanDeviceUSB_OpenDevice函数
* @param DevHandle 设备索引号
* @retval 复位设备的状态
*/
[DllImport("USB2XXX.dll")]
public static extern bool USB_ResetDevice(Int32 DevHandle);
/**
* @brief 检测到USB断开连接后重新连接设备
* @param DevHandle 设备号
* @retval 重连状态
*/
[DllImport("USB2XXX.dll")]
public static extern bool USB_RetryConnect(Int32 DevHandle);
/**
* @brief 获取设备信息,比如设备名称,固件版本号,设备序号,设备功能说明字符串等
* @param DevHandle 设备索引号
* @param pDevInfo 设备信息存储结构体指针
* @param pFunctionStr 设备功能说明字符串
* @retval 获取设备信息的状态
*/
[DllImport("USB2XXX.dll")]
public static extern bool DEV_GetDeviceInfo(Int32 DevHandle, ref DEVICE_INFO pDevInfo, StringBuilder pFunctionStr);
/**
* @brief 擦出用户区数据
* @param DevHandle 设备索引号
* @retval 用户区数据擦出状态
*/
[DllImport("USB2XXX.dll")]
public static extern bool DEV_EraseUserData(Int32 DevHandle);
/**
* @brief 向用户区域写入用户自定义数据,写入数据之前需要调用擦出函数将数据擦出
* @param DevHandle 设备索引号
* @param OffsetAddr 数据写入偏移地址起始地址为0x00用户区总容量为0x10000字节也就是64KBye
* @param pWriteData 用户数据缓冲区首地址
* @param DataLen 待写入的数据字节数
* @retval 写入用户自定义数据状态
*/
[DllImport("USB2XXX.dll")]
public static extern bool DEV_WriteUserData(Int32 DevHandle, Int32 OffsetAddr, byte[] pWriteData, Int32 DataLen);
/**
* @brief 从用户自定义数据区读出数据
* @param DevHandle 设备索引号
* @param OffsetAddr 数据写入偏移地址起始地址为0x00用户区总容量为0x10000字节也就是64KBye
* @param pReadData 用户数据缓冲区首地址
* @param DataLen 待读出的数据字节数
* @retval 读出用户自定义数据的状态
*/
[DllImport("USB2XXX.dll")]
public static extern bool DEV_ReadUserData(Int32 DevHandle, Int32 OffsetAddr, byte[] pReadData, Int32 DataLen);
/**
* @brief 设置可变电压输出引脚输出电压值
* @param DevHandle 设备索引号
* @param PowerLevel 输出电压值
* @retval 设置输出电压状态
*/
[DllImport("USB2XXX.dll")]
public static extern bool DEV_SetPowerLevel(Int32 DevHandle, byte PowerLevel);
/**
* @brief 或者CAN或者LIN的时间戳原始值
* @param DevHandle 设备索引号
* @param pTimestamp 时间戳指针
* @retval 获取时间戳状态
*/
[DllImport("USB2XXX.dll")]
public static extern bool DEV_GetTimestamp(Int32 DevHandle, byte BusType, Int32[] pTimestamp);
/**
* @brief 复位CAN/LIN时间戳需要在初始化CAN/LIN之后调用
* @param DevHandle 设备索引号
* @retval 复位时间戳状态
*/
[DllImport("USB2XXX.dll")]
public static extern bool DEV_ResetTimestamp(Int32 DevHandle);
/**
* @brief 获取dll编译日期
* @param pDateTime 输出DLL编译日期字符串
* @retval 获取dll编译日期字符串
*/
[DllImport("USB2XXX.dll")]
public static extern bool DEV_GetDllBuildTime(StringBuilder pDateTime);
}
}

View File

@@ -1,6 +1,11 @@
using CapMachine.Wpf.Models.Tag;
using CapMachine.Core;
using CapMachine.Model.CANLIN;
using CapMachine.Wpf.Dtos;
using CapMachine.Wpf.Models.Tag;
using CapMachine.Wpf.Services;
using HslCommunication;
using ImTools;
using NLog;
using NPOI.OpenXmlFormats.Wordprocessing;
using Prism.Ioc;
using Prism.Mvvm;
@@ -33,6 +38,7 @@ namespace CapMachine.Wpf.CanDrive
{
ContainerProvider = containerProvider;
HighSpeedDataService = ContainerProvider.Resolve<HighSpeedDataService>();
LoggerService = ContainerProvider.Resolve<ILogService>();
//Stopwatch.Frequency表示高精度计时器每秒的计数次数ticks/秒每毫秒的ticks数 = 每秒的ticks数 ÷ 1000
TicksPerMs = Stopwatch.Frequency / 1000.0;
@@ -57,6 +63,11 @@ namespace CapMachine.Wpf.CanDrive
/// </summary>
public HighSpeedDataService HighSpeedDataService { get; set; }
/// <summary>
/// Logger 实例
/// </summary>
public ILogService LoggerService { get; set; }
/// <summary>
/// 开始Dbc文件写入
/// </summary>
@@ -123,6 +134,7 @@ namespace CapMachine.Wpf.CanDrive
///BufferSize 存储CAN消息缓冲区大小。
///返回值:
//大于等于0表示从CAN适配器内部成功读取到的CAN消息帧数若返回值小于0则说明调用该函数失败。
/// 目前是WriteCANIndex和ReadCANIndex需要相同
/// </summary>
public Byte WriteCANIndex { get; set; } = 0;
@@ -353,19 +365,19 @@ namespace CapMachine.Wpf.CanDrive
{
StringBuilder MsgName = new StringBuilder(32);
CAN_DBCParser.DBC_GetMsgName(DBCHandle, i, MsgName);
//Console.WriteLine("Msg.Name = {0}", MsgName);
Console.WriteLine("Msg.Name = {0}", MsgName);
int DBCSigNum = CAN_DBCParser.DBC_GetMsgSignalQuantity(DBCHandle, MsgName);
StringBuilder Publisher = new StringBuilder(32);
CAN_DBCParser.DBC_GetMsgPublisher(DBCHandle, MsgName, Publisher);
long MsgId;
MsgId = CAN_DBCParser.DBC_GetMsgIDByName(DBCHandle, MsgName);
//Console.Write("Signals:");
Console.Write("Signals:");
for (int j = 0; j < DBCSigNum; j++)
{
StringBuilder SigName = new StringBuilder(32);
CAN_DBCParser.DBC_GetMsgSignalName(DBCHandle, MsgName, j, SigName);
//Console.Write("{0} ", SigName);
Console.Write("{0} ", SigName);
//增加信息数据
ListCanDbcModel.Add(new CanDbcModel()
@@ -379,7 +391,7 @@ namespace CapMachine.Wpf.CanDrive
Publisher = Publisher.ToString()
});
}
//Console.WriteLine("");
Console.WriteLine("");
}
//Dbc解析成功
@@ -429,11 +441,11 @@ namespace CapMachine.Wpf.CanDrive
int SendedNum = USB2CAN.CAN_SendMsg(DevHandle, WriteCANIndex, CanMsg, (uint)CanMsg.Length);
if (SendedNum >= 0)
{
//Console.WriteLine("Success send frames:{0}", SendedNum);
Console.WriteLine("Success send frames:{0}", SendedNum);
}
else
{
//Console.WriteLine("Send CAN data failed! {0}", SendedNum);
Console.WriteLine("Send CAN data failed! {0}", SendedNum);
}
}
@@ -480,7 +492,48 @@ namespace CapMachine.Wpf.CanDrive
/// </summary>
private static Task CycleSendTask { get; set; }
/// <summary>
/// 定时扫描更新数据 扫描Task
/// </summary>
private static Task CycleUpdateCmdTask { get; set; }
StringBuilder ValueSb = new StringBuilder(16);
double[] ValueDouble = new double[5];
private bool _IsSendOk;
/// <summary>
/// 发送报文是否OK
/// </summary>
public bool IsSendOk
{
get { return _IsSendOk; }
set
{
if (_IsSendOk != value)
{
RaisePropertyChanged();
_IsSendOk = value;
}
//RaisePropertyChanged();
}
}
private bool _IsReviceOk;
/// <summary>
/// 接收报文是否OK
/// </summary>
public bool IsReviceOk
{
get { return _IsReviceOk; }
set
{
if (_IsReviceOk != value)
{
RaisePropertyChanged();
_IsReviceOk = value;
}
}
}
/// <summary>
/// 要发送的数据
@@ -530,11 +583,11 @@ namespace CapMachine.Wpf.CanDrive
int SendedNum = USB2CAN.CAN_SendMsg(DevHandle, WriteCANIndex, CanMsg, (uint)CanMsg.Length);
if (SendedNum >= 0)
{
//Console.WriteLine("Success send frames:{0}", SendedNum);
Console.WriteLine("Success send frames:{0}", SendedNum);
}
else
{
//Console.WriteLine("Send CAN data failed! {0}", SendedNum);
Console.WriteLine("Send CAN data failed! {0}", SendedNum);
}
}
catch (Exception ex)
@@ -546,97 +599,6 @@ namespace CapMachine.Wpf.CanDrive
}
/// <summary>
/// 循环获取CAN消息
/// </summary>
public void StartCycleReviceCanMsg()
{
CycleReviceTask = Task.Run(async () =>
{
while (IsCycleRevice)
{
await Task.Delay(ReviceCycle);
try
{
//另外一个CAN通道读取数据
USB2CAN.CAN_MSG[] CanMsgBuffer = new USB2CAN.CAN_MSG[128];
//申请数据缓冲区
IntPtr msgPtRead = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(USB2CAN.CAN_MSG)) * CanMsgBuffer.Length);
int CanNum = USB2CAN.CAN_GetMsgWithSize(DevHandle, ReadCANIndex, msgPtRead, CanMsgBuffer.Length);
if (CanNum > 0)
{
Console.WriteLine("Read CanMsgNum = {0}", CanNum);
for (int i = 0; i < CanNum; i++)
{
//CanMsgBuffer[i] = (USB2CAN.CAN_MSG)Marshal.PtrToStructure((IntPtr)((UInt32)msgPtRead + i * Marshal.SizeOf(typeof(USB2CAN.CAN_MSG))), typeof(USB2CAN.CAN_MSG)); //有溢出报错
CanMsgBuffer[i] = (USB2CAN.CAN_MSG)Marshal.PtrToStructure((IntPtr)(msgPtRead + i * Marshal.SizeOf(typeof(USB2CAN.CAN_MSG))), typeof(USB2CAN.CAN_MSG));
//Console.WriteLine("CanMsg[{0}].ID = 0x{1}", i, CanMsgBuffer[i].ID.ToString("X8"));
//Console.WriteLine("CanMsg[{0}].TimeStamp = {1}", i, CanMsgBuffer[i].TimeStamp);
//Console.Write("CanMsg[{0}].Data = ", i);
for (int j = 0; j < CanMsgBuffer[i].DataLen; j++)
{
Console.Write("{0} ", CanMsgBuffer[i].Data[j].ToString("X2"));
}
//Console.WriteLine("");
//报文给高速记录的服务
HighSpeedDataService.AppendOrUpdateMsg(new Models.HighSpeed.CommMsg()
{
Category = "CAN",
MsgInfo = "0x" + CanMsgBuffer[i].ID.ToString("X8"),
MsgData = BitConverter.ToString(CanMsgBuffer[i].Data),
Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")
});
}
}
else if (CanNum == 0)
{
//Console.WriteLine("No CAN data!");
}
else
{
//Console.WriteLine("Get CAN data error!");
}
Console.WriteLine("");
//将CAN消息数据填充到信号里面用DBC解析数据
CAN_DBCParser.DBC_SyncCANMsgToValue(DBCHandle, msgPtRead, CanNum);
//循环获取消息的数据
foreach (var item in ListCanDbcModel)
{
//有配置的名称的,认为是有用的,则需要读取数据
//if (!string.IsNullOrEmpty(item.Name))
//{
CAN_DBCParser.DBC_GetSignalValueStr(DBCHandle, new StringBuilder(item.MsgName), new StringBuilder(item.SignalName), ValueSb);
item.SignalRtValueSb = ValueSb;
Console.Write(ValueSb.ToString());
//}
}
//释放数据缓冲区,必须释放,否则程序运行一段时间后会报内存不足
Marshal.FreeHGlobal(msgPtRead);
Thread.Sleep(10);
////获取信号值并打印出来
//StringBuilder ValueStr = new StringBuilder(32);
//CAN_DBCParser.DBC_GetSignalValueStr(DBCHandle, new StringBuilder("msg_moto_speed"), new StringBuilder("moto_speed"), ValueStr);
//Console.WriteLine("moto_speed = {0}", ValueStr);
//CAN_DBCParser.DBC_GetSignalValueStr(DBCHandle, new StringBuilder("msg_oil_pressure"), new StringBuilder("oil_pressure"), ValueStr);
//Console.WriteLine("oil_pressure = {0}", ValueStr);
//CAN_DBCParser.DBC_GetSignalValueStr(DBCHandle, new StringBuilder("msg_speed_can"), new StringBuilder("speed_can"), ValueStr);
//Console.WriteLine("speed_can = {0}", ValueStr);
}
catch (Exception ex)
{
//LogService.Info($"时间:{DateTime.Now.ToString()}-【Meter】-{ex.Message}");
}
}
});
}
#region
// 添加取消标记源字段用于停止任务
@@ -725,6 +687,7 @@ namespace CapMachine.Wpf.CanDrive
// 严重延迟,重新校准
NextExecutionTime = Stopwatcher.ElapsedTicks;
Console.WriteLine("定时发送延迟过大,重新校准时间");
LoggerService.Info($"定时发送延迟过大,重新校准时间");
}
// 使用Stopwatch记录实际的执行间隔而不是DateTime
@@ -770,12 +733,12 @@ namespace CapMachine.Wpf.CanDrive
if (SendedNum >= 0)
{
//Console.WriteLine("Success send frames:{0}", SendedNum);
//IsSendOk = true;
IsSendOk = true;
}
else
{
//Console.WriteLine("Send CAN data failed! {0}", SendedNum);
//IsSendOk = false;
IsSendOk = false;
}
}
@@ -783,32 +746,43 @@ namespace CapMachine.Wpf.CanDrive
}
catch (TaskCanceledException)
{
LoggerService.Info($"精确周期发送CAN数据-任务被取消,正常退出");
// 任务被取消,正常退出
IsSendOk = false;
break;
}
catch (Exception ex)
{
Console.WriteLine($"CAN周期发送异常: {ex.Message}");
// 短暂暂停避免异常情况下CPU占用过高
IsSendOk = false;
await Task.Delay(10, token);
LoggerService.Info($"精确周期发送CAN数据-{ex.Message}");
}
}
IsSendOk = false;
}
catch (Exception ex)
{
// 确保在任何情况下(正常退出、异常、取消)都会停止计时器
Stopwatcher.Stop();
LoggerService.Info($"精确周期发送CAN数据-{ex.Message}");
// 清理其他可能的资源
Console.WriteLine("CAN周期发送任务已结束资源已清理");
IsSendOk = false;
}
finally
{
// 确保在任何情况下(正常退出、异常、取消)都会停止计时器
Stopwatcher.Stop();
LoggerService.Info("精确周期发送CAN数据-正常退出、异常、取消)都会停止计时器");
IsSendOk = false;
}
}, token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
}
@@ -823,7 +797,451 @@ namespace CapMachine.Wpf.CanDrive
#endregion
#region
private bool _SchEnable;
/// <summary>
/// 调度表使能
/// </summary>
public bool SchEnable
{
get { return _SchEnable; }
set
{
_SchEnable = value;
RaisePropertyChanged();
}
}
/// <summary>
/// 调度表的发送的报文数据
/// </summary>
private USB2CAN.CAN_MSG[] SchCanMsg { get; set; }
/// <summary>
/// 依据消息的分组
/// </summary>
private IEnumerable<IGrouping<string, CanCmdData>> GroupMsg { get; set; }
/// <summary>
/// 调度表集合数据
/// 总共3个调度表第一个表里面包含3帧数据第二个调度表包含6帧数据第三个调度表包含11帧数据
/// Byte[] MsgTabNum = new Byte[3] { 3, 6, 11 };
/// </summary>
private Byte[] MsgTabNum { get; set; }
/// <summary>
/// 调度表发送的次数集合
/// 第一个调度表循环发送数据第二个调度表循环发送数据第三个调度表只发送3次
/// UInt16[] SendTimes = new UInt16[3] { 0xFFFF, 0xFFFF, 3 };
/// </summary>
private UInt16[] SendTimes { get; set; }
/// <summary>
/// 预设的调度表的个数 常值
/// </summary>
private const int MsgTabCount = 5;
/// <summary>
/// 定时更新时间
/// </summary>
private int UpdateCycle = 100;
/// <summary>
/// CNA 调度表的配置信息
/// </summary>
public List<CANScheduleConfigDto> ListCANScheduleConfig { get; set; }
Random random = new Random();
/// <summary>
/// 更新数据 测试用废弃了
/// </summary>
public void UpdateValue()
{
//通过DBC进行对消息赋值
IntPtr msgPtSend = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(USB2CAN.CAN_MSG)));
int Index = 0;
//循环给MSG赋值数据
foreach (var itemMsg in GroupMsg)
{
foreach (var itemSignal in itemMsg)
{
itemSignal.SignalCmdValue = random.Next(0, 100);
CAN_DBCParser.DBC_SetSignalValue(DBCHandle, new StringBuilder(itemMsg.Key), new StringBuilder(itemSignal.SignalName), itemSignal.SignalCmdValue);
}
CAN_DBCParser.DBC_SyncValueToCANMsg(DBCHandle, new StringBuilder(itemMsg.Key), msgPtSend);
SchCanMsg[Index] = (USB2CAN.CAN_MSG)Marshal.PtrToStructure(msgPtSend, typeof(USB2CAN.CAN_MSG));
Index++;
}
//通过DBC写入数据后生成CanMsg
//将信号值填入CAN消息里面
//释放申请的临时缓冲区
Marshal.FreeHGlobal(msgPtSend);
////总共3个调度表第一个表里面包含3帧数据第二个调度表包含6帧数据第三个调度表包含11帧数据
//MsgTabNum = new Byte[1] { 1 };
////第一个调度表循环发送数据第二个调度表循环发送数据第三个调度表只发送3次
//SendTimes = new UInt16[1] { 0xFFFF };
//var ret = USB2CAN.CAN_SetSchedule(DevHandle, WriteCANIndex, SchCanMsg, MsgTabNum, SendTimes, 1);//配置调度表,该函数耗时可能会比较长,但是只需要执行一次即可
var ret = USB2CAN.CAN_UpdateSchedule(DevHandle, WriteCANIndex, 0, 0, SchCanMsg, 1);//配置调度表,该函数耗时可能会比较长,但是只需要执行一次即可
if (ret == USB2CAN.CAN_SUCCESS)
{
Console.WriteLine("Update CAN Schedule Success");
}
else
{
Console.WriteLine("Update CAN Schedule Error ret = {0}", ret);
return;
}
}
/// <summary>
/// 开始调度表执行
/// </summary>
public void StartSchedule()
{
if (CmdData.Count() == 0) return;
//依据报文进行分组
GroupMsg = CmdData.GroupBy(x => x.MsgName)!;
//初始化调度表要发送的消息结构
SchCanMsg = new USB2CAN.CAN_MSG[GroupMsg.Count()];
for (int i = 0; i < GroupMsg.Count(); i++)
{
SchCanMsg[i] = new USB2CAN.CAN_MSG();
SchCanMsg[i].Data = new Byte[64];
}
//通过DBC进行对消息赋值
IntPtr msgPtSend = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(USB2CAN.CAN_MSG)));
int Index = 0;
//循环给MSG赋值数据
foreach (var itemMsg in GroupMsg)
{
foreach (var itemSignal in itemMsg)
{
CAN_DBCParser.DBC_SetSignalValue(DBCHandle, new StringBuilder(itemMsg.Key), new StringBuilder(itemSignal.SignalName), itemSignal.SignalCmdValue);
}
CAN_DBCParser.DBC_SyncValueToCANMsg(DBCHandle, new StringBuilder(itemMsg.Key), msgPtSend);
//每个分组就是一个帧指令/消息数据
SchCanMsg[Index] = (USB2CAN.CAN_MSG)Marshal.PtrToStructure(msgPtSend, typeof(USB2CAN.CAN_MSG));
//分配当前消息帧在集合中的位置信息到ListCANScheduleConfig中方便实时更新时定位帧的位置
if (ListCANScheduleConfig.Any(a => a.MsgName == itemMsg.Key))
{
//把帧的位置给ListCANScheduleConfig方便更新时定位数据
ListCANScheduleConfig.FindFirst(a => a.MsgName == itemMsg.Key).MsgIndex = Index;
//设置当前这个报文的在调度表中的发送周期
SchCanMsg[Index].TimeStamp = (uint)ListCANScheduleConfig.FindFirst(a => a.MsgName == itemMsg.Key).Cycle;
}
Index++;
}
//通过DBC写入数据后生成CanMsg
//将信号值填入CAN消息里面
//释放申请的临时缓冲区
Marshal.FreeHGlobal(msgPtSend);
//********就是可以设置多个调度表放那里,但是运行时同一个时刻只能运行调度表其中的一个 ********
//****** 控制报文SchCanMsg和调度器中第一个调度器中的报文集合和要更新的报文集合都是同一个变量SchCanMsg ********
// *** SchCanMsg的Index序号和ListCANScheduleConfig的MsgIndex是一样的 ***
//图莫斯的Sample总共3个调度表第一个表里面包含3帧数据第二个调度表包含6帧数据第三个调度表包含11帧数据
//预设5个调度表但是我们只用其中第一个调度表第一个调度表中包括多少消息帧由系统的控制指令的帧的分布决定SchCanMsg.Count()是所需要的控制发送的帧,都放到第一个调度表中
MsgTabNum = new Byte[MsgTabCount] { (byte)SchCanMsg.Count(), 1, 1, 1, 1 };
//0xFFFF调度表循环发送数据X调度表循环发送的次数
//设置每个调度表的发送方式,约定全部为循环发送
SendTimes = new UInt16[MsgTabCount] { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
//SchCanMsg:需要发送的消息集合MsgTabNum调度表集合数据SendTimes发送次数集合数据调度表个数MsgTabCount
var ret = USB2CAN.CAN_SetSchedule(DevHandle, WriteCANIndex, SchCanMsg, MsgTabNum, SendTimes, MsgTabCount);//配置调度表,该函数耗时可能会比较长,但是只需要执行一次即可
if (ret == USB2CAN.CAN_SUCCESS)
{
Console.WriteLine("Set CAN Schedule Success");
}
else
{
Console.WriteLine("Set CAN Schedule Error ret = {0}", ret);
LoggerService.Info($"Set CAN Schedule Error; 返回错误代码:{ret}");
return;
}
//约定使用Index=0 1号调度器因为同一个时刻只能有一个调度器工作把所有的报文都要放到这个调度器中
//CAN_MSG的TimeStamp就是这个报文发送的周期由调度器协调
ret = USB2CAN.CAN_StartSchedule(DevHandle, WriteCANIndex, (byte)0, (byte)100, (byte)ListCANScheduleConfig.FirstOrDefault()!.OrderSend);
if (ret == USB2CAN.CAN_SUCCESS)
{
Console.WriteLine($"Start CAN Schedule 1 SuccessSchTabIndex{(byte)0} - Cycle{(byte)100} - OrderSend{(byte)1}");
}
else
{
Console.WriteLine("Start CAN Schedule 1 Error ret = {0}", ret);
LoggerService.Info($"Start CAN Schedule 1 Error;");
return;
}
//foreach (var itemGroupMsg in GroupMsg)
//{
// if (itemGroupMsg == null) continue;
// if (ListCANScheduleConfig.Any(a => a.MsgName!.Contains(itemGroupMsg.Key)))
// {
// var CANScheduleConfig = ListCANScheduleConfig.FindFirst(a => a.MsgName!.Contains(itemGroupMsg.Key));
// //配置表里面包括这个报文消息内容
// ret = USB2CAN.CAN_StartSchedule(DevHandle, WriteCANIndex, (byte)CANScheduleConfig.SchTabIndex, (byte)CANScheduleConfig.Cycle, (byte)CANScheduleConfig.OrderSend);
// if (ret == USB2CAN.CAN_SUCCESS)
// {
// Console.WriteLine($"Start CAN Schedule 1 SuccessSchTabIndex{(byte)CANScheduleConfig.SchTabIndex} - Cycle{(byte)CANScheduleConfig.Cycle} - OrderSend{(byte)CANScheduleConfig.OrderSend}");
// }
// else
// {
// Console.WriteLine("Start CAN Schedule 1 Error ret = {0}", ret);
// LoggerService.Info($"Start CAN Schedule 1 Error;消息名称:{CANScheduleConfig.MsgName}");
// return;
// }
// }
// else
// {
// LoggerService.Info($"调度表配置未发现对应的消息报文信息;报文信息{itemGroupMsg.Key}");
// }
//}
//走到这里说明调度表执行的是OK的
//IsSendOk = true;
}
/// <summary>
/// 停止调度表
/// </summary>
public void StopSchedule()
{
ret = USB2CAN.CAN_StopSchedule(DevHandle, WriteCANIndex);//启动第一个调度表,表里面的CAN帧并行发送
if (ret == USB2CAN.CAN_SUCCESS)
{
IsSendOk = false;
Console.WriteLine("Stop CAN Schedule");
LoggerService.Info($"Stop CAN Schedule");
}
else
{
Console.WriteLine("Start CAN Schedule Error ret = {0}", ret);
LoggerService.Info($"Stop CAN Schedule");
return;
}
}
/// <summary>
/// 循环使用的
/// </summary>
private int CycleUpdateIndex = 0;
/// <summary>
/// 循环更新调度表的指令数据
/// 定时更新数据到调度表中
/// </summary>
public void StartCycleUpdateCmd()
{
CycleUpdateCmdTask = Task.Run(async () =>
{
while (IsCycleSend)
{
await Task.Delay(UpdateCycle);
try
{
//通过DBC进行对消息赋值
IntPtr msgPtSend = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(USB2CAN.CAN_MSG)));
CycleUpdateIndex = 0;
//循环给MSG赋值数据顺序是固定的跟初始时设置是一样的
foreach (var itemMsg in GroupMsg)
{
foreach (var itemSignal in itemMsg)
{
//itemSignal.SignalCmdValue = random.Next(0, 100); //仿真测试数据使用
CAN_DBCParser.DBC_SetSignalValue(DBCHandle, new StringBuilder(itemMsg.Key), new StringBuilder(itemSignal.SignalName), itemSignal.SignalCmdValue);
}
CAN_DBCParser.DBC_SyncValueToCANMsg(DBCHandle, new StringBuilder(itemMsg.Key), msgPtSend);
SchCanMsg[CycleUpdateIndex] = (USB2CAN.CAN_MSG)Marshal.PtrToStructure(msgPtSend, typeof(USB2CAN.CAN_MSG));
CycleUpdateIndex++;
}
//通过DBC写入数据后生成CanMsg
//将信号值填入CAN消息里面
//释放申请的临时缓冲区
Marshal.FreeHGlobal(msgPtSend);
//CAN_UpdateSchedule 官网解释
// ---MsgTabIndex CAN调度表索引号
// ---MsgIndex 开始更新帧起始索引,若起始索引大于调度表帧数,则将帧添加到调度表后面
// ---pCanMsg 需要更新的CAN帧指针
// ---MsgNum pCanMsgTab里面包含的有效帧数
//CAN_UpdateSchedule中的MsgIndex表示当前的调度器中的帧Index序号
//因为调度表中的帧集合和控制帧的集合和要更新的帧集合都是同一个集合SchCanMsg
//默认1号调度表一个更新所有的帧数据
var ret = USB2CAN.CAN_UpdateSchedule(DevHandle, WriteCANIndex, (byte)0, (byte)(0), SchCanMsg, (byte)SchCanMsg.Count());//配置调度表,该函数耗时可能会比较长,但是只需要执行一次即可
if (ret == USB2CAN.CAN_SUCCESS)
{
IsSendOk = true;
Console.WriteLine($"Update CAN Schedule Success -- SchTabIndex{(byte)0} -- MsgIndex{(byte)(0)} ");
}
else
{
IsSendOk = false;
Console.WriteLine($"Update CAN Schedule Error ret = {ret} -- SchTabIndex{(byte)0} -- MsgIndex{(byte)(0)}");
//return;
}
//一个报文帧一个报文帧进行更新数据
////配置信息 默认启用1号调度器,MsgTabIndex=0
//foreach (var itemMsgSchConfig in ListCANScheduleConfig)
//{
// //USB2CAN.CAN_MSG[] SchCanMsg1=new CAN_MSG[1];
// //SchCanMsg1[0] = SchCanMsg[itemMsgSchConfig.MsgIndex];
// // MsgTabIndex CAN调度表索引号 ;MsgIndex 开始更新帧起始索引,若起始索引大于调度表帧数,则将帧添加到调度表后面, ;
// // pCanMsg 需要更新的CAN帧指针,消息数据 ; MsgNum pCanMsgTab里面包含的有效帧数一个调度表对应一个帧/消息即为1 (byte)(itemMsgSchConfig.MsgIndex+0)
// var ret = USB2CAN.CAN_UpdateSchedule(DevHandle, WriteCANIndex, (byte)0, (byte)(itemMsgSchConfig.MsgIndex), SchCanMsg, 1);//配置调度表,该函数耗时可能会比较长,但是只需要执行一次即可
// if (ret == USB2CAN.CAN_SUCCESS)
// {
// Console.WriteLine($"Update CAN Schedule Success -- SchTabIndex{(byte)itemMsgSchConfig.SchTabIndex} -- MsgIndex{(byte)(itemMsgSchConfig.MsgIndex)} ");
// }
// else
// {
// Console.WriteLine($"Update CAN Schedule Error ret = {ret} -- SchTabIndex{(byte)itemMsgSchConfig.SchTabIndex} -- MsgIndex{(byte)(itemMsgSchConfig.MsgIndex)}");
// //return;
// }
//}
}
catch (Exception ex)
{
IsSendOk = false;
LoggerService.Info($"时间:{DateTime.Now.ToString()}-【MSG】-{ex.Message}");
}
}
IsSendOk = false;
});
}
#endregion
/// <summary>
/// 循环获取CAN消息
/// </summary>
public void StartCycleReviceCanMsg()
{
CycleReviceTask = Task.Run(async () =>
{
while (IsCycleRevice)
{
await Task.Delay(ReviceCycle);
try
{
//另外一个CAN通道读取数据
USB2CAN.CAN_MSG[] CanMsgBuffer = new USB2CAN.CAN_MSG[1024];
//申请数据缓冲区
IntPtr msgPtRead = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(USB2CAN.CAN_MSG)) * CanMsgBuffer.Length);
int CanNum = USB2CAN.CAN_GetMsgWithSize(DevHandle, ReadCANIndex, msgPtRead, CanMsgBuffer.Length);
//int CanNum = USB2CAN.CAN_GetMsgWithSize(DevHandle, 1, msgPtRead, CanMsgBuffer.Length);//测试用CAN卡 CAN1和CAN2 短接时测试用
if (CanNum > 0)
{
IsReviceOk = true;
Console.WriteLine("Read CanMsgNum = {0}", CanNum);
for (int i = 0; i < CanNum; i++)
{
//CanMsgBuffer[i] = (USB2CAN.CAN_MSG)Marshal.PtrToStructure((IntPtr)((UInt32)msgPtRead + i * Marshal.SizeOf(typeof(USB2CAN.CAN_MSG))), typeof(USB2CAN.CAN_MSG)); //有溢出报错
CanMsgBuffer[i] = (USB2CAN.CAN_MSG)Marshal.PtrToStructure((IntPtr)(msgPtRead + i * Marshal.SizeOf(typeof(USB2CAN.CAN_MSG))), typeof(USB2CAN.CAN_MSG));
Console.WriteLine("CanMsg[{0}].ID = 0x{1}", i, CanMsgBuffer[i].ID.ToString("X8"));
Console.WriteLine("CanMsg[{0}].TimeStamp = {1}", i, CanMsgBuffer[i].TimeStamp);
Console.Write("CanMsg[{0}].Data = ", i);
for (int j = 0; j < CanMsgBuffer[i].DataLen; j++)
{
Console.Write("{0} ", CanMsgBuffer[i].Data[j].ToString("X2"));
}
Console.WriteLine("");
//报文给高速记录的服务
HighSpeedDataService.AppendOrUpdateMsg(new Models.HighSpeed.CommMsg()
{
Category = "CAN",
MsgInfo = "0x" + CanMsgBuffer[i].ID.ToString("X8"),
MsgData = BitConverter.ToString(CanMsgBuffer[i].Data),
Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")
});
}
}
else if (CanNum == 0)
{
IsReviceOk = false;
Console.WriteLine("No CAN data!");
}
else
{
IsReviceOk = false;
Console.WriteLine("Get CAN data error!");
}
//Console.WriteLine("");
//将CAN消息数据填充到信号里面用DBC解析数据
CAN_DBCParser.DBC_SyncCANMsgToValue(DBCHandle, msgPtRead, CanNum);
//循环获取消息的数据
foreach (var item in ListCanDbcModel)
{
//有配置的名称的,认为是有用的,则需要读取数据
//if (!string.IsNullOrEmpty(item.Name))
//{
//CAN_DBCParser.DBC_GetSignalValueStr(DBCHandle, new StringBuilder(item.MsgName), new StringBuilder(item.SignalName), ValueSb);
//double[] ValueDouble;
CAN_DBCParser.DBC_GetSignalValue(DBCHandle, new StringBuilder(item.MsgName), new StringBuilder(item.SignalName), ValueDouble);
//item.SignalRtValueSb = ValueSb;
item.SignalRtValue = ValueDouble[0].ToString();
//Console.Write(ValueSb.ToString());
//}
}
//释放数据缓冲区,必须释放,否则程序运行一段时间后会报内存不足
Marshal.FreeHGlobal(msgPtRead);
Thread.Sleep(10);
////获取信号值并打印出来
//StringBuilder ValueStr = new StringBuilder(32);
//CAN_DBCParser.DBC_GetSignalValueStr(DBCHandle, new StringBuilder("msg_moto_speed"), new StringBuilder("moto_speed"), ValueStr);
//Console.WriteLine("moto_speed = {0}", ValueStr);
//CAN_DBCParser.DBC_GetSignalValueStr(DBCHandle, new StringBuilder("msg_oil_pressure"), new StringBuilder("oil_pressure"), ValueStr);
//Console.WriteLine("oil_pressure = {0}", ValueStr);
//CAN_DBCParser.DBC_GetSignalValueStr(DBCHandle, new StringBuilder("msg_speed_can"), new StringBuilder("speed_can"), ValueStr);
//Console.WriteLine("speed_can = {0}", ValueStr);
}
catch (Exception ex)
{
IsReviceOk = false;
LoggerService.Info("接收出现异常");
}
//finally
//{
// IsReviceOk = false;
//}
}
IsReviceOk = false;
});
}
/// <summary>
/// 接受CAN消息
@@ -884,6 +1302,10 @@ namespace CapMachine.Wpf.CanDrive
DbcParserState = false;
IsCycleRevice = false;
IsCycleSend = false;
if (SchEnable)
{
StopSchedule();
}
}
}

View File

@@ -1,511 +0,0 @@
using CapMachine.Wpf.Models.Tag;
using NPOI.OpenXmlFormats.Wordprocessing;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Interop;
namespace CapMachine.Wpf.CanDrive
{
/// <summary>
/// Toomoss CAN
/// </summary>
public class ToomossCanFD : BindableBase
{
/// <summary>
/// 实例化函数
/// </summary>
public ToomossCanFD()
{
}
/// <summary>
/// 开始CAN的驱动
/// </summary>
public void StartCanDrive()
{
IsExistsDllFile();
ScanDevice();
OpenDevice();
GetDeviceInfo();
GetCANConfig();
InitCAN();
}
/// <summary>
/// 开始Dbc文件写入
/// </summary>
public void StartDbc(string DbcPath)
{
DBC_Parser(DbcPath);
}
/// <summary>
/// Dbc消息集合
/// </summary>
public ObservableCollection<CanDbcModel> ListCanDbcModel { get; set; } = new ObservableCollection<CanDbcModel>();
#region
/// <summary>
/// 设备固件信息
/// </summary>
public USB_DEVICE.DEVICE_INFO DevInfo = new USB_DEVICE.DEVICE_INFO();
/// <summary>
/// CAN Config
/// </summary>
USB2CANFD.CANFD_INIT_CONFIG CANConfig = new USB2CANFD.CANFD_INIT_CONFIG();
/// <summary>
/// DBC Handle
/// </summary>
public UInt64 DBCHandle { get; set; }
/// <summary>
/// 扫描设备Handle集合
/// </summary>
public Int32[] DevHandles { get; set; } = new Int32[20];
/// <summary>
/// 扫描设备Handle
/// </summary>
public Int32 DevHandle { get; set; } = 0;
/// <summary>
/// Write CAN Index
/// </summary>
public Byte WriteCANIndex { get; set; } = 0;
/// <summary>
/// Read CAN Index
/// </summary>
public Byte ReadCANIndex { get; set; } = 1;
private bool _OpenState;
/// <summary>
/// 打开设备的状态
/// </summary>
public bool OpenState
{
get { return _OpenState; }
set { _OpenState = value; RaisePropertyChanged(); }
}
/// <summary>
/// 扫描到设备个数
/// </summary>
public Int32 DevNum { get; set; }
public Int32 ret { get; set; }
public string dllFilePath { get; set; } = "USB2XXX.dll";
/// <summary>
/// 消息值Pt
/// </summary>
public IntPtr msgPt { get; set; }
#endregion
/// <summary>
/// ******************【1】*********************
/// 是否存在Dll文件
/// </summary>
/// <returns></returns>
public bool IsExistsDllFile()
{
if (!File.Exists(dllFilePath))
{
Console.WriteLine("请先将USB2XXX.dll和libusb-1.0.dll文件复制到exe程序文件输出目录下!");
Console.WriteLine("dll文件在usb2can_lin_pwm_example/sdk/libs/windows目录下");
Console.WriteLine("程序是32位的就复制x86目录下文件程序是64位的就复制x86_64目录下文件");
return false;
}
return true;
}
/// <summary>
/// ******************【2】*********************
/// 扫描查找设备,并将每个设备的唯一设备号存放到数组中,后面的函数需要用到
/// </summary>
/// <returns></returns>
public bool ScanDevice()
{
DevNum = USB_DEVICE.USB_ScanDevice(DevHandles);
if (DevNum <= 0)
{
Console.WriteLine("No device connected!");
return false;
}
else
{
Console.WriteLine("Have {0} device connected!", DevNum);
DevHandle = DevHandles[0];//获取第一个设备的设备号
return true;
}
}
/// <summary>
/// ******************【3】*********************
/// 打开设备
/// </summary>
/// <returns></returns>
public bool OpenDevice()
{
//打开设备
OpenState = USB_DEVICE.USB_OpenDevice(DevHandle);
if (!OpenState)
{
Console.WriteLine("Open device error!");
return false;
}
else
{
Console.WriteLine("Open device success!");
return true;
}
}
/// <summary>
/// ******************【4】*********************
/// 获取设备的固件信息
/// </summary>
/// <returns></returns>
public bool GetDeviceInfo()
{
//获取固件信息
StringBuilder FuncStr = new StringBuilder(256);
OpenState = USB_DEVICE.DEV_GetDeviceInfo(DevHandle, ref DevInfo, FuncStr);
if (!OpenState)
{
Console.WriteLine("Get device infomation error!");
return false;
}
else
{
Console.WriteLine("Firmware Info:");
Console.WriteLine(" Name:" + Encoding.Default.GetString(DevInfo.FirmwareName));
Console.WriteLine(" Build Date:" + Encoding.Default.GetString(DevInfo.BuildDate));
Console.WriteLine(" Firmware Version:v{0}.{1}.{2}", (DevInfo.FirmwareVersion >> 24) & 0xFF, (DevInfo.FirmwareVersion >> 16) & 0xFF, DevInfo.FirmwareVersion & 0xFFFF);
Console.WriteLine(" Hardware Version:v{0}.{1}.{2}", (DevInfo.HardwareVersion >> 24) & 0xFF, (DevInfo.HardwareVersion >> 16) & 0xFF, DevInfo.HardwareVersion & 0xFFFF);
Console.WriteLine(" Functions:" + DevInfo.Functions.ToString("X8"));
Console.WriteLine(" Functions String:" + FuncStr);
StringBuilder DLLBuildDate = new StringBuilder(256);
USB_DEVICE.DEV_GetDllBuildTime(DLLBuildDate);
Console.WriteLine(" DLL Build Date:" + DLLBuildDate);
return true;
}
}
/// <summary>
/// ******************【5】*********************
/// 获取设备Config配置
/// </summary>
public void GetCANConfig()
{
//获取CAN波特率参数
ret = USB2CANFD.CANFD_GetCANSpeedArg(DevHandle, ref CANConfig, 500000, 2000000);
if (ret != USB2CANFD.CANFD_SUCCESS)
{
Console.WriteLine("Get CAN Speed failed!");
return;
}
else
{
Console.WriteLine("Get CAN Speed Success!");
}
}
/// <summary>
/// ******************【6】*********************
/// 初始化CAN
/// </summary>
public void InitCAN()
{
//初始化CAN
ret = USB2CANFD.CANFD_Init(DevHandle, WriteCANIndex, ref CANConfig);
if (ret != USB2CANFD.CANFD_SUCCESS)
{
Console.WriteLine("Config CAN failed!");
return;
}
else
{
Console.WriteLine("WriteCANIndex Config CAN Success!");
}
ret = USB2CANFD.CANFD_Init(DevHandle, ReadCANIndex, ref CANConfig);
if (ret != USB2CAN.CAN_SUCCESS)
{
Console.WriteLine("Config CAN failed!");
return;
}
else
{
Console.WriteLine("ReadCANIndex Config CAN Success!");
}
Console.WriteLine("");
}
/// <summary>
/// ******************【7】*********************
/// DBC解析
/// </summary>
public void DBC_Parser(string Path)
{
//解析DBC文件
DBCHandle = CANFD_DBCParser.DBC_ParserFile(DevHandle, new StringBuilder(Path));
if (DBCHandle == 0)
{
Console.WriteLine("Parser DBC File error!");
return;
}
else
{
Console.WriteLine("Parser DBC File success!");
}
ListCanDbcModel.Clear();
//打印DBC里面报文和信号相关信息
int DBCMsgNum = CANFD_DBCParser.DBC_GetMsgQuantity(DBCHandle);
for (int i = 0; i < DBCMsgNum; i++)
{
StringBuilder MsgName = new StringBuilder(32);
CANFD_DBCParser.DBC_GetMsgName(DBCHandle, i, MsgName);
Console.WriteLine("Msg.Name = {0}", MsgName);
int DBCSigNum = CANFD_DBCParser.DBC_GetMsgSignalQuantity(DBCHandle, MsgName);
StringBuilder Publisher = new StringBuilder(32);
CANFD_DBCParser.DBC_GetMsgPublisher(DBCHandle, MsgName, Publisher);
Console.Write("Signals:");
for (int j = 0; j < DBCSigNum; j++)
{
StringBuilder SigName = new StringBuilder(32);
CANFD_DBCParser.DBC_GetMsgSignalName(DBCHandle, MsgName, j, SigName);
Console.Write("{0} ", SigName);
//增加信息数据
ListCanDbcModel.Add(new CanDbcModel()
{
MsgName = MsgName.ToString(),
MsgId = "",
SignalName = SigName.ToString(),
SignalDesc = "",
SignalUnit = "",
SignalRtValue = "",
Publisher = Publisher.ToString()
});
}
Console.WriteLine("");
}
}
/// <summary>
/// 发送CAN数据
/// </summary>
public void SendCanMsg(List<CanCmdData> CmdData)
{
var GroupMsg = CmdData.GroupBy(x => x.MsgName);
USB2CANFD.CANFD_MSG[] CanMsg = new USB2CANFD.CANFD_MSG[GroupMsg.Count()];
for (int i = 0; i < GroupMsg.Count(); i++)
{
CanMsg[i] = new USB2CANFD.CANFD_MSG();
CanMsg[i].Data = new Byte[64];
}
IntPtr msgPt = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(USB2CANFD.CANFD_MSG)));
int Index = 0;
//循环给MSG赋值数据
foreach (var itemMsg in GroupMsg)
{
foreach (var itemSignal in itemMsg)
{
CANFD_DBCParser.DBC_SetSignalValue(DBCHandle, new StringBuilder(itemMsg.Key), new StringBuilder(itemSignal.SignalName), itemSignal.SignalCmdValue);
}
CANFD_DBCParser.DBC_SyncValueToCANFDMsg(DBCHandle, new StringBuilder(itemMsg.Key), msgPt);
CanMsg[Index] = (USB2CANFD.CANFD_MSG)Marshal.PtrToStructure(msgPt, typeof(USB2CANFD.CANFD_MSG));
Index++;
}
//设置信号值
//DBCParser.DBC_SetSignalValue(DBCHandle, new StringBuilder("msg_moto_speed"), new StringBuilder("moto_speed"), 2412);
//DBCParser.DBC_SetSignalValue(DBCHandle, new StringBuilder("msg_oil_pressure"), new StringBuilder("oil_pressure"), 980);
//DBCParser.DBC_SetSignalValue(DBCHandle, new StringBuilder("msg_speed_can"), new StringBuilder("speed_can"), 120);
//通过DBC写入数据后生成CanMsg
//将信号值填入CAN消息里面
//IntPtr msgPt = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(USB2CANFD.CANFD_MSG)));
//DBCParser.DBC_SyncValueToCANFDMsg(DBCHandle, new StringBuilder("msg_moto_speed"), msgPt);
//CanMsg[0] = (USB2CANFD.CANFD_MSG)Marshal.PtrToStructure(msgPt, typeof(USB2CANFD.CANFD_MSG));
//DBCParser.DBC_SyncValueToCANFDMsg(DBCHandle, new StringBuilder("msg_oil_pressure"), msgPt);
//CanMsg[1] = (USB2CANFD.CANFD_MSG)Marshal.PtrToStructure(msgPt, typeof(USB2CANFD.CANFD_MSG));
//DBCParser.DBC_SyncValueToCANFDMsg(DBCHandle, new StringBuilder("msg_speed_can"), msgPt);
//CanMsg[2] = (USB2CANFD.CANFD_MSG)Marshal.PtrToStructure(msgPt, typeof(USB2CANFD.CANFD_MSG));
//释放申请的临时缓冲区
Marshal.FreeHGlobal(msgPt);
Console.WriteLine("");
//发送CAN数据
int SendedNum = USB2CANFD.CANFD_SendMsg(DevHandle, WriteCANIndex, CanMsg, (Int32)CanMsg.Length);
if (SendedNum >= 0)
{
Console.WriteLine("Success send frames:{0}", SendedNum);
}
else
{
Console.WriteLine("Send CAN data failed! {0}", SendedNum);
}
}
/// <summary>
/// 是否循环接收数据
/// </summary>
public bool IsCycleRevice { get; set; }
/// <summary>
/// CycleRevice扫描Task
/// </summary>
private static Task CycleReviceTask { get; set; }
/// <summary>
/// 循环获取CAN消息
/// </summary>
public void StartCycleReviceCanMsg()
{
CycleReviceTask = Task.Run(async () =>
{
while (IsCycleRevice)
{
await Task.Delay(1000);
try
{
//另外一个CAN通道读取数据
USB2CANFD.CANFD_MSG[] CanMsgBuffer = new USB2CANFD.CANFD_MSG[10];
msgPt = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(USB2CANFD.CANFD_MSG)) * CanMsgBuffer.Length);
int CanNum = USB2CANFD.CANFD_GetMsg(DevHandle, ReadCANIndex, msgPt, CanMsgBuffer.Length);
if (CanNum > 0)
{
Console.WriteLine("Read CanMsgNum = {0}", CanNum);
for (int i = 0; i < CanNum; i++)
{
CanMsgBuffer[i] = (USB2CANFD.CANFD_MSG)Marshal.PtrToStructure((IntPtr)(msgPt + i * Marshal.SizeOf(typeof(USB2CANFD.CANFD_MSG))), typeof(USB2CANFD.CANFD_MSG));
Console.WriteLine("CanMsg[{0}].ID = 0x{1}", i, CanMsgBuffer[i].ID.ToString("X8"));
//Console.WriteLine("CanMsg[{0}].TimeStamp = {1}",i,CanMsgBuffer[i].TimeStamp);
Console.Write("CanMsg[{0}].Data = ", i);
for (int j = 0; j < CanMsgBuffer[i].DLC; j++)
{
Console.Write("{0} ", CanMsgBuffer[i].Data[j].ToString("X2"));
}
Console.WriteLine("");
}
}
else if (CanNum == 0)
{
Console.WriteLine("No CAN data!");
}
else
{
Console.WriteLine("Get CAN data error!");
}
Console.WriteLine("");
//将CAN消息数据填充到信号里面
CANFD_DBCParser.DBC_SyncCANFDMsgToValue(DBCHandle, msgPt, CanNum);
//获取信号值并打印出来
StringBuilder ValueStr = new StringBuilder(32);
CANFD_DBCParser.DBC_GetSignalValueStr(DBCHandle, new StringBuilder("TX1"), new StringBuilder("COM_current_Power"), ValueStr);
Console.WriteLine("COM_current_Power = {0}", ValueStr);
CANFD_DBCParser.DBC_GetSignalValueStr(DBCHandle, new StringBuilder("TX1"), new StringBuilder("COM_Curr_dc"), ValueStr);
Console.WriteLine("COM_Curr_dc = {0}", ValueStr);
}
catch (Exception ex)
{
//LogService.Info($"时间:{DateTime.Now.ToString()}-【Meter】-{ex.Message}");
}
}
});
}
/// <summary>
/// 接受CAN消息
/// </summary>
public void ReciveCanMsg()
{
//另外一个CAN通道读取数据
USB2CANFD.CANFD_MSG[] CanMsgBuffer = new USB2CANFD.CANFD_MSG[10];
msgPt = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(USB2CANFD.CANFD_MSG)) * CanMsgBuffer.Length);
int CanNum = USB2CANFD.CANFD_GetMsg(DevHandle, ReadCANIndex, msgPt, CanMsgBuffer.Length);
if (CanNum > 0)
{
Console.WriteLine("Read CanMsgNum = {0}", CanNum);
for (int i = 0; i < CanNum; i++)
{
CanMsgBuffer[i] = (USB2CANFD.CANFD_MSG)Marshal.PtrToStructure((IntPtr)(msgPt + i * Marshal.SizeOf(typeof(USB2CANFD.CANFD_MSG))), typeof(USB2CANFD.CANFD_MSG));
Console.WriteLine("CanMsg[{0}].ID = 0x{1}", i, CanMsgBuffer[i].ID.ToString("X8"));
//Console.WriteLine("CanMsg[{0}].TimeStamp = {1}",i,CanMsgBuffer[i].TimeStamp);
Console.Write("CanMsg[{0}].Data = ", i);
for (int j = 0; j < CanMsgBuffer[i].DLC; j++)
{
Console.Write("{0} ", CanMsgBuffer[i].Data[j].ToString("X2"));
}
Console.WriteLine("");
}
}
else if (CanNum == 0)
{
Console.WriteLine("No CAN data!");
}
else
{
Console.WriteLine("Get CAN data error!");
}
Console.WriteLine("");
//将CAN消息数据填充到信号里面
CANFD_DBCParser.DBC_SyncCANFDMsgToValue(DBCHandle, msgPt, CanNum);
//获取信号值并打印出来
StringBuilder ValueStr = new StringBuilder(32);
CANFD_DBCParser.DBC_GetSignalValueStr(DBCHandle, new StringBuilder("msg_moto_speed"), new StringBuilder("moto_speed"), ValueStr);
Console.WriteLine("moto_speed = {0}", ValueStr);
CANFD_DBCParser.DBC_GetSignalValueStr(DBCHandle, new StringBuilder("msg_oil_pressure"), new StringBuilder("oil_pressure"), ValueStr);
Console.WriteLine("oil_pressure = {0}", ValueStr);
CANFD_DBCParser.DBC_GetSignalValueStr(DBCHandle, new StringBuilder("msg_speed_can"), new StringBuilder("speed_can"), ValueStr);
Console.WriteLine("speed_can = {0}", ValueStr);
}
/// <summary>
/// 关闭设备
/// </summary>
public void CloseDevice()
{
//关闭设备
USB_DEVICE.USB_CloseDevice(DevHandle);
OpenState = false;
}
}
}

View File

@@ -101,14 +101,22 @@ namespace CapMachine.Wpf.CanDrive
[DllImport("USB2XXX.dll")]
public static extern Int32 CAN_Init(Int32 DevHandle, Byte CANIndex, ref CAN_INIT_CONFIG pCanConfig);
[DllImport("USB2XXX.dll")]
public static extern Int32 CAN_Init2(Int32 DevHandle, Byte CANIndex, Int32 BaudRateBps, Byte EnResistor);
[DllImport("USB2XXX.dll")]
public static extern Int32 CAN_Filter_Init(Int32 DevHandle, Byte CANIndex, ref CAN_FILTER_CONFIG pFilterConfig);
[DllImport("USB2XXX.dll")]
public static extern Int32 CAN_FilterList_Init(Int32 DevHandle, Byte CANIndex, UInt32[] pIDList, Byte IDListLen);
[DllImport("USB2XXX.dll")]
public static extern Int32 CAN_StartGetMsg(Int32 DevHandle, Byte CANIndex);
[DllImport("USB2XXX.dll")]
public static extern Int32 CAN_StopGetMsg(Int32 DevHandle, Byte CANIndex);
[DllImport("USB2XXX.dll")]
public static extern Int32 CAN_SendMsg(Int32 DevHandle, Byte CANIndex, CAN_MSG[] pCanSendMsg, UInt32 SendMsgNum);
[DllImport("USB2XXX.dll")]
public static extern Int32 CAN_SendMsgSynch(Int32 DevHandle, Byte CANIndex, CAN_MSG[] pCanSendMsg, UInt32 SendMsgNum);
[DllImport("USB2XXX.dll")]
public static extern Int32 CAN_SendMsgWithTime(Int32 DevHandle, Byte CANIndex, CAN_MSG[] pCanSendMsg, UInt32 SendMsgNum);
[DllImport("USB2XXX.dll")]
public static extern Int32 CAN_GetMsg(Int32 DevHandle, Byte CANIndex, IntPtr pCanGetMsg);
[DllImport("USB2XXX.dll")]
public static extern Int32 CAN_GetMsgWithSize(Int32 DevHandle, Byte CANIndex, IntPtr pCanGetMsg, Int32 BufferSize);
@@ -121,9 +129,17 @@ namespace CapMachine.Wpf.CanDrive
[DllImport("USB2XXX.dll")]
public static extern Int32 CAN_StartSchedule(Int32 DevHandle, Byte CANIndex, Byte MsgTabIndex, Byte TimePrecMs, Byte OrderSend);
[DllImport("USB2XXX.dll")]
public static extern Int32 CAN_UpdateSchedule(Int32 DevHandle, Byte CANIndex, Byte MsgTabIndex, Byte MsgIndex, CAN_MSG[] pCanMsg, Byte MsgNum);
[DllImport("USB2XXX.dll")]
public static extern Int32 CAN_StopSchedule(Int32 DevHandle, Byte CANIndex);
[DllImport("USB2XXX.dll")]
public static extern Int32 CAN_SetRelay(Int32 DevHandle, Byte RelayState);
[DllImport("USB2XXX.dll")]
public static extern Int32 CAN_Stop(Int32 DevHandle, Byte CANIndex);
[DllImport("USB2XXX.dll")]
public static extern Int64 CAN_GetStartTime(Int32 DevHandle, Byte CANIndex);
[DllImport("USB2XXX.dll")]
public static extern Int32 CAN_ResetStartTime(Int32 DevHandle, Byte CANIndex);
//CAN Bootloader相关函数
[DllImport("USB2XXX.dll")]