Files
CapMachine/Sample/zdbc_c#_251106/zdbc_c#_251106/DBC/Program.cs
2026-02-02 21:22:01 +08:00

412 lines
17 KiB
C#
Raw 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.
/*
* 241217 程序默认用USBCANFD-200U通讯两通道对侧
* Main 有加载DBC文件打印DBC文件信息
* 打开设备并演示Encode Decode函数
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Threading;
using System.IO;
using ZLGAPI;
namespace DBC
{
internal class Program
{
private static IntPtr deviceHandle = IntPtr.Zero; // 设备句柄
private static IntPtr[] channelHandles = new IntPtr[]{
IntPtr.Zero,
IntPtr.Zero
};
private static int max_chn = 2; // 通道数量
private static uint DBCHandle = 0; // DBC句柄
private static volatile bool isRunning = true; // 线程标志
static void Main(string[] args)
{
Program.LoadDBCFile(); // 加载DBC文件
Program.ReadDBCFileMessages(); // 打印DBC文件信息
//Program.ReadSignalDescPair(); // 获取具体信号的值与含义
//Program.InitDevice(); // 打开设备,并演示接收解析和发送
Console.ReadKey();
Program.CloseDBCFile();
}
// 加载DBC文件
static void LoadDBCFile()
{
// DBC文件路径
string DBCFilePath = "C:\\Users\\admin\\Desktop\\DBC\\12.dbc";
//string currentDirectory = AppDomain.CurrentDomain.BaseDirectory; // 获取当前执行文件exe同级目录
//string fileName = "12.DBC"; // 替换为你的文件名
//string filePath = Path.Combine(currentDirectory, fileName);
//DBCFilePath = filePath.Replace("\\", "\\\\"); // 将路径中的分隔符替换为双反斜杠
Console.WriteLine("{0} ", DBCFilePath);
// 加载DBC文件
Program.DBCHandle = ZDBC.ZDBC_Init();
IntPtr P2DBCFileAddress = Marshal.StringToHGlobalAnsi(DBCFilePath);
bool Result = ZDBC.ZDBC_LoadFile(DBCHandle, P2DBCFileAddress);
Marshal.FreeHGlobal(P2DBCFileAddress);
}
// 关闭DBC文件
static void CloseDBCFile()
{
ZDBC.ZDBC_Release(Program.DBCHandle);
}
// 读取DBC文件内容
static void ReadDBCFileMessages()
{
uint count = ZDBC.ZDBC_GetMessageCount(Program.DBCHandle); //信号数量
Console.WriteLine(" DBC文件中消息的数量{0}\n", count);
ZDBC.DBCMessage msg = new ZDBC.DBCMessage();
IntPtr ptrMsg = Marshal.AllocHGlobal(Marshal.SizeOf(msg));
if (ZDBC.ZDBC_GetFirstMessage(DBCHandle, ptrMsg))
{
Program.PrintfDBCMessage(ptrMsg);
}
while (ZDBC.ZDBC_GetNextMessage(DBCHandle, ptrMsg))
{
Program.PrintfDBCMessage(ptrMsg);
}
Marshal.FreeHGlobal(ptrMsg);
}
// 打印值描述
static void ReadSignalDescPair()
{
ZDBC.DBCMessage msg = new ZDBC.DBCMessage();
IntPtr ptrMsg = Marshal.AllocHGlobal(Marshal.SizeOf(msg));
uint ID = 0x36F;
string SignalName = "BMS_AbnormRlyOffSt";
// 获取这个id的消息情况
if (ZDBC.ZDBC_GetMessageById(Program.DBCHandle, ID, ptrMsg))
{
Program.PrintfDBCMessage(ptrMsg);
}
else
{
Console.WriteLine("没有找到这个0x{0:x}的定义", ID);
}
// 获取具体信号的值与含义对个数
uint ret = ZDBC.ZDBC_GetValDescPairCount(Program.DBCHandle, ID, SignalName);
Console.WriteLine("{0} 的值与含义对个数: {1}\n", SignalName, ret);
// 循环获取值与含义对
IntPtr ptr_pair = Marshal.AllocHGlobal((int)ret * Marshal.SizeOf(typeof(ZDBC.ValDescPair)));
ZDBC.ZDBC_GetValDescPair(Program.DBCHandle, ID, SignalName, ptr_pair);
ZDBC.ValDescPair[] pair = new ZDBC.ValDescPair[ret];
for (int i = 0; i < ret; i++)
{
pair[i] = (ZDBC.ValDescPair)Marshal.PtrToStructure((IntPtr)((Int64)ptr_pair + i * Marshal.SizeOf(typeof(ZDBC.ValDescPair))), typeof(ZDBC.ValDescPair));
string pair_name = new string(Encoding.ASCII.GetChars(pair[i].strName));
string result = pair_name.Substring(0, pair_name.IndexOf('\0'));
Console.WriteLine("[{0}] {1} {2}", i + 1, result, pair[i].value);
}
Console.ReadKey();
}
// 打印消息
static void PrintfDBCMessage(IntPtr ptrMsg)
{
// 消息
ZDBC.DBCMessage msg = new ZDBC.DBCMessage();
msg = (ZDBC.DBCMessage)Marshal.PtrToStructure(ptrMsg, typeof(ZDBC.DBCMessage));
string str_name = new string(Encoding.ASCII.GetChars(msg.strName));
string result = str_name.Substring(0, str_name.IndexOf('\0'));
Console.WriteLine("0x{0:X} {1}", msg.nID, result);
// 信号
Console.WriteLine("\t{0,-27} {1,-4} {2,-5} {3,-5}", "信号名", "起始位", "长度", "原始值");
for (int i = 0; i < msg.nSignalCount; i++)
{
ZDBC.DBCSignal curSig = msg.vSignals[i];
str_name = new string(Encoding.ASCII.GetChars(curSig.strName));
result = str_name.Substring(0, str_name.IndexOf('\0'));
Console.WriteLine("\t{0,-30} {1,-7} {2,-5} {3,-8:X}", result, msg.vSignals[i].nStartBit, msg.vSignals[i].nLen, msg.vSignals[i].nRawvalue);
}
Console.WriteLine("");
}
// 初始化设备
static void InitDevice()
{
//int chn_idx = 0; // 通道号
uint ret; // 返回值
//打开设备
Program.deviceHandle = ZLGCAN.ZCAN_OpenDevice(41, 0, 0); // USBCANFD-200U 41
if (Program.deviceHandle == IntPtr.Zero)
{
Console.WriteLine("打开设备失败");
Console.ReadKey();
return;
}
else
Console.WriteLine("打开设备成功");
// 初始化通道
for (int i = 0; i < Program.max_chn; i++)
{
// 仲裁域波特率
string path = String.Format("{0}/canfd_abit_baud_rate", i);
ret = ZLGCAN.ZCAN_SetValue(deviceHandle, path, "500000"); // 500k
if (ret != 1)
{
Console.WriteLine("设置仲裁域波特率失败");
Console.ReadKey();
return;
}
// 数据域波特率
path = String.Format("{0}/canfd_dbit_baud_rate", i);
ret = ZLGCAN.ZCAN_SetValue(deviceHandle, path, "2000000"); // 2M
if (ret != 1)
{
Console.WriteLine("设置数据域波特率失败");
Console.ReadKey();
return;
}
// 终端电阻
path = String.Format("{0}/initenal_resistance", i);
string resistance = "1";//1-使能 0-禁能
ret = ZLGCAN.ZCAN_SetValue(deviceHandle, path, resistance);
if (ret != 1)
{
Console.WriteLine("设置终端电阻失败");
Console.ReadKey();
return;
}
// 初始化通道
ZLGCAN.ZCAN_CHANNEL_INIT_CONFIG InitConfig = new ZLGCAN.ZCAN_CHANNEL_INIT_CONFIG(); // 结构体
InitConfig.can_type = 1; // 1 - CANFD (USBCANFD 只能选择CANFD模式)
InitConfig.config.canfd.mode = 0; // 0 - 正常模式1 - 只听模式
IntPtr P2InitConfig = Marshal.AllocHGlobal(Marshal.SizeOf(InitConfig));
Marshal.StructureToPtr(InitConfig, P2InitConfig, true); // 转成指针
Program.channelHandles[i] = ZLGCAN.ZCAN_InitCAN(deviceHandle, (uint)i, P2InitConfig);
Marshal.FreeHGlobal(P2InitConfig); // 释放内存
if (Program.channelHandles[i] == IntPtr.Zero)
{
Console.WriteLine("初始化通道失败");
Console.ReadKey();
return;
}
Console.WriteLine("初始化通道成功");
//打开通道
ret = ZLGCAN.ZCAN_StartCAN(Program.channelHandles[i]);
if (ret != 1)
{
Console.WriteLine("打开通道失败");
Console.ReadKey();
return;
}
Console.WriteLine("打开通道成功");
// 创建一个接收线程
Thread workerThread = new Thread(ReceiveThread);
workerThread.IsBackground = true; // 设置为后台线程
workerThread.Start(Program.channelHandles[i]); // 启动线程
}
Thread.Sleep(1000);
// DBC发送
//Program.SendDBCMessageById(0x15D);
// 阻塞等待
Console.ReadKey();
Program.isRunning = false;
for (int i = 0; i < max_chn; i++)
{
// 关闭通道
ret = ZLGCAN.ZCAN_ResetCAN(Program.channelHandles[i]);
if (ret != 1)
{
Console.WriteLine("关闭通道失败");
Console.ReadKey();
return;
}
Console.WriteLine("关闭通道成功");
}
// 关闭设备
ret = ZLGCAN.ZCAN_CloseDevice(Program.deviceHandle);
if (ret != 1)
{
Console.WriteLine("关闭设备失败");
Console.ReadKey();
return;
}
Console.WriteLine("关闭设备成功");
}
// 接收线程 (有DBC解析)
static void ReceiveThread(object state)
{
IntPtr cur_chn = (IntPtr)state;
const int arraySize = 100;
IntPtr ptrCanData = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(ZLGCAN.ZCAN_Receive_Data)) * arraySize);
IntPtr ptrCanFDData = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(ZLGCAN.ZCAN_ReceiveFD_Data)) * arraySize);
IntPtr ptrMsg = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(ZDBC.DBCMessage)));
byte[] zero = new byte[Marshal.SizeOf(typeof(ZLGCAN.ZCAN_Receive_Data)) * arraySize];
while (Program.isRunning)
{
uint RecNum = ZLGCAN.ZCAN_GetReceiveNum(cur_chn, 0); //CAN
if (RecNum != 0)
{
// Marshal.Copy(zero, 0, ptrCanData, zero.Length); // 赋0
uint ReceiveNum = ZLGCAN.ZCAN_Receive(cur_chn, ptrCanData, arraySize, 10); // 接收报文
for (int i = 0; i < ReceiveNum; i++)
{
IntPtr curPtr = IntPtr.Add(ptrCanData, i * Marshal.SizeOf(typeof(ZLGCAN.ZCAN_Receive_Data)));
ZLGCAN.ZCAN_Receive_Data data = (ZLGCAN.ZCAN_Receive_Data)Marshal.PtrToStructure(curPtr, typeof(ZLGCAN.ZCAN_Receive_Data));
// DBC解析
if (true == ZDBC.ZDBC_Decode(Program.DBCHandle, ptrMsg, curPtr, 1, 0))
Program.PrintfDBCMessage(ptrMsg); // 打印解析
}
}
RecNum = ZLGCAN.ZCAN_GetReceiveNum(cur_chn, 1); // CANFD
if (RecNum != 0)
{
// Marshal.Copy(zero, 0, ptrCanData, zero.Length); // 赋0
uint ReceiveNum = ZLGCAN.ZCAN_ReceiveFD(cur_chn, ptrCanFDData, arraySize, 10); // 接收报文
for (int i = 0; i < ReceiveNum; i++)
{
IntPtr curPtr = IntPtr.Add(ptrCanFDData, i * Marshal.SizeOf(typeof(ZLGCAN.ZCAN_ReceiveFD_Data)));
ZLGCAN.ZCAN_ReceiveFD_Data data = (ZLGCAN.ZCAN_ReceiveFD_Data)Marshal.PtrToStructure(curPtr, typeof(ZLGCAN.ZCAN_ReceiveFD_Data));
// DBC解析
if (true == ZDBC.ZDBC_Decode(Program.DBCHandle, ptrMsg, curPtr, 1, 1))
{
Program.PrintfDBCMessage(ptrMsg); // 打印解析
}
}
}
}
Marshal.FreeHGlobal(ptrMsg);
Marshal.FreeHGlobal(ptrCanData);
}
// DBC发送
static void SendDBCMessageById(uint id)
{
// 从DBC文件获取对应ID的 DBC结构体
IntPtr ptrMsg = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(ZDBC.DBCMessage)));
if (ZDBC.ZDBC_GetMessageById(Program.DBCHandle, id, ptrMsg) == false) // 找不到对应id退出
{
Marshal.FreeHGlobal(ptrMsg);
return;
}
ZDBC.DBCMessage msg = (ZDBC.DBCMessage)Marshal.PtrToStructure(ptrMsg, typeof(ZDBC.DBCMessage));
//通过 ZDBC_CalcRawValue 设置信号值这里是根据实际的DBC信号设置的值作为示例设置该消息的第5个信号
/*
double actualVal = 12; // 物理值
IntPtr signalPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(ZDBC.DBCSignal)));
IntPtr actualValPtr = Marshal.AllocHGlobal(sizeof(double));
Marshal.StructureToPtr(msg.vSignals[5], signalPtr, true);
Marshal.StructureToPtr(actualVal, actualValPtr, true);
//计算原始值
ulong rawValue = ZDBC.ZDBC_CalcRawValue(signalPtr, actualValPtr); // 超出可信号值范围时会被修正
msg.vSignals[5].nRawvalue = rawValue;
Marshal.StructureToPtr(msg, ptrMsg, true);
*/
uint count = 1; // 初始化一个值
IntPtr ptrCount = Marshal.AllocHGlobal(sizeof(uint)); // 分配内存
Marshal.WriteInt32(ptrCount, (int)count); // 写入值
//CAN 根据消息类型选择can还是canfd
//Encode DBC_frame -> can_frame
IntPtr ptrCanFrame = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(ZLGCAN.can_frame)));
if (ZDBC.ZDBC_Encode(Program.DBCHandle, ptrCanFrame, ptrCount, ptrMsg, (int)0) == false) // Encode
{
Marshal.FreeHGlobal(ptrMsg);
Marshal.FreeHGlobal(ptrCount);
Marshal.FreeHGlobal(ptrCanFrame);
return;
}
// 构造发送结构体
ZLGCAN.can_frame can_f = (ZLGCAN.can_frame)Marshal.PtrToStructure(ptrCanFrame, typeof(ZLGCAN.can_frame));
ZLGCAN.ZCAN_Transmit_Data tran_data = new ZLGCAN.ZCAN_Transmit_Data();
tran_data.frame = can_f;
// 转换成 ZCAN_Transmit_Data并发送
IntPtr ptrTransmit = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(ZLGCAN.ZCAN_Transmit_Data)));
Marshal.StructureToPtr(tran_data, ptrTransmit, true);
if (count != ZLGCAN.ZCAN_Transmit(Program.channelHandles[0], ptrTransmit, count))
{
Console.WriteLine("发送CAN失败");
}
// CANFD
// Encode DBC_frame -> canfd_frame
IntPtr ptrCanFDFrame = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(ZLGCAN.canfd_frame)));
if (ZDBC.ZDBC_Encode(Program.DBCHandle, ptrCanFDFrame, ptrCount, ptrMsg, (int)1) == false) // Encode
{
Marshal.FreeHGlobal(ptrMsg);
Marshal.FreeHGlobal(ptrCount);
Marshal.FreeHGlobal(ptrCanFDFrame);
return;
}
// 构造发送结构体
ZLGCAN.canfd_frame canfd_f = (ZLGCAN.canfd_frame)Marshal.PtrToStructure(ptrCanFDFrame, typeof(ZLGCAN.canfd_frame));
ZLGCAN.ZCAN_TransmitFD_Data tranfd_data = new ZLGCAN.ZCAN_TransmitFD_Data();
tranfd_data.frame = canfd_f;
// 转换成 ZCAN_Transmit_Data并发送
IntPtr ptrTransmitFD = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(ZLGCAN.ZCAN_TransmitFD_Data)));
Marshal.StructureToPtr(tranfd_data, ptrTransmitFD, true);
if (count != ZLGCAN.ZCAN_TransmitFD(Program.channelHandles[0], ptrTransmitFD, count))
{
Console.WriteLine("发送CANFD失败");
}
Marshal.FreeHGlobal(ptrMsg);
Marshal.FreeHGlobal(ptrCount);
Marshal.FreeHGlobal(ptrCanFrame);
Marshal.FreeHGlobal(ptrCanFDFrame);
Marshal.FreeHGlobal(ptrTransmit);
//Marshal.FreeHGlobal(actualValPtr);
//Marshal.FreeHGlobal(signalPtr);
return;
}
}
}