参考资料
1.USBCAN(CANalyst-II 分析仪)产品说明书.pdf
2.接口函数库(二次开发库)使用说明书.pdf
3.USB 驱动的安装与卸载说明书.pdf
4.USB-CAN Tool 调试软件安装与使用说明书.pdf
5.插件 1:USB-CAN 总线适配器测试.pdf
13.附件 6:如何更好地使用二次开发函数.pdf
14.附件 7:常见问题及处理.pdf
CAN1通道为高速CAN,波特率可以通过软件配置为10Kbps-1Mbps,
CAN2通道当通过软件配置为高速CAN时,波特率配置范围为10Kbps-1Mbps,
CAN2通道当通过软件配置为低速容错CAN时,波特率配置范围为10Kbps-125Kbps
内部CAN发送缓冲区容量:20帧/通道(发送失败时自动重发),
CAN接收缓冲区容量: 2000帧/通道;
1数据类型:
1 Device Type................................设备类型
2 VCI_BOARD_INFO ....................设备铭牌【VCI_ReadBoardInfo】
VCI_BOARD_FIND....................搜索5设备【VCI_FindUsbDevice】
VCI_BOARD_FIND2....................搜索50设备【VCI_FindUsbDevice2】
3 VCI_CAN_OBJ ...........................单帧对象【缓冲区<=2000帧,发2001帧为1帧】
4 VCI_INIT_CONFIG .....................参数配置
设备性能参数:
循环缓冲区2000帧。【<=2000】
发2001帧,触发丢弃,实收1帧。【发2003帧,实收最后3帧】
【注】数据包转盘2000格。
设备类型:
//【1】 设备类型
public enum DeviceType : byte //【设备类型】USB{单路,双路},以太网{单路,双路}
{
DEV_USBCAN = 3, // USB【单路CAN】
DEV_USBCAN2 = 4,// USB【双路CAN】
VCI_USBCAN1 = 3,
VCI_USBCAN2 = 4,// 我买的属于这个(创芯科技CAN-Pro)【双路CAN】
VCI_USBCAN2A = 4,
VCI_USBCAN_E_U = 20,// 以太网单路CAN
VCI_USBCAN_2E_U = 21// 以太网双路CAN
}
//【2】 设备信息
public struct VCI_BOARD_INFO //主板铭牌 unsafe
{ // VCI_ReadBoardInfo【要先运行VCI_OpenDevice(4,0,0);】
public UInt16 hw_Version;//【0x0900】硬件版本,V9.00。
public UInt16 fw_Version;//【0x0341】固件版本,v3.41
public UInt16 dr_Version;//【0x0900】驱动版本,v9.00
public UInt16 in_Version;//【0x0905】接口版本,v9.05
public UInt16 irq_Num;// 【0x00】 保留参数。
public byte can_Num; // 【0x02】 表示有几路CAN通道。
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
public char[] str_Serial_Num;// 板卡序列号。【31F01031C93】
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)]
public char[] str_hw_Type;// 设备名称【USBCAN-II】
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public UInt16[] Reserved;// 系统保留。
}
// 发现5个设备
public struct VCI_BOARD_FIND // 搜索设备
{// VCI_FindUsbDevice【专用参数】
public UInt16 hw_Version;//【0x0900】 硬件版本,V9.00。 // 信息 设备【31F01031C93】v3.41
public UInt16 fw_Version;//【0x0341】 固件版本,v3.41,
public UInt16 dr_Version;//【0x0900】 驱动版本,v9.00
public UInt16 in_Version;//【0x0905】 接口版本,v9.05
public UInt16 irq_Num;// 【0x0000】 保留参数。
public byte can_Num;// 【0x02】 表示有几路CAN通道。
public byte Reserved;// 【0x00】 保留。
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public char[] str_Serial_Num;// 此板卡的id号。【43 41 4e 2d 31 43 39 33】"CAN-1C93"
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 9)]
public char[] str_hw_Type;// 设备类型。【55 53 42 43 41 4e 2d 49 49】"USBCAN-II"
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 7)]
public char[] Reserved1;// 【0x00】 保留。
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public char[] str_Usb_Serial;// 设备id【31 43 39 33】// "1C93"
}
// 最多50个设备
public struct VCI_BOARD_FIND2 //主板SN码 // 最多50个设备
{// VCI_FindUsbDevice2【专用参数】
public UInt16 hw_Version;//【0x0900】硬件版本,V9.00。
public UInt16 fw_Version;//【0x0341】固件版本,v3.41
public UInt16 dr_Version;//【0x0900】驱动版本,v9.00
public UInt16 in_Version;//【0x0905】接口版本,v9.05
public UInt16 irq_Num;// 【0x00】 保留参数。
public byte can_Num; // 【0x02】 表示有几路CAN通道。
public byte str_Serial_Num0;// 3 //板卡序列号。【31F01031C93】
public byte str_Serial_Num1;// 1
public byte str_Serial_Num2;// F
public byte str_Serial_Num3;// 0
public byte str_Serial_Num4;// 1
public byte str_Serial_Num5;// 0
public byte str_Serial_Num6;// 3
public byte str_Serial_Num7;// 1
public byte str_Serial_Num8;// C
public byte str_Serial_Num9;// 9
public byte str_Serial_NumA;// 3
public UInt16 Reserved;// 系统保留。
}
//【3】 单帧,数据帧对象
public unsafe struct VCI_CAN_OBJ //CAN单帧对象,
{
public UInt32 ID;// 帧ID。 【u32】帧id,数据格式为靠右对齐。 详情请参照: 《8.附件1: ID对齐方式.pdf》说明文档。
public UInt32 TimeStamp; //【u32】时间值。 时间标示从CAN卡上电开始计时,计时单位为0.1ms。
public Byte TimeFlag; //标志位,=1时TimeStamp有效
public Byte SendType; //发送类型。【0】正常发送(失败有重发20次)【1】单次发送
public Byte RemoteFlag; //远程帧标志。 【0】数据帧,【1】远程帧(数据段空,用于呼叫从站)。
public Byte ExternFlag; //扩展帧标志。 【0】标准帧(11位ID),【1】扩展帧(29位ID)。
public Byte DataLen; //有效字节 DLC (<=8),即CAN帧Data有几个字节。约束了后面Data[8]中有效字节数。
public fixed Byte Data[8]; //数据包,如DataLen定义为3,即Data[0]、 Data[1]、 Data[2]是有效的。
public fixed Byte Reserved[3];//系统保留。
}
public struct CAN_OBJ
{// 创芯用这个,【bug是读2000帧里只有一帧更新】
public UInt32 ID;// 帧ID。 【u32】帧id,标准帧11bit,扩展帧29bit。
public UInt32 TimeStamp; //【u32】时间值。从CAN卡上电开始计时,计时单位为0.1ms。
public Byte TimeFlag; // 标志位,【1】TimeStamp值有效
public Byte SendType; // 发送类型。【0】正常发送(失败有重发)【1】单次发送
public Byte RemoteFlag; // 远帧标志。【0】数据帧【1】远程帧(数据段空,用于呼叫从站)。
public Byte ExternFlag; // 扩展帧标志【0】标准帧(11位ID),【1】扩展帧(29位ID)。
public Byte DataLen; // 单帧有效字节 DLC (<=8)约束了后面Data[8]中有效字节数。
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public Byte[] Data; // 数据包,如DataLen为3,Data[0]、Data[1]、Data[2]是有效的。
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public Byte[] Reserved; // 保留。
}
//【4】配置参数
public struct VCI_INIT_CONFIG // 配置参数 设备【31F01031C93】v3.41
{
/// <summary>
/// bit高低全部匹配,此帧才可以被接收。D31对应帧id最高位
/// </summary>
public UInt32 AccCode;//bit【钥匙销子】匹配id,(右移21bit分析【32-11】)b31对应帧id最高位【左对齐】
// 相当于机械钥匙,凸起和凹槽必须匹配,才能开锁(接收)
// b31对应帧id最高位,所以11bit要左移21bit(//分析标准帧时右移21bit)
/// <summary>
/// bit高,使AccCode对应的bit失效,D31对应帧id最高位
/// </summary>
public UInt32 AccMask;// 【屏蔽码】使AccCode的某个bit功能失效。左对齐,bit31~bit21置1为屏蔽AccCode的bit匹配功能,
// 相当于机械钥匙的bit销位,是否失效(bit置1为失效)
// 。屏蔽码推荐设置为0xFFFFFFFF,即全部接收。
public UInt32 Reserved;// 保留。
public byte Filter; //滤帧方式 【1】接收所有帧。【2】只收标准帧,【3】只收扩展帧。
public byte Timing0; //波特率参数,具体配置,请查看二次开发库函数说明书。(1Mbps):《Timing0=0x00,Timing1=0x14》
public byte Timing1; //波特率 1MHz【T0=0x00,T1=0x14】 // 查手册
public byte Mode; //模式【0】收发模式,【1】只收,【2】自发自收模式(环回模式)。
}
2接口函数:
1 VCI_OpenDevice ........................打开设备
2 VCI_CloseDevice ........................关闭设备
3 VCI_InitCan .................................CAN通道【参数】初始化
4 VCI_ReadBoardInfo ....................读设备铭牌
5 VCI_GetReceiveNum ...................get缓冲区帧数
6 VCI_ClearBuffer ............................清空缓冲区
7 VCI_StartCAN ...............................CAN通道【打开】
8 VCI_ResetCAN .............................CAN通道复位
9 VCI_Transmit .................................CAN通道【发送】帧
10 VCI_Receive ................................CAN通道【接收】帧
11 VCI_FILTER_RECORD ................设置滤帧范围【只接收范围内的帧】
12 VCI_UsbDeviceReset ...................设备复位
13 VCI_FindUsbDevice2 ....................搜索设备【最多50个】
14 VCI_SetReference .........................设置滤帧表
#region 元始库方法
//方法
/*------------兼容ZLG的函数描述---------------------------------*/
[DllImport("controlcan.dll")]
public static extern Int32 VCI_OpenDevice(UInt32 DeviceType, UInt32 DeviceInd, UInt32 Reserved);
//返回值=1,表示操作成功;=0表示操作失败;=-1表示USB-CAN设备不存在或USB掉线。
//使能设备//(can通道不工作,只设备工作)
[DllImport("controlcan.dll")]
public static extern Int32 VCI_CloseDevice(UInt32 DeviceType, UInt32 DeviceInd);
//返回值=1,表示操作成功;=0表示操作失败;=-1表示USB-CAN设备不存在或USB掉线。
//关闭设备
[DllImport("controlcan.dll")]
public static extern Int32 VCI_InitCAN(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_INIT_CONFIG pInitConfig);
//初始化can通道(参数配置)b31对应帧id最高位【数据左对齐】,所以11bit要左移21bit
[DllImport("controlcan.dll")]
public static extern Int32 VCI_ReadBoardInfo(UInt32 DeviceType, UInt32 DeviceInd, ref VCI_BOARD_INFO pInfo);
//读取主板铭牌【需要先VCI_OpenDevice】
[DllImport("controlcan.dll")]
public static extern Int32 VCI_GetReceiveNum(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd);
//缓存区可用帧数(<=2000帧)
[DllImport("controlcan.dll")]
public static extern Int32 VCI_ClearBuffer(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd);
//清空缓存区
[DllImport("controlcan.dll")]
public static extern Int32 VCI_StartCAN(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd);
//CAN通道启动(启动can通道)
[DllImport("controlcan.dll")]
public static extern Int32 VCI_ResetCAN(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd);
//CAN通道复位
[DllImport("controlcan.dll")]
public static extern Int32 VCI_Transmit(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_CAN_OBJ pSend, UInt32 Length);
//返回实际发送的帧数,=-1表示USB-CAN设备不存在或USB掉线。
//Length 最大为1000,建议设为1,每次发送单帧,以提高发送效率
//CAN通道发送(单次<=10帧)
[DllImport("controlcan.dll")]
public static extern Int32 VCI_Receive(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_CAN_OBJ pReceive, UInt32 Len, Int32 WaitTime_ms);
//CAN通道接收(函数调用间隔至少应设置在5ms以上。)【Len为单次封顶帧数2500帧被读出
/*------------其他函数描述---------------------------------*/
[DllImport("controlcan.dll")]
public static extern Int32 VCI_ConnectDevice(UInt32 DevType, UInt32 DevIndex);
//设备连接
[DllImport("controlcan.dll")]
public static extern Int32 VCI_UsbDeviceReset(UInt32 DevType, UInt32 DevIndex, UInt32 Reserved);
//设备复位
[DllImport("controlcan.dll")]
public static extern Int32 VCI_FindUsbDevice(ref VCI_BOARD_INFO1 pInfo);
//返回前5个设备信息
//若计算机中插入多于5个适配器,则使用VCI_FindUsbDevice2函数,最大支持50个USB-CAN适配器。
[DllImport("controlcan.dll")]
public static extern UInt32 VCI_FindUsbDevice2(ref VCI_BOARD_FIND2 pInfo);
//如:VCI_BOARD_INFO pInfo[50]。
[DllImport("controlcan.dll")]
public static extern Int32 VCI_SetReference(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, UInt32 RefType, ref VCI_FILTER_RECORD pData);
//设置滤帧(设备类型,设备id,通道id,参数类型,参数包)【只监听某一范围的帧】
//RefType=1,添加滤帧表 指向VCI_FILTER_RECORD结构的指针
//RefType=2,启用滤帧表
//RefType=3,清除滤帧表。
/*------------函数描述结束---------------------------------*/
#endregion
3二次开发库文件【C#】
复制这个文件到Visual Studio 2022
using help;
//using Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.NetworkInformation;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
// 1先引用 CAN_namespace 用于参数类型 // using USB_CAN;
// 2再引用 help的方法
namespace CAN_namespace
{
#region 全局类型【声明】:通讯接口
/// <summary>
/// 全局类型:通讯接口
/// </summary>
public interface Iface_RTX // 开,关,收,发,轮询
{
/// <summary>
/// 连接
/// </summary>
/// <typeparam name="T">连接</typeparam>
/// <param name="a">ip地址</param>
/// <param name="b">端口</param>
/// <returns></returns>
bool connect<T>(T a, T b);// <string> "192.168.0.3","502"
/// <summary>
/// 断开
/// </summary>
/// <returns></returns>
bool Close();
/// <summary>
/// 只收
/// </summary>
/// <returns></returns>
int RXs(ref object obj);
//int RXs<T>(ref T obj);//测试
/// <summary>
/// 只发,格式148报文08123456781122334455667788
/// </summary>
/// <param name="cmd"></param>
/// <returns></returns>
int TXs(string cmd);
/// <summary>
/// 轮询
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="cmd"></param>
/// <param name="t"></param>
/// <returns></returns>
int sendAndReceive<T>(string cmd, ref T t);//万物皆文本
}
#endregion
#region 对象
public class Help_USB_ZHCX_CAN : Iface_RTX // ZHCX 珠海创芯科技有限公司
{//作者qq750273008 祁成 更新日期:2023.11.25
//===============================================
//[Browsable(true)] //可浏览
//[Category("自定义属性")] // 属性分栏
//[Description("属性的说明")] //
//================================================
#region 全局
//1申明委托》委托命令
public delegate void WT_GET_Data<T>(T ciA402);//↑ui显示发送命令
public delegate void WT_SET_Data(byte[] butes, string data);//↓下执行对象
#region CAN【数据类型】:全局:设备类型,主板信息,单帧信息,配置表
/*------------兼容ZLG的数据类型---------------------------------*/
//1.设备类型
/// <summary>
/// 设备类型(单路,双路,以太网CAN)
/// </summary>
public enum DeviceType : byte //设备类型【USB】{单路,双路},【以太网】{单路,双路}
{
DEV_USBCAN = 3, // USB单路CAN
DEV_USBCAN2 = 4,// USB双路CAN
VCI_USBCAN1 = 3,
VCI_USBCAN2 = 4,// 我买的属于这个(创芯科技CAN-Pro)
VCI_USBCAN2A = 4,
VCI_USBCAN_E_U = 20,// 以太网单路CAN
VCI_USBCAN_2E_U = 21// 以太网双路CAN
}
//2.ZLGCAN系列接口卡信息的数据类型。
/// <summary>
/// 主板设备【31F01031C93】v3.41 VCI_ReadBoardInfo【要先打开设备】
/// </summary>
public struct VCI_BOARD_INFO //主板信息 unsafe
{ // VCI_ReadBoardInfo【要先运行VCI_OpenDevice(4,0,0);】
public UInt16 hw_Version;//【0x0900】硬件版本,V9.00。
public UInt16 fw_Version;//【0x0341】固件版本,v3.41
public UInt16 dr_Version;//【0x0900】驱动版本,v9.00
public UInt16 in_Version;//【0x0905】接口版本,v9.05
public UInt16 irq_Num;// 【0x00】 保留参数。
public byte can_Num; // 【0x02】 表示有几路CAN通道。
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
public char[] str_Serial_Num;// 板卡序列号。【31F01031C93】
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)]
public char[] str_hw_Type;// 设备名称【USBCAN-II】
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public UInt16[] Reserved;// 系统保留。
}
public struct VCI_BOARD_FIND // 读取USB主板信息 设备【31F01031C93】v3.41
{// VCI_FindUsbDevice【专用参数】
public UInt16 hw_Version;//【0x0900】 硬件版本,V9.00。 //
public UInt16 fw_Version;//【0x0341】 固件版本,v3.41,
public UInt16 dr_Version;//【0x0900】 驱动版本,v9.00
public UInt16 in_Version;//【0x0905】 接口版本,v9.05
public UInt16 irq_Num;// 【0x0000】 保留参数。
public byte can_Num;// 【0x02】 表示有几路CAN通道。
public byte Reserved;// 【0x00】 保留。
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public char[] str_Serial_Num;// 此板卡的id号。【43 41 4e 2d 31 43 39 33】"CAN-1C93"
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 9)]
public char[] str_hw_Type;// 硬件类型“USBCAN V1.00”【55 53 42 43 41 4e 2d 49 49】"USBCAN-II"
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 7)]
public char[] Reserved1;// 【0x00】 保留。
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public char[] str_Usb_Serial;// 设备id【31 43 39 33】// "1C93"
}
public struct VCI_BOARD_FIND2 //主板信息
{// VCI_FindUsbDevice2【专用参数】
public UInt16 hw_Version;//【0x0900】硬件版本,V9.00。
public UInt16 fw_Version;//【0x0341】固件版本,v3.41
public UInt16 dr_Version;//【0x0900】驱动版本,v9.00
public UInt16 in_Version;//【0x0905】接口版本,v9.05
public UInt16 irq_Num;// 【0x00】 保留参数。
public byte can_Num; // 【0x02】 表示有几路CAN通道。
public byte str_Serial_Num0;// 3 //板卡序列号。【31F01031C93】
public byte str_Serial_Num1;// 1
public byte str_Serial_Num2;// F
public byte str_Serial_Num3;// 0
public byte str_Serial_Num4;// 1
public byte str_Serial_Num5;// 0
public byte str_Serial_Num6;// 3
public byte str_Serial_Num7;// 1
public byte str_Serial_Num8;// C
public byte str_Serial_Num9;// 9
public byte str_Serial_NumA;// 3
public UInt16 Reserved;// 系统保留。
}
//public fixed char str_Serial_Num[20];// 板卡序列号。【31F01031C93】
//public fixed char str_hw_Type[40];// 设备名称【USBCAN-II】
//public fixed UInt16 Reserved[8];// 系统保留。
//unsafe public struct VCI_FindUsbDevice2//使用不安全代码
//{
// public UInt16 hw_Version;
// public UInt16 fw_Version;
// public UInt16 dr_Version;
// public UInt16 in_Version;
// public UInt16 irq_Num;
// public byte can_Num;
// public fixed byte str_Serial_Num[20];
// public fixed byte str_hw_Type[40];
// public fixed byte Reserved[8];
//}
//unsafe public struct VCI_BOARD_INFO//使用不安全代码
//{
// public UInt16 hw_Version;
// public UInt16 fw_Version;
// public UInt16 dr_Version;
// public UInt16 in_Version;
// public UInt16 irq_Num;
// public byte can_Num;
// public fixed char str_Serial_Num[20]; // 【不能改】会影响到函数签名
// public fixed byte str_hw_Type[40];
// public fixed byte Reserved[8];
//}
//2-1.USB-CAN总线适配器板卡信息的数据类型1,该类型为VCI_FindUsbDevice函数的返回参数。
/// <summary>
/// USB-CAN设备主板信息,该类型为VCI_FindUsbDevice函数的返回参数。
/// </summary>
//public struct VCI_BOARD_FIND // 读取USB主板信息 设备【31F01031C93】v3.41
//{// VCI_FindUsbDevice
// public UInt16 hw_Version;//【0x0900】 硬件版本,0x0100表示V1.00。 //
// public UInt16 fw_Version;//【0x0341】 固件版本,v3.41,
// public UInt16 dr_Version;//【0x0900】 驱动版本,
// public UInt16 in_Version;//【0x0905】 接口版本,
// public UInt16 irq_Num;// 【0x0000】 保留参数。
// public byte can_Num;// 【0x02】 表示有几路CAN通道。
// public byte Reserved;// 【0x00】 保留。
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
// public char[] str_Serial_Num;// 此板卡的序列号。【43 41 4e 2d 31 43 39 33】"CAN-1C93"
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
// public char[] str_hw_Type;// 硬件类型“USBCAN V1.00”【55 53 42 43 41 4e 2d 49 49】"USBCAN-II"
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
// public char[] str_Usb_Serial;// 序列号【31 43 39 33】// "1C93"
//}
//3.定义CAN数据帧类型。
/// <summary>
/// CAN数据帧对象(每帧对象)
/// </summary>
public unsafe struct VCI_CAN_OBJ //CAN每帧对象,
{
public UInt32 ID;// 帧ID。 【u32】帧id,数据格式为靠右对齐。 详情请参照: 《8.附件1: ID对齐方式.pdf》说明文档。
public UInt32 TimeStamp; //【u32】时间值。 时间标示从CAN卡上电开始计时,计时单位为0.1ms。
public Byte TimeFlag; //标志位,=1时TimeStamp有效
public Byte SendType; //发送类型。【0】正常发送(失败有重发)【1】单次发送
public Byte RemoteFlag; //远程帧标志。 【0】数据帧,【1】远程帧(数据段空,用于呼叫从站)。
public Byte ExternFlag; //扩展帧标志。 【0】标准帧(11位ID),【1】扩展帧(29位ID)。
public Byte DataLen; //有效字节 DLC (<=8),即CAN帧Data有几个字节。约束了后面Data[8]中有效字节数。
public fixed Byte Data[8]; //数据包,如DataLen定义为3,即Data[0]、 Data[1]、 Data[2]是有效的。
public fixed Byte Reserved[3];//系统保留。
}
//public struct VCI_CAN_OBJ //CAN每帧对象,
//{// 创芯不能用这个,【bug是2000帧里只有一帧更新】
// public UInt32 ID;// 帧ID。 【u32】帧id,标准帧11bit,扩展帧29bit。
// public UInt32 TimeStamp; //【u32】时间值。从CAN卡上电开始计时,计时单位为0.1ms。
// public Byte TimeFlag; // 标志位,【1】TimeStamp值有效
// public Byte SendType; // 发送类型。【0】正常发送(失败有重发)【1】单次发送
// public Byte RemoteFlag; // 远帧标志。【0】数据帧【1】远程帧(数据段空,用于呼叫从站)。
// public Byte ExternFlag; // 扩展帧标志【0】标准帧(11位ID),【1】扩展帧(29位ID)。
// public Byte DataLen; // 单帧有效字节 DLC (<=8)约束了后面Data[8]中有效字节数。
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
// public Byte[] Data; // 数据包,如DataLen为3,Data[0]、Data[1]、Data[2]是有效的。
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
// public Byte[] Reserved; // 保留。
//}
public struct CAN_OBJ
{// 创芯不能用这个,【bug是2000帧里只有一帧更新】
public UInt32 ID;// 帧ID。 【u32】帧id,标准帧11bit,扩展帧29bit。
public UInt32 TimeStamp; //【u32】时间值。从CAN卡上电开始计时,计时单位为0.1ms。
public Byte TimeFlag; // 标志位,【1】TimeStamp值有效
public Byte SendType; // 发送类型。【0】正常发送(失败有重发)【1】单次发送
public Byte RemoteFlag; // 远帧标志。【0】数据帧【1】远程帧(数据段空,用于呼叫从站)。
public Byte ExternFlag; // 扩展帧标志【0】标准帧(11位ID),【1】扩展帧(29位ID)。
public Byte DataLen; // 单帧有效字节 DLC (<=8)约束了后面Data[8]中有效字节数。
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public Byte[] Data; // 数据包,如DataLen为3,Data[0]、Data[1]、Data[2]是有效的。
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public Byte[] Reserved; // 保留。
}
//————————————————
//版权声明:本文为CSDN博主「cfqq1989」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
//原文链接:https://blog.csdn.net/cfqq1989/article/details/134510613
//4.定义配置CAN的数据类型
/// <summary>
/// 初始化_配置(参数表)
/// </summary>
public struct VCI_INIT_CONFIG // 配置参数 设备【31F01031C93】v3.41
{
/// <summary>
/// bit高低全部匹配,此帧才可以被接收。D31对应帧id最高位
/// </summary>
public UInt32 AccCode;// bit全部匹配,此帧才可以被接收。否则不能接收。(//标准帧右移21bit分析)
// 相当于机械钥匙,凸起和凹槽必须匹配,才能开锁(接收)
// b31对应帧id最高位,所以11bit要左移21bit(//分析标准帧时右移21bit)
/// <summary>
/// bit高,使AccCode对应的bit失效,D31对应帧id最高位
/// </summary>
public UInt32 AccMask;// 屏蔽码。使AccCode的某个bit功能失效。左对齐,bit31~bit21置1为屏蔽AccCode的bit匹配功能,
// 相当于机械钥匙的bit销位,是否失效(bit置1为失效)
// 。屏蔽码推荐设置为0xFFFFFFFF,即全部接收。
public UInt32 Reserved;// 保留。
public byte Filter; // 【滤帧方式】【1】接收所有帧。【2】只收标准帧,【3】只收扩展帧。
public byte Timing0; //波特率参数,具体配置,请查看二次开发库函数说明书。(1Mbps):《Timing0=0x00,Timing1=0x14》
public byte Timing1; // 0x14 //波特率参数 1MHz(T0=0x00,T1=0x14)
public byte Mode; //模式【0】收发模式,【1】只收,【2】自测模式(环回模式)。
}
/*------------其他数据结构描述---------------------------------*/
/// <summary>
/// T 结构体用于装载更改 CANET_UDP 与 CANET_TCP 的目标 IP 和
///端口的必要信息。此结构体在 CANETE_UDP 与 CANET_TCP 中使用。
/// </summary>
public struct CHGDESIPANDPORT // 以太网can
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
public byte[] szpwd;
//更改目标 IP 和端口所需要的密码,长度小于 10,比如为“11223344”。
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
public byte[] szdesip;
//所要更改的目标 IP,比如为“192.168.0.111”。
public Int32 desport;
//所要更改的目标端口,比如为 4000。
public byte blisten;
//所要更改的工作模式,0 表示正常模式,1 表示只听模式。
}
public struct VCI_FILTER_RECORD //滤帧配置【满足条件的才接收】
{
UInt32 ExtFrame;// 过滤的帧类型【1】过滤扩展帧【0】过滤标准帧。
UInt32 Start;//起始帧ID
UInt32 End; //结束帧ID
}
/*------------数据结构描述完成---------------------------------*/
#endregion
#endregion
#region 字段
#region 原始库方法【接口函数】
//方法
/*------------兼容ZLG的函数描述---------------------------------*/
[DllImport("controlcan.dll")]
public static extern Int32 VCI_OpenDevice(UInt32 DeviceType, UInt32 DeviceInd, UInt32 Reserved);
//返回值=1,表示操作成功;=0表示操作失败;=-1表示USB-CAN设备不存在或USB掉线。
//使能设备//(can通道不工作,只设备工作)
[DllImport("controlcan.dll")]
public static extern Int32 VCI_CloseDevice(UInt32 DeviceType, UInt32 DeviceInd);
//返回值=1,表示操作成功;=0表示操作失败;=-1表示USB-CAN设备不存在或USB掉线。
//关闭设备
[DllImport("controlcan.dll")]
public static extern Int32 VCI_InitCAN(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_INIT_CONFIG pInitConfig);
//初始化can通道(参数配置)b31对应帧id最高位【数据左对齐】,所以11bit要左移21bit
[DllImport("controlcan.dll")]
public static extern Int32 VCI_ReadBoardInfo(UInt32 DeviceType, UInt32 DeviceInd, ref VCI_BOARD_INFO pInfo);
//读取主板信息【需要先VCI_OpenDevice】
[DllImport("controlcan.dll")]
public static extern Int32 VCI_GetReceiveNum(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd);
//缓存区可用帧数(<=2000帧)
[DllImport("controlcan.dll")]
public static extern Int32 VCI_ClearBuffer(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd);
//清空缓存区
[DllImport("controlcan.dll")]
public static extern Int32 VCI_StartCAN(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd);
//CAN通道启动(启动can通道)
[DllImport("controlcan.dll")]
public static extern Int32 VCI_ResetCAN(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd);
//CAN通道复位
[DllImport("controlcan.dll")]
public static extern Int32 VCI_Transmit(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_CAN_OBJ pSend, UInt32 Length);
//返回实际发送的帧数,=-1表示USB-CAN设备不存在或USB掉线。
//Length 最大为1000,建议设为1,每次发送单帧,以提高发送效率
//CAN通道发送(单次<=10帧)
[DllImport("controlcan.dll")]
public static extern Int32 VCI_Receive(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_CAN_OBJ pReceive, UInt32 Len, Int32 WaitTime_ms);
//CAN通道接收(函数调用间隔至少应设置在5ms以上。)【Len为单次封顶帧数2500帧被读出
/*------------其他函数描述---------------------------------*/
[DllImport("controlcan.dll")]
public static extern Int32 VCI_ConnectDevice(UInt32 DevType, UInt32 DevIndex);
//设备连接
[DllImport("controlcan.dll")]
public static extern Int32 VCI_UsbDeviceReset(UInt32 DevType, UInt32 DevIndex, UInt32 Reserved);
//设备复位
[DllImport("controlcan.dll")]
public static extern Int32 VCI_FindUsbDevice(ref VCI_BOARD_FIND pInfo);
//返回前5个设备信息
//若计算机中插入多于5个适配器,则使用VCI_FindUsbDevice2函数,最大支持50个USB-CAN适配器。
[DllImport("controlcan.dll")]
public static extern Int32 VCI_FindUsbDevice2(ref VCI_BOARD_FIND2 pInfo);
//如:VCI_BOARD_INFO pInfo[50]。
[DllImport("controlcan.dll")]
public static extern Int32 VCI_SetReference(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, UInt32 RefType, ref VCI_FILTER_RECORD pData);
//设置滤帧(设备类型,设备id,通道id,参数类型,参数包)【只监听某一范围的帧】
//RefType=1,添加滤帧表 指向VCI_FILTER_RECORD结构的指针
//RefType=2,启用滤帧表
//RefType=3,清除滤帧表。
/*------------函数描述结束---------------------------------*/
#endregion
//private CancellationTokenSource cts;//线程令牌
//private ManualResetEvent resetEvent = new ManualResetEvent(true);// 暂停业务
//=====================================================
Help_String help_String = new Help_String();//文本处理
#endregion
#region 属性
//public Iface_RTX help_rtx { get; set; }// 接口扩展
/// <summary>
/// ↑:byte包,文本
/// </summary>
//static public WT_GET_Data Wt_get;//↑event委托=》呼叫上ui层 让上层显示:发送命令
/// <summary>
/// ↓:byte包,文本
/// </summary>
static public WT_SET_Data Wt_set;//↓委托=》呼叫下位机执行
//设备类型
public uint VCI_USBCAN { get => 3; }// USB单路CAN
public uint VCI_USBCAN2 { get => 4; }// USB双路CAN
// E表示以太网
public uint VCI_USBCAN_E_U { get => 20; }// 以太网单路CAN
public uint VCI_USBCAN_2E_U { get => 21; }// 以太网双路CAN
public uint CAN1 { get => 0; } // 字段,内部使用
public uint CAN2 { get => 1; }
public byte STATUS_OK { get => 1; }
public byte STATUS_ERR { get => 0; }
/// <summary>
/// 发现设备 5个
/// </summary>
public VCI_BOARD_FIND[] get_FindUsbDevice
{
get
{
VCI_BOARD_FIND[] pInfo = new VCI_BOARD_FIND[5];
Int32 num = VCI_FindUsbDevice(ref pInfo[0]);// 查找5个设备
return pInfo;
}
}
/// <summary>
/// USB设备id:查找50个USB设备【31F01031C93】
/// </summary>
public VCI_BOARD_FIND2[] get_FindUsbDevice2
{
get
{
VCI_BOARD_FIND2[] pInfo = new VCI_BOARD_FIND2[50];
Int32 num = VCI_FindUsbDevice2(ref pInfo[0]);// 查找50个设备
return pInfo;
}
}
public VCI_BOARD_INFO get_ReadBoardInfo_USBCAN2
{
get
{
//Set_Open();
VCI_BOARD_INFO info = new VCI_BOARD_INFO();
VCI_ReadBoardInfo(VCI_USBCAN2, 0, ref info);
return info;
}
}
#endregion
#region 构造
#endregion
#region 事件
#endregion
#region APP方法【 开,关,收,发,复位
/// <summary>
/// 打开CAN:设备类型,硬件id,CAN通道id,参数表
/// </summary>
/// <param name="DeviceType"></param>
/// <param name="DeviceInd"></param>
/// <param name="CANInd"></param>
/// <param name="pInitConfig"></param>
/// <returns></returns>
public bool Set_Open()// 设备类型,设备id,通道,配置参数
{//打开CAN:设备类型,硬件索引,CAN通道索引,初始化参数,
UInt32 DeviceType = VCI_USBCAN2;// 设备类型4【USB双路CAN】
UInt32 DeviceInd = 0;// 设备ID
// 配置表
VCI_INIT_CONFIG config = new VCI_INIT_CONFIG();// 参数表【结构体】
// bit全部匹配,此帧才可以被接收。否则不能接收。【左对齐】(//标准帧右移21bit分析)
config.AccCode = 0;//bit【钥匙销子】匹配id,(右移21bit分析【32-11】)b31对应帧id最高位【左对齐】
config.AccMask = 0xffffffff;// 屏蔽码。使AccCode的某个bit功能失效。左对齐,【标准帧11bit】bit31~bit21置1为屏蔽AccCode的bit匹配功能,
config.Filter = 0; // 【滤帧方式】【1】接收所有帧。【2】只收标准帧,【3】只收扩展帧。
config.Timing0 = 0x00;//波特率 1MHz【T0=0x00,T1=0x14】 // 查手册
config.Timing1 = 0x14;
config.Mode = 0;//模式,0正常收发,1只收,2自发自收模式(环回模式)
//==========================================================
VCI_BOARD_FIND2 bord = new VCI_BOARD_FIND2();// 设备信息【结构体】
int num = VCI_FindUsbDevice2(ref bord);// 查找USB设备【31F01031C93】v3.41
if (num < 1)
{// 找不到设备
return false;
}
Int32 sta = 1;// 故障标记
// usb硬件
sta &= VCI_使能设备(DeviceType, DeviceInd);// 通电
sta &= VCI_初始化通道(DeviceType, DeviceInd, CAN1, ref config);// CAN 1
sta &= VCI_初始化通道(DeviceType, DeviceInd, CAN2, ref config);// CAN 2
sta &= VCI_CAN通道工作(DeviceType, DeviceInd, CAN1);// CAN 1 用于发送
sta &= VCI_CAN通道工作(DeviceType, DeviceInd, CAN2);// CAN 2 用于接收
return sta == STATUS_OK ? true : false; // 1完成,0故障
//================================
//VCI_INIT_CONFIG config = new VCI_INIT_CONFIG();// 参数表
//config.AccCode = 0;// bit全部匹配,此帧才可以被接收。否则不能接收。【左对齐】(//标准帧右移21bit分析)
//config.AccMask = 0xffffffff;//全部接收 // 屏蔽码。使AccCode的某个bit功能失效。左对齐,bit31~bit21置1为屏蔽AccCode的bit匹配功能,
//config.Filter = 0;//0或1接收所有帧。2标准帧滤波,3是扩展帧滤波。
//config.Timing0 = 0x00;//波特率参数 1MHz(T0=0x00,T1=0x14)
//config.Timing1 = 0x14;
//config.Mode = 0;//模式,0表示正常模式,1表示只听模式,2自测模式
//uint i = can.set_Open(Help_USB_CAN.VCI_USBCAN2, 0, 0, ref config);// CAN 1
//i &= can.set_Open(Help_USB_CAN.VCI_USBCAN2, 0, 1, ref config);// CAN 2
}
/// <summary>
/// 关闭CAN:设备类型,设备id
/// </summary>
/// <param name="DeviceType"></param>
/// <param name="DeviceInd"></param>
/// <returns></returns>
public Int32 Set_Close(UInt32 DeviceType, UInt32 DeviceInd)
{
Int32 sta = 1;// 故障标记
sta &= VCI_CloseDevice(DeviceType, DeviceInd);//设备关
sta &= VCI_UsbDeviceReset(DeviceType, DeviceInd, 0);// 设备复位
return sta;
}
public Int32 Set_ClearBuffer(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd)
{//设备类型,设备id,通道id
Int32 sta = 1;
sta &= VCI_ClearBuffer(DeviceType, DeviceInd, CANInd);
//sta&= VCI_ClearBuffer(DeviceType, DeviceInd, 1);// CAN2
return sta;
}
/// <summary>
/// 接收:设备类型,设备索引,CAN通道索引,参数表,最大帧数2000,超时时间
/// </summary>
/// <param name="DeviceType">设备类型</param>
/// <param name="DeviceInd">设备id</param>
/// <param name="CANInd">通道id</param>
/// <param name="pReceive">数据包</param>
/// <param name="Len">小于2500帧</param>
/// <param name="WaitTime">保留=0</param>
/// <returns></returns>
public Int32 get_Receive(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_CAN_OBJ pReceive, UInt32 Len, Int32 WaitTime)
{//VCI_CAN_OBJ pReceive 设置为数组,2000帧
// 设备类型,设备id,通道id,数据包,帧数,等待时间【保留0】
return VCI_Receive(DeviceType, DeviceInd, CANInd, ref pReceive, Len, WaitTime);
}
/// <summary>
/// 发送:设备类型,设备索引,CAN通道索引,参数表,要发帧数
/// </summary>
/// <param name="DeviceType">设备类型</param>
/// <param name="DeviceInd">设备id</param>
/// <param name="CANInd">通道id</param>
/// <param name="pSend">数据包</param>
/// <param name="Len">帧数小于1000</param>
/// <returns></returns>
public Int32 set_Send(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_CAN_OBJ pSend, UInt32 Len)
{
// 设备类型,设备id,通道id,数据包,帧数
return VCI_Transmit(DeviceType, DeviceInd, CANInd, ref pSend, Len);
}
public Int32 set_ResetCAN(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd)
{// 复位can通道
return VCI_ResetCAN(DeviceType, DeviceInd, CANInd);
}
/// <summary>
/// 获取CAN设备信息【需要先打开设备】
/// </summary>
/// <param name="DeviceType"></param>
/// <param name="DeviceInd"></param>
/// <param name="pInfo"></param>
/// <returns></returns>
public Int32 get_BoardInfo(UInt32 DeviceType, UInt32 DeviceInd, ref VCI_BOARD_INFO pInfo)
{//需要设备开启后,才能读取
return VCI_ReadBoardInfo(DeviceType, DeviceInd, ref pInfo);
//=======================================================
//VCI_BOARD_INFO info = new VCI_BOARD_INFO();
//uint i = can.get_Board(4, 0, ref info);
}
//==以下不再重要=======================================================================
//==以下不再重要========
/// <summary>
/// 使能硬件:设备类型,设备id。
/// </summary>
/// <param name="DeviceType">Help_USB_CAN.VCI_USBCAN2 = 4;双路CAN</param>
/// <param name="DeviceInd">第1个CAN通道是0</param>
/// <param name="Reserved">备用=0</param>
/// <returns></returns>
public Int32 VCI_使能设备(UInt32 DeviceType, UInt32 DeviceInd)
{// 相当于 插电
return VCI_OpenDevice(DeviceType, DeviceInd, 0x00);// 通电
}
/// <summary>
/// 初始化硬件:can设备类型,设备id,CAN通道id,VCI_INIT_CONFIG初始化参数结构体
/// </summary>
/// <param name="DeviceType">can设备类型</param>
/// <param name="DeviceInd">设备索引0</param>
/// <param name="CANInd">CAN通道索引0</param>
/// <param name="pInitConfig">VCI_INIT_CONFIG初始化参数结构</param>
/// <returns></returns>
public Int32 VCI_初始化通道(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_INIT_CONFIG pInitConfig)
{
return VCI_InitCAN(DeviceType, DeviceInd, CANInd, ref pInitConfig);
}
//设备类型。设备索引,CAN通道索引。初始化参数结构。
/// <summary>
/// CAN工作:设备类型,设备id,CAN通道id(返回【1】成功; 【0】失败; 【-1】设备不存在或USB掉线。)
/// </summary>
/// <param name="DeviceType"></param>
/// <param name="DeviceInd"></param>
/// <param name="CANInd"></param>
/// <returns></returns>
public Int32 VCI_CAN通道工作(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd)
{
return VCI_StartCAN(DeviceType, DeviceInd, CANInd);
}
/// <summary>
/// CAN发送:设备类型,设备索引,CAN通道索引,VCI_CAN_OBJ数组的首指针,(帧数量 最大为10)
/// </summary>
/// <param name="DeviceType"></param>
/// <param name="DeviceInd"></param>
/// <param name="CANInd"></param>
/// <param name="pSend"></param>
/// <param name="Len"></param>
/// <returns></returns>
public Int32 VCI_set发送(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_CAN_OBJ pSend, UInt32 Len)
{
return VCI_Transmit(DeviceType, DeviceInd, CANInd, ref pSend, Len);
}
/// <summary>
/// 缓冲区【小于等于2000帧】
/// </summary>
/// <param name="DeviceType"></param>
/// <param name="DeviceInd"></param>
/// <param name="CANInd"></param>
/// <returns></returns>
public Int32 VCI_get缓存区帧数(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd)
{
return VCI_GetReceiveNum(DeviceType, DeviceInd, CANInd);// 缓存区,帧数
}
/// <summary>
/// CAN接收:设备类型,设备id,CAN通道id,VCI_CAN_OBJ数组的首指针,本次接收的最大帧数 2500 ,等待时间ms
/// </summary>
/// <param name="DeviceType"></param>
/// <param name="DeviceInd"></param>
/// <param name="CANInd"></param>
/// <param name="pReceive"></param>
/// <param name="Len"></param>
/// <param name="WaitTime_ms"></param>
/// <returns></returns>
public Int32 VCI_get接收(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_CAN_OBJ pReceive, UInt32 Len, Int32 WaitTime_ms)
{
//VCI_CAN_OBJ[] obj = new VCI_CAN_OBJ[2000];
//uint i = can.VCI_get接收(4, 0, 1, ref obj[0], 2000, 0);
return VCI_Receive(DeviceType, DeviceInd, CANInd, ref pReceive, Len, WaitTime_ms);
}
#endregion
#region 后台方法
#endregion
#region 窗体移动
//private Point mouseOff;//鼠标移动位置变量
//private bool leftFlag;//标签是否为左键
//private void Frm_MouseDown(object sender, MouseEventArgs e)//鼠标按下
//{
// if (e.Button == MouseButtons.Left)
// {
// mouseOff = new Point(-e.X, -e.Y); //得到变量的值
// leftFlag = true; //点击左键按下时标注为true;
// }
//}
//private void Frm_MouseMove(object sender, MouseEventArgs e)//鼠标移动
//{
// if (leftFlag)
// {
// Point mouseSet = Control.MousePosition;
// mouseSet.Offset(mouseOff.X, mouseOff.Y); //设置移动后的位置
// //Location = mouseSet;//Form 窗体父类字段
// }
//}
//private void Frm_MouseUp(object sender, MouseEventArgs e)//鼠标松开
//{
// if (leftFlag)
// {
// leftFlag = false;//释放鼠标后标注为false;
// }
//}
#endregion
#region 错误
//try
//{
// byte[] buffer = Encoding.Default.GetBytes(data);//以计算机的编码发送
// serialPort.Write(buffer, 0, buffer.Length);// 开始发送
//}
//catch (Exception ex) { MessageBox.Show(ex.Message); }//显示错误
#endregion
#region 接口实现
public bool connect<T>(T a, T b)
{// 打开USB-CAN设备的can1通道
//throw new NotImplementedException();
UInt32 DeviceType = VCI_USBCAN2;// 设备类型4【USB双路CAN】
UInt32 DeviceInd = 0;// 设备ID
// 配置表
VCI_INIT_CONFIG config = new VCI_INIT_CONFIG();// 参数表【结构体】
// bit全部匹配,此帧才可以被接收。否则不能接收。【左对齐】(//标准帧右移21bit分析)
config.AccCode = 0;//bit【钥匙销子】匹配id,(右移21bit分析【32-11】)b31对应帧id最高位【左对齐】
config.AccMask = 0xffffffff;// 屏蔽码。使AccCode的某个bit功能失效。左对齐,【标准帧11bit】bit31~bit21置1为屏蔽AccCode的bit匹配功能,
config.Filter = 0; // 【滤帧方式】【1】接收所有帧。【2】只收标准帧,【3】只收扩展帧。
config.Timing0 = 0x00;//波特率 1MHz【T0=0x00,T1=0x14】 // 查手册
config.Timing1 = 0x14;
config.Mode = 0;//模式,0正常收发,1只收,2自发自收模式(环回模式)
//==========================================================
VCI_BOARD_FIND2[] bord = new VCI_BOARD_FIND2[50];// 设备信息【结构体】
int num = VCI_FindUsbDevice2(ref bord[0]);// 查找USB设备【31F01031C93】v3.41 VCI_FindUsbDevice2
if (num < 1)
{// 找不到设备
return false;
}
Int32 sta = 1;// 故障标记
// usb硬件
sta &= VCI_使能设备(DeviceType, DeviceInd);// 通电
sta &= VCI_初始化通道(DeviceType, DeviceInd, CAN1, ref config);// CAN 1
sta &= VCI_初始化通道(DeviceType, DeviceInd, CAN2, ref config);// CAN 2
sta &= VCI_CAN通道工作(DeviceType, DeviceInd, CAN1);// CAN 1 用于发送
sta &= VCI_CAN通道工作(DeviceType, DeviceInd, CAN2);// CAN 2 用于接收
return sta == STATUS_OK ? true : false; // 1完成,0故障
}
public bool Close()
{
//throw new NotImplementedException();
if (Set_Close(VCI_USBCAN2, 0) == STATUS_OK)
{
return true;
}
return false;
}
public Int32 RXs(ref object Obj)// 【<=2000帧】
{
//throw new NotImplementedException();
// 缓存区可用帧数=============================
//int i = VCI_GetReceiveNum(Help_USB_CAN.VCI_USBCAN2, CAN_inD, CAN1);// can1
VCI_CAN_OBJ[] obj = new VCI_CAN_OBJ[2000];// 创新科技CAN分析仪,单次最大缓存2000帧接收,间隔5ms以上
Int32 num = VCI_get接收(VCI_USBCAN2, 0, CAN2, ref obj[0], 2000, 100);// 注意 CAN1 通道
if (num > 0)// CAN1接收帧数
{
Obj = obj;
return num;
#region 取一帧 【1 4 8】
//=================================================
//byte[] bytes = new byte[13];
//bytes[0] = obj[0].DataLen; // 【1】有效字节
//uint id = obj[0].ID; // 帧 id【4】帧id
//bytes[1] = (byte)(id >> 24);
//bytes[2] = (byte)(id >> 16);
//bytes[3] = (byte)(id >> 8);
//bytes[4] = (byte)(id & 0xff);
//fixed (VCI_CAN_OBJ* p_obj = &obj[0])// 8字节 第一帧
//{
// bytes[5] = p_obj->Data[0];// 【8】包数据
// bytes[6] = p_obj->Data[1];
// bytes[7] = p_obj->Data[2];
// bytes[8] = p_obj->Data[3];
// bytes[9] = p_obj->Data[4];
// bytes[10] = p_obj->Data[5];
// bytes[11] = p_obj->Data[6];
// bytes[12] = p_obj->Data[7];
//}
//return bytes;
#endregion
}
return 0;
}
//public int RXs<T>(ref T obj)// 待测试
//{
// //throw new NotImplementedException();
// VCI_CAN_OBJ[] obj2 = new VCI_CAN_OBJ[2000];// 创新科技CAN分析仪最大支持2000帧接收,间隔5ms以上
// int num = VCI_get接收(4, 0, CAN1, ref obj2[0], 2000, 50);
// if (num > 0)// CAN1接收帧数
// {
// //obj = obj2.ToList<T>();
// return num;
// }
// return 0;
// }
public unsafe int TXs(string cmd)// "08 00000602 4064600000000000" // CAN_namespace.Iface_RTX.
{// 1 4 8 (DLC字节,帧id,Byte8数据包)
//throw new NotImplementedException();
cmd.Replace(" ", "");//头尾去除空白
byte[] buffercmd = help_String.StringsToHexBytes(cmd);//准备报文 //去除空白 StringsToHexBytes
VCI_CAN_OBJ[] buffer = new VCI_CAN_OBJ[1];
string id = cmd.Substring(2, 8);// 从站地址 00000602
// 4
buffer[0].ID = Convert.ToUInt32(id, 16);//从站id
// 重发功能 0开,1关
buffer[0].SendType = 0;//【0】正常,失败有重发 【1】只发单次,失败无重发
// 1
buffer[0].DataLen = buffercmd[0];//数据长度 DLC (<=8),即CAN帧Data有几个字节。约束了后面Data[8]中的有效字节。
// 8
//buffer[0].Data = new Byte[8];
buffer[0].Data[0] = buffercmd[5];// byte8
buffer[0].Data[1] = buffercmd[6];
buffer[0].Data[2] = buffercmd[7];
buffer[0].Data[3] = buffercmd[8];
buffer[0].Data[4] = buffercmd[9];
buffer[0].Data[5] = buffercmd[10];
buffer[0].Data[6] = buffercmd[11];
buffer[0].Data[7] = buffercmd[12];
// 上车
Int32 ret = VCI_set发送(VCI_USBCAN2, 0, CAN1, ref buffer[0], 1);// 库函数(发送TXs)
return ret;
}
public unsafe object sendAndReceive(string stringcmd)
{//"1803052000018705"
//"04000006014000200000000000"
//throw new NotImplementedException();
stringcmd.Replace(" ", "");//去除空白
byte[] buffercmd = help_String.StringsToHexBytes(stringcmd);//准备报文 //去除空白 StringsToHexBytes
VCI_CAN_OBJ[] buffer = new VCI_CAN_OBJ[10];
string id = stringcmd.Substring(7, 3);// 从站地址
buffer[0].ID = Convert.ToUInt32(id, 16);//从站id
buffer[0].SendType = 1;//发送帧类型。=0时为正常发送(发送失败会自动重发,重发超时时间为4秒, 4秒内没有发出则取消);=1时为单次发送
buffer[0].DataLen = buffercmd[0];//数据长度 DLC (<=8),即CAN帧Data有几个字节。约束了后面Data[8]中的有效字节。
buffer[0].Data[0] = buffercmd[5];
buffer[0].Data[1] = buffercmd[6];
buffer[0].Data[2] = buffercmd[7];
buffer[0].Data[3] = buffercmd[8];
buffer[0].Data[4] = buffercmd[9];
buffer[0].Data[5] = buffercmd[10];
buffer[0].Data[6] = buffercmd[11];
buffer[0].Data[7] = buffercmd[12];
Int32 ret = set_Send(VCI_USBCAN2, 0, 0, ref buffer[0], 1);// 发1帧
//byte[] buff = SendAndReceive(buffer, stringcmd);// 收发报文
//if (buff == null) throw new Exception("ACK 未应答。。。");
//if (buff != null)
//{
// string str = help_String.BytesToHexStrings(buff);
// return str;
//}
return null;// 发送后未接收
}
//public unsafe object RXs()// VCI_CAN_OBJ //CAN帧参数
//{
// //throw new NotImplementedException();
// // 缓存区可用帧数=============================
// uint i = VCI_GetReceiveNum(Help_USB_CAN.VCI_USBCAN2, 0, 0);// can1
// if (i > 0)// CAN1接收帧数
// {
// uint CAN1 = 0;
// VCI_CAN_OBJ[] obj = new VCI_CAN_OBJ[2000];// 创新科技CAN分析仪最大支持2000帧接收
// i = VCI_get接收(4, 0, CAN1, ref obj[0], 1, 0);// 注意 CAN1 通道
// #region 取一帧
// //=================================================
// byte[] bytes = new byte[13];
// bytes[0] = obj[0].DataLen; //obj[0].
// uint id = obj[0].ID; // 帧 id
// bytes[1] = (byte)(id >> 24);
// bytes[2] = (byte)(id >> 16);
// bytes[3] = (byte)(id >> 8);
// bytes[4] = (byte)(id & 0xff);
// fixed (VCI_CAN_OBJ* p_obj = &obj[0])// 8字节 第一帧
// {
// bytes[5] = p_obj->Data[0];
// bytes[6] = p_obj->Data[1];
// bytes[7] = p_obj->Data[2];
// bytes[8] = p_obj->Data[3];
// bytes[9] = p_obj->Data[4];
// bytes[10] = p_obj->Data[5];
// bytes[11] = p_obj->Data[6];
// bytes[12] = p_obj->Data[7];
// }
// return bytes;
// #endregion
// //return obj;
// }
// return null;
//}
//public unsafe object RXs()// VCI_CAN_OBJ //CAN帧参数
//{// CAN1 接收
// //throw new NotImplementedException();
// // 缓存区可用帧数=============================
// //Help_Delay.delayTime(0.005);// usb大概3~5ms
// int i = VCI_GetReceiveNum(Help_USB_CAN.VCI_USBCAN2, CAN_inD, CAN1);// can1
// if (i > 0)// CAN1接收帧数
// {
// VCI_CAN_OBJ[] obj = new VCI_CAN_OBJ[2000];// 创新科技CAN分析仪最大支持2000帧接收,间隔5ms以上
// i = VCI_get接收(4, 0, CAN1, ref obj[0], 2000, 50);// 注意 CAN1 通道
// #region 取一帧 【1 4 8】
// //=================================================
// //byte[] bytes = new byte[13];
// //bytes[0] = obj[0].DataLen; // 【1】有效字节
// //uint id = obj[0].ID; // 帧 id【4】帧id
// //bytes[1] = (byte)(id >> 24);
// //bytes[2] = (byte)(id >> 16);
// //bytes[3] = (byte)(id >> 8);
// //bytes[4] = (byte)(id & 0xff);
// //fixed (VCI_CAN_OBJ* p_obj = &obj[0])// 8字节 第一帧
// //{
// // bytes[5] = p_obj->Data[0];// 【8】包数据
// // bytes[6] = p_obj->Data[1];
// // bytes[7] = p_obj->Data[2];
// // bytes[8] = p_obj->Data[3];
// // bytes[9] = p_obj->Data[4];
// // bytes[10] = p_obj->Data[5];
// // bytes[11] = p_obj->Data[6];
// // bytes[12] = p_obj->Data[7];
// //}
// //return bytes;
// #endregion
// return obj;
// }
// return null;
//}
//public unsafe object TXs(string stringcmd)// "04000006014000200000000000"
//{//被CanOpen调用
// //throw new NotImplementedException();
// stringcmd.Replace(" ", "");//去除空白
// byte[] buffercmd = help_String.StringsToHexBytes(stringcmd);//准备报文 //去除空白 StringsToHexBytes
// VCI_CAN_OBJ[] buffer = new VCI_CAN_OBJ[10];
// string id = stringcmd.Substring(2, 8);// 从站地址 00000601
// buffer[0].ID = Convert.ToUInt32(id, 16);//从站id
// // 重发功能 0开,1关
// buffer[0].SendType = 0;//0(4秒内有重发) 1只发单次
// buffer[0].DataLen = buffercmd[0];//数据长度 DLC (<=8),即CAN帧Data有几个字节。约束了后面Data[8]中的有效字节。
// buffer[0].Data[0] = buffercmd[5];// byte8
// buffer[0].Data[1] = buffercmd[6];
// buffer[0].Data[2] = buffercmd[7];
// buffer[0].Data[3] = buffercmd[8];
// buffer[0].Data[4] = buffercmd[9];
// buffer[0].Data[5] = buffercmd[10];
// buffer[0].Data[6] = buffercmd[11];
// buffer[0].Data[7] = buffercmd[12];
// Int32 ret = VCI_set发送(Help_USB_CAN.VCI_USBCAN2, 0, CAN1, ref buffer[0], 1);// 库函数(发送TXs)
// return ret;
//}
//public int Close()
//{
// //throw new NotImplementedException();
// return (int)set_Close((UInt32)CAN设备类型.VCI_USBCAN2, CAN_inD);
//}
public int sendAndReceive<T>(string cmd, ref T t)
{
throw new NotImplementedException();
}
#endregion
}
#endregion
}
只用到【只收】【只发】功能
更新日期:23.11.18
using help;
//using Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.NetworkInformation;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
// 1先引用 CAN_namespace 用于参数类型 // using USB_CAN;
// 2再引用 help的方法
namespace CAN_namespace
{
#region 全局类型【声明】:通讯接口
/// <summary>
/// 全局类型:通讯接口
/// </summary>
public interface Iface_RTX // 开,关,收,发,轮询
{
/// <summary>
/// 连接
/// </summary>
/// <typeparam name="T">连接</typeparam>
/// <param name="a">ip地址</param>
/// <param name="b">端口</param>
/// <returns></returns>
bool connect<T>(T a, T b);
/// <summary>
/// 断开
/// </summary>
/// <returns></returns>
bool Close();
/// <summary>
/// 只收
/// </summary>
/// <returns></returns>
int RXs(ref object obj);
//int RXs<T>(ref T obj);//测试
/// <summary>
/// 只发,格式148报文
/// </summary>
/// <param name="cmd"></param>
/// <returns></returns>
bool TXs(string cmd);
/// <summary>
/// 轮询
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="cmd"></param>
/// <param name="t"></param>
/// <returns></returns>
bool sendAndReceive<T>(string cmd, ref T t);//万物皆文本
}
#endregion
#region 对象
public class Help_USB_CAN : Iface_RTX
{//作者qq750273008 祁成 更新日期:2023.11.13
//===============================================
//[Browsable(true)] //可浏览
//[Category("自定义属性")] // 属性分栏
//[Description("属性的说明")] //
//================================================
#region 全局
//1申明委托》委托命令
public delegate void WT_GET_Data<T>(T ciA402);//↑ui显示发送命令
public delegate void WT_SET_Data(byte[] butes, string data);//↓下执行对象
#region CAN参数类型:全局;【设备类型,主板信息,单帧信息,配置表
/*------------兼容ZLG的数据类型---------------------------------*/
//1.设备类型
/// <summary>
/// 设备类型(单路,双路,以太网CAN)
/// </summary>
public enum DeviceType : byte //设备类型【USB的【单路,双路】,以太网的【单路,双路】can】
{
DEV_USBCAN = 3, // USB单路CAN
DEV_USBCAN2 = 4,// USB双路CAN
VCI_USBCAN1 = 3,
VCI_USBCAN2 = 4,// 我买的属于这个(创新科技CAN-Pro)
VCI_USBCAN2A = 4,
VCI_USBCAN_E_U = 20,// 以太网单路CAN
VCI_USBCAN_2E_U = 21// 以太网双路CAN
}
//设备类型
public enum CAN设备类型 : int
{
DEV_USBCAN = 3, // USB单路CAN
DEV_USBCAN2 = 4,// USB双路CAN
VCI_USBCAN1 = 3,
VCI_USBCAN2 = 4,
VCI_USBCAN2A = 4,
VCI_USBCAN_E_U = 20,// 以太网单路CAN
VCI_USBCAN_2E_U = 21// 以太网双路CAN
}
//2.ZLGCAN系列接口卡信息的数据类型。
/// <summary>
/// 主板设备【31F01031C93】v3.41 VCI_ReadBoardInfo
/// </summary>
public struct VCI_BOARD_INFO //主板信息
{ // VCI_ReadBoardInfo【要先运行VCI_OpenDevice(4,0,0);】 VCI_FindUsbDevice2
public UInt16 hw_Version;//【0x0900】硬件版本,比如0x0100表示V1.00。
public UInt16 fw_Version;//【0x0341】固件版本,v3.41
public UInt16 dr_Version;//【0x0900】驱动版本,
public UInt16 in_Version;//【0x0905】接口版本,
public UInt16 irq_Num;// 【0x00】 保留参数。
public byte can_Num; // 【0x02】 表示有几路CAN通道。
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
public char[] str_Serial_Num;// 板卡序列号。【31F01031C93】
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)]
public char[] str_hw_Type;// 硬件类型【55 53 42 43 41 4e 2d 49 49】“USBCAN-II”
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public UInt16[] Reserved;// 系统保留。
}
//2-1.USB-CAN总线适配器板卡信息的数据类型1,该类型为VCI_FindUsbDevice函数的返回参数。
/// <summary>
/// USB-CAN设备主板信息,该类型为VCI_FindUsbDevice函数的返回参数。
/// </summary>
public struct VCI_BOARD_INFO1 // 读取USB主板信息 设备【31F01031C93】v3.41
{// VCI_FindUsbDevice
public UInt16 hw_Version;//【0x0900】 硬件版本,0x0100表示V1.00。 //
public UInt16 fw_Version;//【0x0341】 固件版本,v3.41,
public UInt16 dr_Version;//【0x0900】 驱动版本,
public UInt16 in_Version;//【0x0905】 接口版本,
public UInt16 irq_Num;// 【0x0000】 保留参数。
public byte can_Num;// 【0x02】 表示有几路CAN通道。
public byte Reserved;// 【0x00】 保留。
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public char[] str_Serial_Num;// 此板卡的序列号。【43 41 4e 2d 31 43 39 33】"CAN-1C93"
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public char[] str_hw_Type;// 硬件类型“USBCAN V1.00”【55 53 42 43 41 4e 2d 49 49】"USBCAN-II"
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public char[] str_Usb_Serial;// 序列号【31 43 39 33】// "1C93"
}
//3.定义CAN每帧的数据类型。
/// <summary>
/// CAN的每一帧详细信息(每帧对象)
/// </summary>
public unsafe struct VCI_CAN_OBJ //CAN每帧对象,
{
public uint ID;// 帧ID。 【u32】帧id,数据格式为靠右对齐。 详情请参照: 《8.附件1: ID对齐方式.pdf》说明文档。
public uint TimeStamp; //【u32】设备时间标识。 时间标示从CAN卡上电开始计时,计时单位为0.1ms。
public byte TimeFlag; //是否使用时间标识,=1时TimeStamp有效
public byte SendType; //发送类型。=0时为正常发送(重发超时时间为1秒,1秒内没有发出则取消);=1时为单次发送
public byte RemoteFlag; //是否远程帧标志。 =0时为数据帧, =1时为远程帧(数据段空)。
public byte ExternFlag; //是否扩展帧标志。 =0时为标准帧(11位ID), =1时为扩展帧(29位ID)。
public byte DataLen; //有效字节 DLC (<=8),即CAN帧Data有几个字节。约束了后面Data[8]中有效字节数。
public fixed byte Data[8]; //数据包,如DataLen定义为3,即Data[0]、 Data[1]、 Data[2]是有效的。
public fixed byte Reserved[3];//系统保留。
}
//4.定义配置CAN的数据类型
/// <summary>
/// USB-CAN2、配置表(参数表)
/// </summary>
public struct VCI_INIT_CONFIG // 配置参数 设备【31F01031C93】v3.41
{
public UInt32 AccCode;// bit全部匹配,此帧才可以被接收。否则不能接收。(//标准帧右移21bit分析)
// 相当于机械钥匙,凸起和凹槽必须匹配,才能开锁(接收)
// b31对应帧id最高位,所以11bit要左移21bit(//分析标准帧时右移21bit)
public UInt32 AccMask;// 屏蔽码。使AccCode的某个bit功能失效。左对齐,bit31~bit21置1为屏蔽AccCode的bit匹配功能,
// 相当于机械钥匙的bit销位,是否失效(bit置1为失效)
// 。屏蔽码推荐设置为0xFFFFFFFF,即全部接收。
public UInt32 Reserved;// 保留。
public byte Filter; // 1接收所有帧。2只收标准帧,3只收扩展帧。
public byte Timing0; //波特率参数,具体配置,请查看二次开发库函数说明书。(1Mbps):《Timing0=0x00,Timing1=0x14》
public byte Timing1; // 0x14 波特率参数 1MHz(T0=0x00,T1=0x14)
public byte Mode; //模式,0表示正常模式,1表示只听模式,2自测模式(环回模式)。
}
/*------------其他数据结构描述---------------------------------*/
public struct CHGDESIPANDPORT // 扩展端口?
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
public byte[] szpwd;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
public byte[] szdesip;
public Int32 desport;
public void Init()
{
szpwd = new byte[10];
szdesip = new byte[20];
}
}
public struct VCI_FILTER_RECORD //滤帧配置
{
UInt32 ExtFrame;// 过滤的帧类型【1】过滤扩展帧【0】过滤标准帧。
UInt32 Start;//起始帧ID
UInt32 End; //结束帧ID
}
/*------------数据结构描述完成---------------------------------*/
#endregion
#endregion
#region 字段
//private CancellationTokenSource cts;//线程令牌
//private ManualResetEvent resetEvent = new ManualResetEvent(true);// 暂停业务
//=====================================================
Help_String help_String = new Help_String();//文本处理
//设备类型
public const int VCI_USBCAN = 3;// USB单路CAN
public const int VCI_USBCAN2 = 4;// USB双路CAN
// E表示以太网
public const int VCI_USBCAN_E_U = 20;// 以太网单路CAN
public const int VCI_USBCAN_2E_U = 21;// 以太网双路CAN
const uint CAN1 = 0; // 字段,内部使用
const uint CAN2 = 1;
const byte STATUS_OK = 1;
const byte STATUS_ERR = 0;
#endregion
#region 属性
//public Iface_RTX help_rtx { get; set; }// 接口扩展
/// <summary>
/// ↑:byte包,文本
/// </summary>
//static public WT_GET_Data Wt_get;//↑event委托=》呼叫上ui层 让上层显示:发送命令
/// <summary>
/// ↓:byte包,文本
/// </summary>
static public WT_SET_Data Wt_set;//↓委托=》呼叫下位机执行
public VCI_BOARD_INFO1[] get_FindUsbDevice
{
get
{
VCI_BOARD_INFO1[] pInfo = new VCI_BOARD_INFO1[5];
Int32 num = VCI_FindUsbDevice(ref pInfo[0]);// 查找5个设备
return pInfo;
}
}
/// <summary>
/// USB设备id:查找50个USB设备【31F01031C93】
/// </summary>
public VCI_BOARD_INFO[] get_FindUsbDevice2
{
get
{
VCI_BOARD_INFO[] pInfo = new VCI_BOARD_INFO[50];
UInt32 num = VCI_FindUsbDevice2(ref pInfo[0]);// 查找50个设备
return pInfo;
}
}
public VCI_BOARD_INFO get_ReadBoardInfo
{
get
{
Set_Open();
VCI_BOARD_INFO info = new VCI_BOARD_INFO();
Int32 num = VCI_ReadBoardInfo(VCI_USBCAN2, 0, ref info);
return info;
}
}
#endregion
#region 构造
#endregion
#region 事件
#endregion
#region APP方法【 开,关,收,发,复位
/// <summary>
/// 打开CAN:设备类型,硬件id,CAN通道id,参数表
/// </summary>
/// <param name="DeviceType"></param>
/// <param name="DeviceInd"></param>
/// <param name="CANInd"></param>
/// <param name="pInitConfig"></param>
/// <returns></returns>
public Int32 Set_Open()//(DeviceType deviceType, uint deviceID,uint canX, VCI_INIT_CONFIG Config)// 设备类型,设备id,通道,配置参数
{//打开CAN:设备类型,硬件索引,CAN通道索引,初始化参数,
//查找CAN并打开can1通道
Int32 sta = 1;// 故障标记
UInt32 DeviceType = (int)VCI_USBCAN2;// 设备类型4【USB双路CAN】
UInt32 DeviceInd = 0;// 设备ID
VCI_BOARD_INFO1 bord = new VCI_BOARD_INFO1();// 设备信息【结构体】
int num = VCI_FindUsbDevice(ref bord);// 查找USB设备【31F01031C93】v3.41
if (num < 1)
{// 找不到设备
return 0;
}
// 配置表
VCI_INIT_CONFIG config = new VCI_INIT_CONFIG();// 参数表【结构体】
// bit全部匹配,此帧才可以被接收。否则不能接收。【左对齐】(//标准帧右移21bit分析)
config.AccCode = 0;//bit【钥匙销子】匹配id,(右移21bit分析【32-11】)b31对应帧id最高位【左对齐】
config.AccMask = 0xffffffff;// 屏蔽码。使AccCode的某个bit功能失效。左对齐,【标准帧11bit】bit31~bit21置1为屏蔽AccCode的bit匹配功能,
config.Filter = 1;//0或1接收所有帧。2只接收标准帧,3只接收扩展帧。
config.Timing0 = 0x00;//波特率 1MHz【T0=0x00,T1=0x14】 // 查手册
config.Timing1 = 0x14;
config.Mode = 0;//模式,0表示正常模式,1表示只听模式,2表示自发自收模式(环回模式)
// usb硬件
sta &= VCI_使能设备(DeviceType, DeviceInd);// 通电
sta &= VCI_初始化通道(DeviceType, DeviceInd, CAN1, ref config);// CAN 1
sta &= VCI_初始化通道(DeviceType, DeviceInd, CAN2, ref config);// CAN 2
sta &= VCI_CAN通道工作(DeviceType, DeviceInd, CAN1);// CAN 1
//sta &= VCI_CAN通道工作(DeviceType, DeviceInd, CAN2);// CAN 2
// 硬件信息【在VCI_OpenDevice运行后才可读设备信息】
VCI_BOARD_INFO pInfo = new VCI_BOARD_INFO();// 设备信息
Int32 num1 = VCI_ReadBoardInfo(4, 0, ref pInfo);// VCI_ReadBoardInfo VCI_FindUsbDevice
if (num1 >= 1)
{
string 序列号 = new string(pInfo.str_Serial_Num);
string 设备名称 = new string(pInfo.str_hw_Type);
}
return (Int32)(sta == 1 ? 1 : 0);// 1完成,0故障
//================================
//VCI_INIT_CONFIG config = new VCI_INIT_CONFIG();// 参数表
//config.AccCode = 0;// bit全部匹配,此帧才可以被接收。否则不能接收。【左对齐】(//标准帧右移21bit分析)
//config.AccMask = 0xffffffff;//全部接收 // 屏蔽码。使AccCode的某个bit功能失效。左对齐,bit31~bit21置1为屏蔽AccCode的bit匹配功能,
//config.Filter = 0;//0或1接收所有帧。2标准帧滤波,3是扩展帧滤波。
//config.Timing0 = 0x00;//波特率参数 1MHz(T0=0x00,T1=0x14)
//config.Timing1 = 0x14;
//config.Mode = 0;//模式,0表示正常模式,1表示只听模式,2自测模式
//uint i = can.set_Open(Help_USB_CAN.VCI_USBCAN2, 0, 0, ref config);// CAN 1
//i &= can.set_Open(Help_USB_CAN.VCI_USBCAN2, 0, 1, ref config);// CAN 2
}
/// <summary>
/// 关闭CAN:设备类型,设备id
/// </summary>
/// <param name="DeviceType"></param>
/// <param name="DeviceInd"></param>
/// <returns></returns>
public Int32 Set_Close(UInt32 DeviceType, UInt32 DeviceInd)// UInt32 DeviceType, UInt32 DeviceInd
{
Int32 sta = 1;// 故障标记
sta &= VCI_CloseDevice(DeviceType, DeviceInd);//设备关
sta &= VCI_UsbDeviceReset(DeviceType, DeviceInd, 0);// 设备复位
return sta;
}
public Int32 Set_ClearBuffer(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd)
{//设备类型,设备id,通道id
Int32 sta = 1;
sta &= VCI_ClearBuffer(DeviceType, DeviceInd, CANInd);
//sta&= VCI_ClearBuffer(DeviceType, DeviceInd, 1);// CAN2
return sta;
}
/// <summary>
/// 接收:设备类型,设备索引,CAN通道索引,参数表,最大帧数2000,超时时间
/// </summary>
/// <param name="DeviceType">设备类型</param>
/// <param name="DeviceInd">设备id</param>
/// <param name="CANInd">通道id</param>
/// <param name="pReceive">数据包</param>
/// <param name="Len">小于2500帧</param>
/// <param name="WaitTime">保留=0</param>
/// <returns></returns>
public Int32 get_Receive(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_CAN_OBJ pReceive, UInt32 Len, Int32 WaitTime)
{//VCI_CAN_OBJ pReceive 设置为数组,2000帧
// 设备类型,设备id,通道id,数据包,帧数,等待时间【保留0】
return VCI_Receive(DeviceType, DeviceInd, CANInd, ref pReceive, Len, WaitTime);
}
/// <summary>
/// 发送:设备类型,设备索引,CAN通道索引,参数表,要发帧数
/// </summary>
/// <param name="DeviceType">设备类型</param>
/// <param name="DeviceInd">设备id</param>
/// <param name="CANInd">通道id</param>
/// <param name="pSend">数据包</param>
/// <param name="Len">帧数小于1000</param>
/// <returns></returns>
public Int32 set_Send(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_CAN_OBJ pSend, UInt32 Len)
{
// 设备类型,设备id,通道id,数据包,帧数
return VCI_Transmit(DeviceType, DeviceInd, CANInd, ref pSend, Len);
}
public Int32 set_ResetCAN(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd)
{// 复位can通道
return VCI_ResetCAN(DeviceType, DeviceInd, CANInd);
}
/// <summary>
/// 获取CAN设备信息【需要先打开设备】
/// </summary>
/// <param name="DeviceType"></param>
/// <param name="DeviceInd"></param>
/// <param name="pInfo"></param>
/// <returns></returns>
public Int32 get_BoardInfo(UInt32 DeviceType, UInt32 DeviceInd, ref VCI_BOARD_INFO pInfo)
{//需要设备开启后,才能读取
return VCI_ReadBoardInfo(DeviceType, DeviceInd, ref pInfo);
//=======================================================
//VCI_BOARD_INFO info = new VCI_BOARD_INFO();
//uint i = can.get_Board(4, 0, ref info);
}
//==以下不再重要=======================================================================
//==以下不再重要========
/// <summary>
/// 使能硬件:设备类型,设备id。
/// </summary>
/// <param name="DeviceType">Help_USB_CAN.VCI_USBCAN2 = 4;双路CAN</param>
/// <param name="DeviceInd">第1个CAN通道是0</param>
/// <param name="Reserved">备用=0</param>
/// <returns></returns>
public Int32 VCI_使能设备(UInt32 DeviceType, UInt32 DeviceInd)
{// 相当于 插电
return VCI_OpenDevice(DeviceType, DeviceInd, 0x00);// 通电
}
/// <summary>
/// 初始化硬件:can设备类型,设备id,CAN通道id,VCI_INIT_CONFIG初始化参数结构体
/// </summary>
/// <param name="DeviceType">can设备类型</param>
/// <param name="DeviceInd">设备索引0</param>
/// <param name="CANInd">CAN通道索引0</param>
/// <param name="pInitConfig">VCI_INIT_CONFIG初始化参数结构</param>
/// <returns></returns>
public Int32 VCI_初始化通道(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_INIT_CONFIG pInitConfig)
{
return VCI_InitCAN(DeviceType, DeviceInd, CANInd, ref pInitConfig);
}
//设备类型。设备索引,CAN通道索引。初始化参数结构。
/// <summary>
/// CAN工作:设备类型,设备id,CAN通道id(返回【1】成功; 【0】失败; 【-1】设备不存在或USB掉线。)
/// </summary>
/// <param name="DeviceType"></param>
/// <param name="DeviceInd"></param>
/// <param name="CANInd"></param>
/// <returns></returns>
public Int32 VCI_CAN通道工作(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd)
{
return VCI_StartCAN(DeviceType, DeviceInd, CANInd);
}
/// <summary>
/// CAN发送:设备类型,设备索引,CAN通道索引,VCI_CAN_OBJ数组的首指针,(帧数量 最大为10)
/// </summary>
/// <param name="DeviceType"></param>
/// <param name="DeviceInd"></param>
/// <param name="CANInd"></param>
/// <param name="pSend"></param>
/// <param name="Len"></param>
/// <returns></returns>
public Int32 VCI_set发送(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_CAN_OBJ pSend, UInt32 Len)
{
return VCI_Transmit(DeviceType, DeviceInd, CANInd, ref pSend, Len);
}
public Int32 VCI_get缓存区帧数(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd)
{
return VCI_GetReceiveNum(DeviceType, DeviceInd, CANInd);// 缓存区,帧数
}
/// <summary>
/// CAN接收:设备类型,设备id,CAN通道id,VCI_CAN_OBJ数组的首指针,本次接收的最大帧数 2500 ,超时时间ms
/// </summary>
/// <param name="DeviceType"></param>
/// <param name="DeviceInd"></param>
/// <param name="CANInd"></param>
/// <param name="pReceive"></param>
/// <param name="Len"></param>
/// <param name="WaitTime"></param>
/// <returns></returns>
public Int32 VCI_get接收(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_CAN_OBJ pReceive, UInt32 Len, Int32 WaitTime)
{
//VCI_CAN_OBJ[] obj = new VCI_CAN_OBJ[2000];
//uint i = can.VCI_get接收(4, 0, 1, ref obj[0], 2000, 0);
return VCI_Receive(DeviceType, DeviceInd, CANInd, ref pReceive, Len, WaitTime);
}
#endregion
#region 后台方法
#region 元始库方法
//方法
/*------------兼容ZLG的函数描述---------------------------------*/
[DllImport("controlcan.dll")]
public static extern Int32 VCI_OpenDevice(UInt32 DeviceType, UInt32 DeviceInd, UInt32 Reserved);
//返回值=1,表示操作成功;=0表示操作失败;=-1表示USB-CAN设备不存在或USB掉线。
//使能设备//(can通道不工作,只设备工作)
[DllImport("controlcan.dll")]
public static extern Int32 VCI_CloseDevice(UInt32 DeviceType, UInt32 DeviceInd);
//返回值=1,表示操作成功;=0表示操作失败;=-1表示USB-CAN设备不存在或USB掉线。
//关闭设备
[DllImport("controlcan.dll")]
public static extern Int32 VCI_InitCAN(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_INIT_CONFIG pInitConfig);
//初始化can通道(参数配置)b31对应帧id最高位,所以11bit要左移21bit
[DllImport("controlcan.dll")]
public static extern Int32 VCI_ReadBoardInfo(UInt32 DeviceType, UInt32 DeviceInd, ref VCI_BOARD_INFO pInfo);
//读取主板信息【需要先VCI_OpenDevice】
[DllImport("controlcan.dll")]
public static extern Int32 VCI_GetReceiveNum(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd);
//缓存区可用帧数(<=2000帧)
[DllImport("controlcan.dll")]
public static extern Int32 VCI_ClearBuffer(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd);
//清空缓存区
[DllImport("controlcan.dll")]
public static extern Int32 VCI_StartCAN(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd);
//CAN通道启动(启动can通道)
[DllImport("controlcan.dll")]
public static extern Int32 VCI_ResetCAN(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd);
//CAN通道复位
[DllImport("controlcan.dll")]
public static extern Int32 VCI_Transmit(UInt32 DeviceType,UInt32 DeviceInd, UInt32 CANInd, ref VCI_CAN_OBJ pSend,UInt32 Length);
//返回实际发送的帧数,=-1表示USB-CAN设备不存在或USB掉线。
//Length 最大为1000,建议设为1,每次发送单帧,以提高发送效率
//CAN通道发送(单次<=10帧)
[DllImport("controlcan.dll")]
public static extern Int32 VCI_Receive(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_CAN_OBJ pReceive, UInt32 Len, Int32 WaitTime);
//CAN通道接收(函数调用间隔至少应设置在5ms以上。)【Len为单次封顶帧数2500帧被读出
/*------------其他函数描述---------------------------------*/
[DllImport("controlcan.dll")]
public static extern Int32 VCI_ConnectDevice(UInt32 DevType, UInt32 DevIndex);
//设备连接
[DllImport("controlcan.dll")]
public static extern Int32 VCI_UsbDeviceReset(UInt32 DevType, UInt32 DevIndex, UInt32 Reserved);
//设备复位
[DllImport("controlcan.dll")]
public static extern Int32 VCI_FindUsbDevice(ref VCI_BOARD_INFO1 pInfo);
//返回前5个设备信息
//若计算机中插入多于5个适配器,则使用VCI_FindUsbDevice2函数,最大支持50个USB-CAN适配器。
[DllImport("controlcan.dll")]
public static extern UInt32 VCI_FindUsbDevice2 (ref VCI_BOARD_INFO pInfo);
//如:VCI_BOARD_INFO pInfo[50]。
[DllImport("controlcan.dll")]
public static extern Int32 VCI_SetReference(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, UInt32 RefType, ref VCI_FILTER_RECORD pData);
//设置滤帧(设备类型,设备id,通道id,参数类型,参数包)【只监听某一范围的帧】
//RefType=1,添加滤帧表 指向VCI_FILTER_RECORD结构的指针
//RefType=2,启用滤帧表
//RefType=3,清除滤帧表。
/*------------函数描述结束---------------------------------*/
#endregion
#endregion
#region 窗体移动
//private Point mouseOff;//鼠标移动位置变量
//private bool leftFlag;//标签是否为左键
//private void Frm_MouseDown(object sender, MouseEventArgs e)//鼠标按下
//{
// if (e.Button == MouseButtons.Left)
// {
// mouseOff = new Point(-e.X, -e.Y); //得到变量的值
// leftFlag = true; //点击左键按下时标注为true;
// }
//}
//private void Frm_MouseMove(object sender, MouseEventArgs e)//鼠标移动
//{
// if (leftFlag)
// {
// Point mouseSet = Control.MousePosition;
// mouseSet.Offset(mouseOff.X, mouseOff.Y); //设置移动后的位置
// //Location = mouseSet;//Form 窗体父类字段
// }
//}
//private void Frm_MouseUp(object sender, MouseEventArgs e)//鼠标松开
//{
// if (leftFlag)
// {
// leftFlag = false;//释放鼠标后标注为false;
// }
//}
#endregion
#region 错误
//try
//{
// byte[] buffer = Encoding.Default.GetBytes(data);//以计算机的编码发送
// serialPort.Write(buffer, 0, buffer.Length);// 开始发送
//}
//catch (Exception ex) { MessageBox.Show(ex.Message); }//显示错误
#endregion
#region 接口实现
public bool connect<T>(T a, T b)
{// 打开USB-CAN设备的can1通道
//throw new NotImplementedException();
int sta = Set_Open();
return sta == STATUS_OK ? true : false; // 1完成,0故障
}
bool Iface_RTX.Close()
{
//throw new NotImplementedException();
if (Set_Close(VCI_USBCAN2, 0) == 1)
{
return true;
}
return false;
}
public Int32 RXs(ref object Obj)
{
//throw new NotImplementedException();
// 缓存区可用帧数=============================
//int i = VCI_GetReceiveNum(Help_USB_CAN.VCI_USBCAN2, CAN_inD, CAN1);// can1
VCI_CAN_OBJ[] obj = new VCI_CAN_OBJ[2500];// 创新科技CAN分析仪,单次最大缓存2500帧接收,间隔5ms以上
Int32 num = VCI_get接收(VCI_USBCAN2, 0, CAN1, ref obj[0], 2500, 0);// 注意 CAN1 通道
if (num > 0)// CAN1接收帧数
{
Obj = obj;
return num;
#region 取一帧 【1 4 8】
//=================================================
//byte[] bytes = new byte[13];
//bytes[0] = obj[0].DataLen; // 【1】有效字节
//uint id = obj[0].ID; // 帧 id【4】帧id
//bytes[1] = (byte)(id >> 24);
//bytes[2] = (byte)(id >> 16);
//bytes[3] = (byte)(id >> 8);
//bytes[4] = (byte)(id & 0xff);
//fixed (VCI_CAN_OBJ* p_obj = &obj[0])// 8字节 第一帧
//{
// bytes[5] = p_obj->Data[0];// 【8】包数据
// bytes[6] = p_obj->Data[1];
// bytes[7] = p_obj->Data[2];
// bytes[8] = p_obj->Data[3];
// bytes[9] = p_obj->Data[4];
// bytes[10] = p_obj->Data[5];
// bytes[11] = p_obj->Data[6];
// bytes[12] = p_obj->Data[7];
//}
//return bytes;
#endregion
}
return 0;
}
//public int RXs<T>(ref T obj)// 待测试
//{
// //throw new NotImplementedException();
// VCI_CAN_OBJ[] obj2 = new VCI_CAN_OBJ[2000];// 创新科技CAN分析仪最大支持2000帧接收,间隔5ms以上
// int num = VCI_get接收(4, 0, CAN1, ref obj2[0], 2000, 50);
// if (num > 0)// CAN1接收帧数
// {
// //obj = obj2.ToList<T>();
// return num;
// }
// return 0;
// }
public unsafe bool TXs(string cmd)// "08 00000602 4064600000000000" // CAN_namespace.Iface_RTX.
{// 1 4 8 (DLC字节,帧id,Byte8数据包)
//throw new NotImplementedException();
cmd.Replace(" ", "");//去除空白
byte[] buffercmd = help_String.StringsToHexBytes(cmd);//准备报文 //去除空白 StringsToHexBytes
VCI_CAN_OBJ[] buffer = new VCI_CAN_OBJ[10];
string id = cmd.Substring(2, 8);// 从站地址 00000602
// 4
buffer[0].ID = Convert.ToUInt32(id, 16);//从站id
// 重发功能 0开,1关
buffer[0].SendType = 0;//【0】正常,失败有重发 【1】只发单次,失败无重发
// 1
buffer[0].DataLen = buffercmd[0];//数据长度 DLC (<=8),即CAN帧Data有几个字节。约束了后面Data[8]中的有效字节。
// 8
buffer[0].Data[0] = buffercmd[5];// byte8
buffer[0].Data[1] = buffercmd[6];
buffer[0].Data[2] = buffercmd[7];
buffer[0].Data[3] = buffercmd[8];
buffer[0].Data[4] = buffercmd[9];
buffer[0].Data[5] = buffercmd[10];
buffer[0].Data[6] = buffercmd[11];
buffer[0].Data[7] = buffercmd[12];
// 上车
Int32 ret = VCI_set发送(Help_USB_CAN.VCI_USBCAN2, 0, CAN1, ref buffer[0], 1);// 库函数(发送TXs)
if (ret == 1) return true;
return false;
}
public unsafe object sendAndReceive(string stringcmd)
{//"1803052000018705"
//"04000006014000200000000000"
//throw new NotImplementedException();
stringcmd.Replace(" ", "");//去除空白
byte[] buffercmd = help_String.StringsToHexBytes(stringcmd);//准备报文 //去除空白 StringsToHexBytes
VCI_CAN_OBJ[] buffer = new VCI_CAN_OBJ[10];
string id = stringcmd.Substring(7, 3);// 从站地址
buffer[0].ID = Convert.ToUInt32(id, 16);//从站id
buffer[0].SendType = 1;//发送帧类型。=0时为正常发送(发送失败会自动重发,重发超时时间为4秒, 4秒内没有发出则取消);=1时为单次发送
buffer[0].DataLen = buffercmd[0];//数据长度 DLC (<=8),即CAN帧Data有几个字节。约束了后面Data[8]中的有效字节。
buffer[0].Data[0] = buffercmd[5];
buffer[0].Data[1] = buffercmd[6];
buffer[0].Data[2] = buffercmd[7];
buffer[0].Data[3] = buffercmd[8];
buffer[0].Data[4] = buffercmd[9];
buffer[0].Data[5] = buffercmd[10];
buffer[0].Data[6] = buffercmd[11];
buffer[0].Data[7] = buffercmd[12];
Int32 ret = set_Send(VCI_USBCAN2, 0, 0, ref buffer[0], 1);// 发1帧
//byte[] buff = SendAndReceive(buffer, stringcmd);// 收发报文
//if (buff == null) throw new Exception("ACK 未应答。。。");
//if (buff != null)
//{
// string str = help_String.BytesToHexStrings(buff);
// return str;
//}
return null;// 发送后未接收
}
//public unsafe object RXs()// VCI_CAN_OBJ //CAN帧参数
//{
// //throw new NotImplementedException();
// // 缓存区可用帧数=============================
// uint i = VCI_GetReceiveNum(Help_USB_CAN.VCI_USBCAN2, 0, 0);// can1
// if (i > 0)// CAN1接收帧数
// {
// uint CAN1 = 0;
// VCI_CAN_OBJ[] obj = new VCI_CAN_OBJ[2000];// 创新科技CAN分析仪最大支持2000帧接收
// i = VCI_get接收(4, 0, CAN1, ref obj[0], 1, 0);// 注意 CAN1 通道
// #region 取一帧
// //=================================================
// byte[] bytes = new byte[13];
// bytes[0] = obj[0].DataLen; //obj[0].
// uint id = obj[0].ID; // 帧 id
// bytes[1] = (byte)(id >> 24);
// bytes[2] = (byte)(id >> 16);
// bytes[3] = (byte)(id >> 8);
// bytes[4] = (byte)(id & 0xff);
// fixed (VCI_CAN_OBJ* p_obj = &obj[0])// 8字节 第一帧
// {
// bytes[5] = p_obj->Data[0];
// bytes[6] = p_obj->Data[1];
// bytes[7] = p_obj->Data[2];
// bytes[8] = p_obj->Data[3];
// bytes[9] = p_obj->Data[4];
// bytes[10] = p_obj->Data[5];
// bytes[11] = p_obj->Data[6];
// bytes[12] = p_obj->Data[7];
// }
// return bytes;
// #endregion
// //return obj;
// }
// return null;
//}
//public unsafe object RXs()// VCI_CAN_OBJ //CAN帧参数
//{// CAN1 接收
// //throw new NotImplementedException();
// // 缓存区可用帧数=============================
// //Help_Delay.delayTime(0.005);// usb大概3~5ms
// int i = VCI_GetReceiveNum(Help_USB_CAN.VCI_USBCAN2, CAN_inD, CAN1);// can1
// if (i > 0)// CAN1接收帧数
// {
// VCI_CAN_OBJ[] obj = new VCI_CAN_OBJ[2000];// 创新科技CAN分析仪最大支持2000帧接收,间隔5ms以上
// i = VCI_get接收(4, 0, CAN1, ref obj[0], 2000, 50);// 注意 CAN1 通道
// #region 取一帧 【1 4 8】
// //=================================================
// //byte[] bytes = new byte[13];
// //bytes[0] = obj[0].DataLen; // 【1】有效字节
// //uint id = obj[0].ID; // 帧 id【4】帧id
// //bytes[1] = (byte)(id >> 24);
// //bytes[2] = (byte)(id >> 16);
// //bytes[3] = (byte)(id >> 8);
// //bytes[4] = (byte)(id & 0xff);
// //fixed (VCI_CAN_OBJ* p_obj = &obj[0])// 8字节 第一帧
// //{
// // bytes[5] = p_obj->Data[0];// 【8】包数据
// // bytes[6] = p_obj->Data[1];
// // bytes[7] = p_obj->Data[2];
// // bytes[8] = p_obj->Data[3];
// // bytes[9] = p_obj->Data[4];
// // bytes[10] = p_obj->Data[5];
// // bytes[11] = p_obj->Data[6];
// // bytes[12] = p_obj->Data[7];
// //}
// //return bytes;
// #endregion
// return obj;
// }
// return null;
//}
//public unsafe object TXs(string stringcmd)// "04000006014000200000000000"
//{//被CanOpen调用
// //throw new NotImplementedException();
// stringcmd.Replace(" ", "");//去除空白
// byte[] buffercmd = help_String.StringsToHexBytes(stringcmd);//准备报文 //去除空白 StringsToHexBytes
// VCI_CAN_OBJ[] buffer = new VCI_CAN_OBJ[10];
// string id = stringcmd.Substring(2, 8);// 从站地址 00000601
// buffer[0].ID = Convert.ToUInt32(id, 16);//从站id
// // 重发功能 0开,1关
// buffer[0].SendType = 0;//0(4秒内有重发) 1只发单次
// buffer[0].DataLen = buffercmd[0];//数据长度 DLC (<=8),即CAN帧Data有几个字节。约束了后面Data[8]中的有效字节。
// buffer[0].Data[0] = buffercmd[5];// byte8
// buffer[0].Data[1] = buffercmd[6];
// buffer[0].Data[2] = buffercmd[7];
// buffer[0].Data[3] = buffercmd[8];
// buffer[0].Data[4] = buffercmd[9];
// buffer[0].Data[5] = buffercmd[10];
// buffer[0].Data[6] = buffercmd[11];
// buffer[0].Data[7] = buffercmd[12];
// Int32 ret = VCI_set发送(Help_USB_CAN.VCI_USBCAN2, 0, CAN1, ref buffer[0], 1);// 库函数(发送TXs)
// return ret;
//}
//public int Close()
//{
// //throw new NotImplementedException();
// return (int)set_Close((UInt32)CAN设备类型.VCI_USBCAN2, CAN_inD);
//}
public bool sendAndReceive<T>(string cmd, ref T t)
{
throw new NotImplementedException();
}
#endregion
}
#endregion
}
更新日期:2023.11.25
using help;
//using Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.NetworkInformation;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
// 1先引用 CAN_namespace 用于参数类型 // using USB_CAN;
// 2再引用 help的方法
namespace CAN_namespace
{
#region 全局类型【声明】:通讯接口
/// <summary>
/// 全局类型:通讯接口
/// </summary>
public interface Iface_RTX // 开,关,收,发,轮询
{
/// <summary>
/// 连接
/// </summary>
/// <typeparam name="T">连接</typeparam>
/// <param name="a">ip地址</param>
/// <param name="b">端口</param>
/// <returns></returns>
bool connect<T>(T a, T b);// <string> "192.168.0.3","502"
/// <summary>
/// 断开
/// </summary>
/// <returns></returns>
bool Close();
/// <summary>
/// 只收
/// </summary>
/// <returns></returns>
int RXs(ref object obj);
//int RXs<T>(ref T obj);//测试
/// <summary>
/// 只发,格式148报文08123456781122334455667788
/// </summary>
/// <param name="cmd"></param>
/// <returns></returns>
int TXs(string cmd);
/// <summary>
/// 轮询
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="cmd"></param>
/// <param name="t"></param>
/// <returns></returns>
int sendAndReceive<T>(string cmd, ref T t);//万物皆文本
}
#endregion
#region 对象
public class Help_USB_ZHCX_CAN : Iface_RTX // ZHCX 珠海创芯科技有限公司
{//作者qq750273008 祁成 更新日期:2023.11.25
//===============================================
//[Browsable(true)] //可浏览
//[Category("自定义属性")] // 属性分栏
//[Description("属性的说明")] //
//================================================
#region 全局
//1申明委托》委托命令
public delegate void WT_GET_Data<T>(T ciA402);//↑ui显示发送命令
public delegate void WT_SET_Data(byte[] butes, string data);//↓下执行对象
#region CAN【数据类型】:全局:设备类型,主板信息,单帧信息,配置表
/*------------兼容ZLG的数据类型---------------------------------*/
//1.设备类型
/// <summary>
/// 设备类型(单路,双路,以太网CAN)
/// </summary>
public enum DeviceType : byte //设备类型【USB】{单路,双路},【以太网】{单路,双路}
{
DEV_USBCAN = 3, // USB单路CAN
DEV_USBCAN2 = 4,// USB双路CAN
VCI_USBCAN1 = 3,
VCI_USBCAN2 = 4,// 我买的属于这个(创芯科技CAN-Pro)
VCI_USBCAN2A = 4,
VCI_USBCAN_E_U = 20,// 以太网单路CAN
VCI_USBCAN_2E_U = 21// 以太网双路CAN
}
//2.ZLGCAN系列接口卡信息的数据类型。
/// <summary>
/// 主板设备【31F01031C93】v3.41 VCI_ReadBoardInfo【要先打开设备】
/// </summary>
public struct VCI_BOARD_INFO //主板信息 unsafe
{ // VCI_ReadBoardInfo【要先运行VCI_OpenDevice(4,0,0);】
public UInt16 hw_Version;//【0x0900】硬件版本,V9.00。
public UInt16 fw_Version;//【0x0341】固件版本,v3.41
public UInt16 dr_Version;//【0x0900】驱动版本,v9.00
public UInt16 in_Version;//【0x0905】接口版本,v9.05
public UInt16 irq_Num;// 【0x00】 保留参数。
public byte can_Num; // 【0x02】 表示有几路CAN通道。
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
public char[] str_Serial_Num;// 板卡序列号。【31F01031C93】
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)]
public char[] str_hw_Type;// 设备名称【USBCAN-II】
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public UInt16[] Reserved;// 系统保留。
}
public struct VCI_BOARD_FIND // 读取USB主板信息 设备【31F01031C93】v3.41
{// VCI_FindUsbDevice【专用参数】
public UInt16 hw_Version;//【0x0900】 硬件版本,V9.00。 //
public UInt16 fw_Version;//【0x0341】 固件版本,v3.41,
public UInt16 dr_Version;//【0x0900】 驱动版本,v9.00
public UInt16 in_Version;//【0x0905】 接口版本,v9.05
public UInt16 irq_Num;// 【0x0000】 保留参数。
public byte can_Num;// 【0x02】 表示有几路CAN通道。
public byte Reserved;// 【0x00】 保留。
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public char[] str_Serial_Num;// 此板卡的id号。【43 41 4e 2d 31 43 39 33】"CAN-1C93"
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 9)]
public char[] str_hw_Type;// 硬件类型“USBCAN V1.00”【55 53 42 43 41 4e 2d 49 49】"USBCAN-II"
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 7)]
public char[] Reserved1;// 【0x00】 保留。
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public char[] str_Usb_Serial;// 设备id【31 43 39 33】// "1C93"
}
public struct VCI_BOARD_FIND2 //主板信息
{// VCI_FindUsbDevice2【专用参数】
public UInt16 hw_Version;//【0x0900】硬件版本,V9.00。
public UInt16 fw_Version;//【0x0341】固件版本,v3.41
public UInt16 dr_Version;//【0x0900】驱动版本,v9.00
public UInt16 in_Version;//【0x0905】接口版本,v9.05
public UInt16 irq_Num;// 【0x00】 保留参数。
public byte can_Num; // 【0x02】 表示有几路CAN通道。
public byte str_Serial_Num0;// 3 //板卡序列号。【31F01031C93】
public byte str_Serial_Num1;// 1
public byte str_Serial_Num2;// F
public byte str_Serial_Num3;// 0
public byte str_Serial_Num4;// 1
public byte str_Serial_Num5;// 0
public byte str_Serial_Num6;// 3
public byte str_Serial_Num7;// 1
public byte str_Serial_Num8;// C
public byte str_Serial_Num9;// 9
public byte str_Serial_NumA;// 3
public UInt16 Reserved;// 系统保留。
}
//public fixed char str_Serial_Num[20];// 板卡序列号。【31F01031C93】
//public fixed char str_hw_Type[40];// 设备名称【USBCAN-II】
//public fixed UInt16 Reserved[8];// 系统保留。
//unsafe public struct VCI_FindUsbDevice2//使用不安全代码
//{
// public UInt16 hw_Version;
// public UInt16 fw_Version;
// public UInt16 dr_Version;
// public UInt16 in_Version;
// public UInt16 irq_Num;
// public byte can_Num;
// public fixed byte str_Serial_Num[20];
// public fixed byte str_hw_Type[40];
// public fixed byte Reserved[8];
//}
//unsafe public struct VCI_BOARD_INFO//使用不安全代码
//{
// public UInt16 hw_Version;
// public UInt16 fw_Version;
// public UInt16 dr_Version;
// public UInt16 in_Version;
// public UInt16 irq_Num;
// public byte can_Num;
// public fixed char str_Serial_Num[20]; // 【不能改】会影响到函数签名
// public fixed byte str_hw_Type[40];
// public fixed byte Reserved[8];
//}
//2-1.USB-CAN总线适配器板卡信息的数据类型1,该类型为VCI_FindUsbDevice函数的返回参数。
/// <summary>
/// USB-CAN设备主板信息,该类型为VCI_FindUsbDevice函数的返回参数。
/// </summary>
//public struct VCI_BOARD_FIND // 读取USB主板信息 设备【31F01031C93】v3.41
//{// VCI_FindUsbDevice
// public UInt16 hw_Version;//【0x0900】 硬件版本,0x0100表示V1.00。 //
// public UInt16 fw_Version;//【0x0341】 固件版本,v3.41,
// public UInt16 dr_Version;//【0x0900】 驱动版本,
// public UInt16 in_Version;//【0x0905】 接口版本,
// public UInt16 irq_Num;// 【0x0000】 保留参数。
// public byte can_Num;// 【0x02】 表示有几路CAN通道。
// public byte Reserved;// 【0x00】 保留。
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
// public char[] str_Serial_Num;// 此板卡的序列号。【43 41 4e 2d 31 43 39 33】"CAN-1C93"
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
// public char[] str_hw_Type;// 硬件类型“USBCAN V1.00”【55 53 42 43 41 4e 2d 49 49】"USBCAN-II"
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
// public char[] str_Usb_Serial;// 序列号【31 43 39 33】// "1C93"
//}
//3.定义CAN数据帧类型。
/// <summary>
/// CAN数据帧对象(每帧对象)
/// </summary>
public unsafe struct VCI_CAN_OBJ //CAN每帧对象,
{
public UInt32 ID;// 帧ID。 【u32】帧id,数据格式为靠右对齐。 详情请参照: 《8.附件1: ID对齐方式.pdf》说明文档。
public UInt32 TimeStamp; //【u32】时间值。 时间标示从CAN卡上电开始计时,计时单位为0.1ms。
public Byte TimeFlag; //标志位,=1时TimeStamp有效
public Byte SendType; //发送类型。【0】正常发送(失败有重发)【1】单次发送
public Byte RemoteFlag; //远程帧标志。 【0】数据帧,【1】远程帧(数据段空,用于呼叫从站)。
public Byte ExternFlag; //扩展帧标志。 【0】标准帧(11位ID),【1】扩展帧(29位ID)。
public Byte DataLen; //有效字节 DLC (<=8),即CAN帧Data有几个字节。约束了后面Data[8]中有效字节数。
public fixed Byte Data[8]; //数据包,如DataLen定义为3,即Data[0]、 Data[1]、 Data[2]是有效的。
public fixed Byte Reserved[3];//系统保留。
}
//public struct VCI_CAN_OBJ //CAN每帧对象,
//{// 创芯不能用这个,【bug是2000帧里只有一帧更新】
// public UInt32 ID;// 帧ID。 【u32】帧id,标准帧11bit,扩展帧29bit。
// public UInt32 TimeStamp; //【u32】时间值。从CAN卡上电开始计时,计时单位为0.1ms。
// public Byte TimeFlag; // 标志位,【1】TimeStamp值有效
// public Byte SendType; // 发送类型。【0】正常发送(失败有重发)【1】单次发送
// public Byte RemoteFlag; // 远帧标志。【0】数据帧【1】远程帧(数据段空,用于呼叫从站)。
// public Byte ExternFlag; // 扩展帧标志【0】标准帧(11位ID),【1】扩展帧(29位ID)。
// public Byte DataLen; // 单帧有效字节 DLC (<=8)约束了后面Data[8]中有效字节数。
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
// public Byte[] Data; // 数据包,如DataLen为3,Data[0]、Data[1]、Data[2]是有效的。
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
// public Byte[] Reserved; // 保留。
//}
public struct CAN_OBJ
{// 创芯不能用这个,【bug是2000帧里只有一帧更新】
public UInt32 ID;// 帧ID。 【u32】帧id,标准帧11bit,扩展帧29bit。
public UInt32 TimeStamp; //【u32】时间值。从CAN卡上电开始计时,计时单位为0.1ms。
public Byte TimeFlag; // 标志位,【1】TimeStamp值有效
public Byte SendType; // 发送类型。【0】正常发送(失败有重发)【1】单次发送
public Byte RemoteFlag; // 远帧标志。【0】数据帧【1】远程帧(数据段空,用于呼叫从站)。
public Byte ExternFlag; // 扩展帧标志【0】标准帧(11位ID),【1】扩展帧(29位ID)。
public Byte DataLen; // 单帧有效字节 DLC (<=8)约束了后面Data[8]中有效字节数。
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public Byte[] Data; // 数据包,如DataLen为3,Data[0]、Data[1]、Data[2]是有效的。
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public Byte[] Reserved; // 保留。
}
//————————————————
//版权声明:本文为CSDN博主「cfqq1989」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
//原文链接:https://blog.csdn.net/cfqq1989/article/details/134510613
//4.定义配置CAN的数据类型
/// <summary>
/// 初始化_配置(参数表)
/// </summary>
public struct VCI_INIT_CONFIG // 配置参数 设备【31F01031C93】v3.41
{
/// <summary>
/// bit高低全部匹配,此帧才可以被接收。D31对应帧id最高位
/// </summary>
public UInt32 AccCode;// bit全部匹配,此帧才可以被接收。否则不能接收。(//标准帧右移21bit分析)
// 相当于机械钥匙,凸起和凹槽必须匹配,才能开锁(接收)
// b31对应帧id最高位,所以11bit要左移21bit(//分析标准帧时右移21bit)
/// <summary>
/// bit高,使AccCode对应的bit失效,D31对应帧id最高位
/// </summary>
public UInt32 AccMask;// 屏蔽码。使AccCode的某个bit功能失效。左对齐,bit31~bit21置1为屏蔽AccCode的bit匹配功能,
// 相当于机械钥匙的bit销位,是否失效(bit置1为失效)
// 。屏蔽码推荐设置为0xFFFFFFFF,即全部接收。
public UInt32 Reserved;// 保留。
public byte Filter; // 【滤帧方式】【1】接收所有帧。【2】只收标准帧,【3】只收扩展帧。
public byte Timing0; //波特率参数,具体配置,请查看二次开发库函数说明书。(1Mbps):《Timing0=0x00,Timing1=0x14》
public byte Timing1; // 0x14 //波特率参数 1MHz(T0=0x00,T1=0x14)
public byte Mode; //模式【0】收发模式,【1】只收,【2】自测模式(环回模式)。
}
/*------------其他数据结构描述---------------------------------*/
/// <summary>
/// T 结构体用于装载更改 CANET_UDP 与 CANET_TCP 的目标 IP 和
///端口的必要信息。此结构体在 CANETE_UDP 与 CANET_TCP 中使用。
/// </summary>
public struct CHGDESIPANDPORT // 以太网can
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
public byte[] szpwd;
//更改目标 IP 和端口所需要的密码,长度小于 10,比如为“11223344”。
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
public byte[] szdesip;
//所要更改的目标 IP,比如为“192.168.0.111”。
public Int32 desport;
//所要更改的目标端口,比如为 4000。
public byte blisten;
//所要更改的工作模式,0 表示正常模式,1 表示只听模式。
}
public struct VCI_FILTER_RECORD //滤帧配置【满足条件的才接收】
{
UInt32 ExtFrame;// 过滤的帧类型【1】过滤扩展帧【0】过滤标准帧。
UInt32 Start;//起始帧ID
UInt32 End; //结束帧ID
}
/*------------数据结构描述完成---------------------------------*/
#endregion
#endregion
#region 字段
#region 原始库方法【接口函数】
//方法
/*------------兼容ZLG的函数描述---------------------------------*/
[DllImport("controlcan.dll")]
public static extern Int32 VCI_OpenDevice(UInt32 DeviceType, UInt32 DeviceInd, UInt32 Reserved);
//返回值=1,表示操作成功;=0表示操作失败;=-1表示USB-CAN设备不存在或USB掉线。
//使能设备//(can通道不工作,只设备工作)
[DllImport("controlcan.dll")]
public static extern Int32 VCI_CloseDevice(UInt32 DeviceType, UInt32 DeviceInd);
//返回值=1,表示操作成功;=0表示操作失败;=-1表示USB-CAN设备不存在或USB掉线。
//关闭设备
[DllImport("controlcan.dll")]
public static extern Int32 VCI_InitCAN(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_INIT_CONFIG pInitConfig);
//初始化can通道(参数配置)b31对应帧id最高位【数据左对齐】,所以11bit要左移21bit
[DllImport("controlcan.dll")]
public static extern Int32 VCI_ReadBoardInfo(UInt32 DeviceType, UInt32 DeviceInd, ref VCI_BOARD_INFO pInfo);
//读取主板信息【需要先VCI_OpenDevice】
[DllImport("controlcan.dll")]
public static extern Int32 VCI_GetReceiveNum(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd);
//缓存区可用帧数(<=2000帧)
[DllImport("controlcan.dll")]
public static extern Int32 VCI_ClearBuffer(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd);
//清空缓存区
[DllImport("controlcan.dll")]
public static extern Int32 VCI_StartCAN(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd);
//CAN通道启动(启动can通道)
[DllImport("controlcan.dll")]
public static extern Int32 VCI_ResetCAN(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd);
//CAN通道复位
[DllImport("controlcan.dll")]
public static extern Int32 VCI_Transmit(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_CAN_OBJ pSend, UInt32 Length);
//返回实际发送的帧数,=-1表示USB-CAN设备不存在或USB掉线。
//Length 最大为1000,建议设为1,每次发送单帧,以提高发送效率
//CAN通道发送(单次<=10帧)
[DllImport("controlcan.dll")]
public static extern Int32 VCI_Receive(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_CAN_OBJ pReceive, UInt32 Len, Int32 WaitTime_ms);
//CAN通道接收(函数调用间隔至少应设置在5ms以上。)【Len为单次封顶帧数2500帧被读出
/*------------其他函数描述---------------------------------*/
[DllImport("controlcan.dll")]
public static extern Int32 VCI_ConnectDevice(UInt32 DevType, UInt32 DevIndex);
//设备连接
[DllImport("controlcan.dll")]
public static extern Int32 VCI_UsbDeviceReset(UInt32 DevType, UInt32 DevIndex, UInt32 Reserved);
//设备复位
[DllImport("controlcan.dll")]
public static extern Int32 VCI_FindUsbDevice(ref VCI_BOARD_FIND pInfo);
//返回前5个设备信息
//若计算机中插入多于5个适配器,则使用VCI_FindUsbDevice2函数,最大支持50个USB-CAN适配器。
[DllImport("controlcan.dll")]
public static extern Int32 VCI_FindUsbDevice2(ref VCI_BOARD_FIND2 pInfo);
//如:VCI_BOARD_INFO pInfo[50]。
[DllImport("controlcan.dll")]
public static extern Int32 VCI_SetReference(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, UInt32 RefType, ref VCI_FILTER_RECORD pData);
//设置滤帧(设备类型,设备id,通道id,参数类型,参数包)【只监听某一范围的帧】
//RefType=1,添加滤帧表 指向VCI_FILTER_RECORD结构的指针
//RefType=2,启用滤帧表
//RefType=3,清除滤帧表。
/*------------函数描述结束---------------------------------*/
#endregion
//private CancellationTokenSource cts;//线程令牌
//private ManualResetEvent resetEvent = new ManualResetEvent(true);// 暂停业务
//=====================================================
Help_String help_String = new Help_String();//文本处理
#endregion
#region 属性
//public Iface_RTX help_rtx { get; set; }// 接口扩展
/// <summary>
/// ↑:byte包,文本
/// </summary>
//static public WT_GET_Data Wt_get;//↑event委托=》呼叫上ui层 让上层显示:发送命令
/// <summary>
/// ↓:byte包,文本
/// </summary>
static public WT_SET_Data Wt_set;//↓委托=》呼叫下位机执行
//设备类型
public uint VCI_USBCAN { get => 3; }// USB单路CAN
public uint VCI_USBCAN2 { get => 4; }// USB双路CAN
// E表示以太网
public uint VCI_USBCAN_E_U { get => 20; }// 以太网单路CAN
public uint VCI_USBCAN_2E_U { get => 21; }// 以太网双路CAN
public uint CAN1 { get => 0; } // 字段,内部使用
public uint CAN2 { get => 1; }
public byte STATUS_OK { get => 1; }
public byte STATUS_ERR { get => 0; }
/// <summary>
/// 发现设备 5个
/// </summary>
public VCI_BOARD_FIND[] get_FindUsbDevice
{
get
{
VCI_BOARD_FIND[] pInfo = new VCI_BOARD_FIND[5];
Int32 num = VCI_FindUsbDevice(ref pInfo[0]);// 查找5个设备
return pInfo;
}
}
/// <summary>
/// USB设备id:查找50个USB设备【31F01031C93】
/// </summary>
public VCI_BOARD_FIND2[] get_FindUsbDevice2
{
get
{
VCI_BOARD_FIND2[] pInfo = new VCI_BOARD_FIND2[50];
Int32 num = VCI_FindUsbDevice2(ref pInfo[0]);// 查找50个设备
return pInfo;
}
}
public VCI_BOARD_INFO get_ReadBoardInfo_USBCAN2
{
get
{
//Set_Open();
VCI_BOARD_INFO info = new VCI_BOARD_INFO();
VCI_ReadBoardInfo(VCI_USBCAN2, 0, ref info);
return info;
}
}
#endregion
#region 构造
#endregion
#region 事件
#endregion
#region APP方法【 开,关,收,发,复位
/// <summary>
/// 打开CAN:设备类型,硬件id,CAN通道id,参数表
/// </summary>
/// <param name="DeviceType"></param>
/// <param name="DeviceInd"></param>
/// <param name="CANInd"></param>
/// <param name="pInitConfig"></param>
/// <returns></returns>
public bool Set_Open()// 设备类型,设备id,通道,配置参数
{//打开CAN:设备类型,硬件索引,CAN通道索引,初始化参数,
UInt32 DeviceType = VCI_USBCAN2;// 设备类型4【USB双路CAN】
UInt32 DeviceInd = 0;// 设备ID
// 配置表
VCI_INIT_CONFIG config = new VCI_INIT_CONFIG();// 参数表【结构体】
// bit全部匹配,此帧才可以被接收。否则不能接收。【左对齐】(//标准帧右移21bit分析)
config.AccCode = 0;//bit【钥匙销子】匹配id,(右移21bit分析【32-11】)b31对应帧id最高位【左对齐】
config.AccMask = 0xffffffff;// 屏蔽码。使AccCode的某个bit功能失效。左对齐,【标准帧11bit】bit31~bit21置1为屏蔽AccCode的bit匹配功能,
config.Filter = 0; // 【滤帧方式】【1】接收所有帧。【2】只收标准帧,【3】只收扩展帧。
config.Timing0 = 0x00;//波特率 1MHz【T0=0x00,T1=0x14】 // 查手册
config.Timing1 = 0x14;
config.Mode = 0;//模式,0正常收发,1只收,2自发自收模式(环回模式)
//==========================================================
VCI_BOARD_FIND2 bord = new VCI_BOARD_FIND2();// 设备信息【结构体】
int num = VCI_FindUsbDevice2(ref bord);// 查找USB设备【31F01031C93】v3.41
if (num < 1)
{// 找不到设备
return false;
}
Int32 sta = 1;// 故障标记
// usb硬件
sta &= VCI_使能设备(DeviceType, DeviceInd);// 通电
sta &= VCI_初始化通道(DeviceType, DeviceInd, CAN1, ref config);// CAN 1
sta &= VCI_初始化通道(DeviceType, DeviceInd, CAN2, ref config);// CAN 2
sta &= VCI_CAN通道工作(DeviceType, DeviceInd, CAN1);// CAN 1 用于发送
sta &= VCI_CAN通道工作(DeviceType, DeviceInd, CAN2);// CAN 2 用于接收
return sta == STATUS_OK ? true : false; // 1完成,0故障
//================================
//VCI_INIT_CONFIG config = new VCI_INIT_CONFIG();// 参数表
//config.AccCode = 0;// bit全部匹配,此帧才可以被接收。否则不能接收。【左对齐】(//标准帧右移21bit分析)
//config.AccMask = 0xffffffff;//全部接收 // 屏蔽码。使AccCode的某个bit功能失效。左对齐,bit31~bit21置1为屏蔽AccCode的bit匹配功能,
//config.Filter = 0;//0或1接收所有帧。2标准帧滤波,3是扩展帧滤波。
//config.Timing0 = 0x00;//波特率参数 1MHz(T0=0x00,T1=0x14)
//config.Timing1 = 0x14;
//config.Mode = 0;//模式,0表示正常模式,1表示只听模式,2自测模式
//uint i = can.set_Open(Help_USB_CAN.VCI_USBCAN2, 0, 0, ref config);// CAN 1
//i &= can.set_Open(Help_USB_CAN.VCI_USBCAN2, 0, 1, ref config);// CAN 2
}
/// <summary>
/// 关闭CAN:设备类型,设备id
/// </summary>
/// <param name="DeviceType"></param>
/// <param name="DeviceInd"></param>
/// <returns></returns>
public Int32 Set_Close(UInt32 DeviceType, UInt32 DeviceInd)
{
Int32 sta = 1;// 故障标记
sta &= VCI_CloseDevice(DeviceType, DeviceInd);//设备关
sta &= VCI_UsbDeviceReset(DeviceType, DeviceInd, 0);// 设备复位
return sta;
}
public Int32 Set_ClearBuffer(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd)
{//设备类型,设备id,通道id
Int32 sta = 1;
sta &= VCI_ClearBuffer(DeviceType, DeviceInd, CANInd);
//sta&= VCI_ClearBuffer(DeviceType, DeviceInd, 1);// CAN2
return sta;
}
/// <summary>
/// 接收:设备类型,设备索引,CAN通道索引,参数表,最大帧数2000,超时时间
/// </summary>
/// <param name="DeviceType">设备类型</param>
/// <param name="DeviceInd">设备id</param>
/// <param name="CANInd">通道id</param>
/// <param name="pReceive">数据包</param>
/// <param name="Len">小于2500帧</param>
/// <param name="WaitTime">保留=0</param>
/// <returns></returns>
public Int32 get_Receive(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_CAN_OBJ pReceive, UInt32 Len, Int32 WaitTime)
{//VCI_CAN_OBJ pReceive 设置为数组,2000帧
// 设备类型,设备id,通道id,数据包,帧数,等待时间【保留0】
return VCI_Receive(DeviceType, DeviceInd, CANInd, ref pReceive, Len, WaitTime);
}
/// <summary>
/// 发送:设备类型,设备索引,CAN通道索引,参数表,要发帧数
/// </summary>
/// <param name="DeviceType">设备类型</param>
/// <param name="DeviceInd">设备id</param>
/// <param name="CANInd">通道id</param>
/// <param name="pSend">数据包</param>
/// <param name="Len">帧数小于1000</param>
/// <returns></returns>
public Int32 set_Send(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_CAN_OBJ pSend, UInt32 Len)
{
// 设备类型,设备id,通道id,数据包,帧数
return VCI_Transmit(DeviceType, DeviceInd, CANInd, ref pSend, Len);
}
public Int32 set_ResetCAN(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd)
{// 复位can通道
return VCI_ResetCAN(DeviceType, DeviceInd, CANInd);
}
/// <summary>
/// 获取CAN设备信息【需要先打开设备】
/// </summary>
/// <param name="DeviceType"></param>
/// <param name="DeviceInd"></param>
/// <param name="pInfo"></param>
/// <returns></returns>
public Int32 get_BoardInfo(UInt32 DeviceType, UInt32 DeviceInd, ref VCI_BOARD_INFO pInfo)
{//需要设备开启后,才能读取
return VCI_ReadBoardInfo(DeviceType, DeviceInd, ref pInfo);
//=======================================================
//VCI_BOARD_INFO info = new VCI_BOARD_INFO();
//uint i = can.get_Board(4, 0, ref info);
}
//==以下不再重要=======================================================================
//==以下不再重要========
/// <summary>
/// 使能硬件:设备类型,设备id。
/// </summary>
/// <param name="DeviceType">Help_USB_CAN.VCI_USBCAN2 = 4;双路CAN</param>
/// <param name="DeviceInd">第1个CAN通道是0</param>
/// <param name="Reserved">备用=0</param>
/// <returns></returns>
public Int32 VCI_使能设备(UInt32 DeviceType, UInt32 DeviceInd)
{// 相当于 插电
return VCI_OpenDevice(DeviceType, DeviceInd, 0x00);// 通电
}
/// <summary>
/// 初始化硬件:can设备类型,设备id,CAN通道id,VCI_INIT_CONFIG初始化参数结构体
/// </summary>
/// <param name="DeviceType">can设备类型</param>
/// <param name="DeviceInd">设备索引0</param>
/// <param name="CANInd">CAN通道索引0</param>
/// <param name="pInitConfig">VCI_INIT_CONFIG初始化参数结构</param>
/// <returns></returns>
public Int32 VCI_初始化通道(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_INIT_CONFIG pInitConfig)
{
return VCI_InitCAN(DeviceType, DeviceInd, CANInd, ref pInitConfig);
}
//设备类型。设备索引,CAN通道索引。初始化参数结构。
/// <summary>
/// CAN工作:设备类型,设备id,CAN通道id(返回【1】成功; 【0】失败; 【-1】设备不存在或USB掉线。)
/// </summary>
/// <param name="DeviceType"></param>
/// <param name="DeviceInd"></param>
/// <param name="CANInd"></param>
/// <returns></returns>
public Int32 VCI_CAN通道工作(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd)
{
return VCI_StartCAN(DeviceType, DeviceInd, CANInd);
}
/// <summary>
/// CAN发送:设备类型,设备索引,CAN通道索引,VCI_CAN_OBJ数组的首指针,(帧数量 最大为10)
/// </summary>
/// <param name="DeviceType"></param>
/// <param name="DeviceInd"></param>
/// <param name="CANInd"></param>
/// <param name="pSend"></param>
/// <param name="Len"></param>
/// <returns></returns>
public Int32 VCI_set发送(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_CAN_OBJ pSend, UInt32 Len)
{
return VCI_Transmit(DeviceType, DeviceInd, CANInd, ref pSend, Len);
}
/// <summary>
/// 缓冲区【小于等于2000帧】
/// </summary>
/// <param name="DeviceType"></param>
/// <param name="DeviceInd"></param>
/// <param name="CANInd"></param>
/// <returns></returns>
public Int32 VCI_get缓存区帧数(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd)
{
return VCI_GetReceiveNum(DeviceType, DeviceInd, CANInd);// 缓存区,帧数
}
/// <summary>
/// CAN接收:设备类型,设备id,CAN通道id,VCI_CAN_OBJ数组的首指针,本次接收的最大帧数 2500 ,等待时间ms
/// </summary>
/// <param name="DeviceType"></param>
/// <param name="DeviceInd"></param>
/// <param name="CANInd"></param>
/// <param name="pReceive"></param>
/// <param name="Len"></param>
/// <param name="WaitTime_ms"></param>
/// <returns></returns>
public Int32 VCI_get接收(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_CAN_OBJ pReceive, UInt32 Len, Int32 WaitTime_ms)
{
//VCI_CAN_OBJ[] obj = new VCI_CAN_OBJ[2000];
//uint i = can.VCI_get接收(4, 0, 1, ref obj[0], 2000, 0);
return VCI_Receive(DeviceType, DeviceInd, CANInd, ref pReceive, Len, WaitTime_ms);
}
#endregion
#region 后台方法
#endregion
#region 窗体移动
//private Point mouseOff;//鼠标移动位置变量
//private bool leftFlag;//标签是否为左键
//private void Frm_MouseDown(object sender, MouseEventArgs e)//鼠标按下
//{
// if (e.Button == MouseButtons.Left)
// {
// mouseOff = new Point(-e.X, -e.Y); //得到变量的值
// leftFlag = true; //点击左键按下时标注为true;
// }
//}
//private void Frm_MouseMove(object sender, MouseEventArgs e)//鼠标移动
//{
// if (leftFlag)
// {
// Point mouseSet = Control.MousePosition;
// mouseSet.Offset(mouseOff.X, mouseOff.Y); //设置移动后的位置
// //Location = mouseSet;//Form 窗体父类字段
// }
//}
//private void Frm_MouseUp(object sender, MouseEventArgs e)//鼠标松开
//{
// if (leftFlag)
// {
// leftFlag = false;//释放鼠标后标注为false;
// }
//}
#endregion
#region 错误
//try
//{
// byte[] buffer = Encoding.Default.GetBytes(data);//以计算机的编码发送
// serialPort.Write(buffer, 0, buffer.Length);// 开始发送
//}
//catch (Exception ex) { MessageBox.Show(ex.Message); }//显示错误
#endregion
#region 接口实现
public bool connect<T>(T a, T b)
{// 打开USB-CAN设备的can1通道
//throw new NotImplementedException();
Close();
UInt32 DeviceType = VCI_USBCAN2;// 设备类型4【USB双路CAN】
UInt32 DeviceInd = 0;// 设备ID
// 配置表
VCI_INIT_CONFIG config = new VCI_INIT_CONFIG();// 参数表【结构体】
// bit全部匹配,此帧才可以被接收。否则不能接收。【左对齐】(//标准帧右移21bit分析)
config.AccCode = 0;//bit【钥匙销子】匹配id,(右移21bit分析【32-11】)b31对应帧id最高位【左对齐】
config.AccMask = 0xffffffff;// 屏蔽码。使AccCode的某个bit功能失效。左对齐,【标准帧11bit】bit31~bit21置1为屏蔽AccCode的bit匹配功能,
config.Filter = 0; // 【滤帧方式】【1】接收所有帧。【2】只收标准帧,【3】只收扩展帧。
config.Timing0 = 0x00;//波特率 1MHz【T0=0x00,T1=0x14】 // 查手册
config.Timing1 = 0x14;
config.Mode = 0;//模式,0正常收发,1只收,2自发自收模式(环回模式)
//==========================================================
//VCI_BOARD_FIND2[] bord = new VCI_BOARD_FIND2[50];// 设备信息【结构体】
//int num = VCI_FindUsbDevice2(ref bord[0]);// 查找USB设备【31F01031C93】v3.41 VCI_FindUsbDevice2
//if (num < 1)
//{// 找不到设备
// return false;
//}
Int32 sta = 1;// 故障标记
// usb硬件
sta &= VCI_使能设备(DeviceType, DeviceInd);// 通电
sta &= VCI_初始化通道(DeviceType, DeviceInd, CAN1, ref config);// CAN 1
sta &= VCI_初始化通道(DeviceType, DeviceInd, CAN2, ref config);// CAN 2
sta &= VCI_CAN通道工作(DeviceType, DeviceInd, CAN1);// CAN 1 用于发送
sta &= VCI_CAN通道工作(DeviceType, DeviceInd, CAN2);// CAN 2 用于接收
return sta == STATUS_OK ? true : false; // 1完成,0故障
}
public bool Close()
{
//throw new NotImplementedException();
if (Set_Close(VCI_USBCAN2, 0) == STATUS_OK)
{
return true;
}
return false;
}
public Int32 RXs(ref object Obj)// 【<=2000帧】
{
//throw new NotImplementedException();
// 缓存区可用帧数=============================
//int i = VCI_GetReceiveNum(Help_USB_CAN.VCI_USBCAN2, CAN_inD, CAN1);// can1
VCI_CAN_OBJ[] obj = new VCI_CAN_OBJ[2000];// 创新科技CAN分析仪,单次最大缓存2000帧接收,间隔5ms以上
Int32 num = VCI_get接收(VCI_USBCAN2, 0, CAN1, ref obj[0], 2000, 100);// 注意 CAN1 通道
if (num > 0)// CAN1接收帧数
{
Obj = obj;
return num;
#region 取一帧 【1 4 8】
//=================================================
//byte[] bytes = new byte[13];
//bytes[0] = obj[0].DataLen; // 【1】有效字节
//uint id = obj[0].ID; // 帧 id【4】帧id
//bytes[1] = (byte)(id >> 24);
//bytes[2] = (byte)(id >> 16);
//bytes[3] = (byte)(id >> 8);
//bytes[4] = (byte)(id & 0xff);
//fixed (VCI_CAN_OBJ* p_obj = &obj[0])// 8字节 第一帧
//{
// bytes[5] = p_obj->Data[0];// 【8】包数据
// bytes[6] = p_obj->Data[1];
// bytes[7] = p_obj->Data[2];
// bytes[8] = p_obj->Data[3];
// bytes[9] = p_obj->Data[4];
// bytes[10] = p_obj->Data[5];
// bytes[11] = p_obj->Data[6];
// bytes[12] = p_obj->Data[7];
//}
//return bytes;
#endregion
}
return 0;
}
//public int RXs<T>(ref T obj)// 待测试
//{
// //throw new NotImplementedException();
// VCI_CAN_OBJ[] obj2 = new VCI_CAN_OBJ[2000];// 创新科技CAN分析仪最大支持2000帧接收,间隔5ms以上
// int num = VCI_get接收(4, 0, CAN1, ref obj2[0], 2000, 50);
// if (num > 0)// CAN1接收帧数
// {
// //obj = obj2.ToList<T>();
// return num;
// }
// return 0;
// }
public unsafe Int32 TXs(string cmd)// "08 00000602 4064600000000000" // CAN_namespace.Iface_RTX.
{// 1 4 8 (DLC字节,帧id,Byte8数据包)
//throw new NotImplementedException();
cmd.Replace(" ", "");//头尾去除空白
byte[] buffercmd = help_String.StringsToHexBytes(cmd);//准备报文 //去除空白 StringsToHexBytes
VCI_CAN_OBJ[] buffer = new VCI_CAN_OBJ[1];
string id = cmd.Substring(2, 8);// 从站地址 00000602
// 4
buffer[0].ID = Convert.ToUInt32(id, 16);//从站id
// 重发功能 0开,1关
buffer[0].SendType = 0;//【0】正常,失败有重发 【1】只发单次,失败无重发
// 1
buffer[0].DataLen = buffercmd[0];//数据长度 DLC (<=8),即CAN帧Data有几个字节。约束了后面Data[8]中的有效字节。
// 8
//buffer[0].Data = new Byte[8];//你不应该动到这里。【检查接收是否只刷新一帧】
buffer[0].Data[0] = buffercmd[5];// byte8
buffer[0].Data[1] = buffercmd[6];
buffer[0].Data[2] = buffercmd[7];
buffer[0].Data[3] = buffercmd[8];
buffer[0].Data[4] = buffercmd[9];
buffer[0].Data[5] = buffercmd[10];
buffer[0].Data[6] = buffercmd[11];
buffer[0].Data[7] = buffercmd[12];
// 上车》发车
Int32 ret = VCI_set发送(VCI_USBCAN2, 0, CAN1, ref buffer[0], 1);// 库函数(发送TXs)
return ret;
}
public unsafe object sendAndReceive(string stringcmd)
{//"1803052000018705"
//"04000006014000200000000000"
//throw new NotImplementedException();
stringcmd.Replace(" ", "");//去除空白
byte[] buffercmd = help_String.StringsToHexBytes(stringcmd);//准备报文 //去除空白 StringsToHexBytes
VCI_CAN_OBJ[] buffer = new VCI_CAN_OBJ[10];
string id = stringcmd.Substring(7, 3);// 从站地址
buffer[0].ID = Convert.ToUInt32(id, 16);//从站id
buffer[0].SendType = 1;//发送帧类型。=0时为正常发送(发送失败会自动重发,重发超时时间为4秒, 4秒内没有发出则取消);=1时为单次发送
buffer[0].DataLen = buffercmd[0];//数据长度 DLC (<=8),即CAN帧Data有几个字节。约束了后面Data[8]中的有效字节。
buffer[0].Data[0] = buffercmd[5];
buffer[0].Data[1] = buffercmd[6];
buffer[0].Data[2] = buffercmd[7];
buffer[0].Data[3] = buffercmd[8];
buffer[0].Data[4] = buffercmd[9];
buffer[0].Data[5] = buffercmd[10];
buffer[0].Data[6] = buffercmd[11];
buffer[0].Data[7] = buffercmd[12];
Int32 ret = set_Send(VCI_USBCAN2, 0, 0, ref buffer[0], 1);// 发1帧
//byte[] buff = SendAndReceive(buffer, stringcmd);// 收发报文
//if (buff == null) throw new Exception("ACK 未应答。。。");
//if (buff != null)
//{
// string str = help_String.BytesToHexStrings(buff);
// return str;
//}
return null;// 发送后未接收
}
//public unsafe object RXs()// VCI_CAN_OBJ //CAN帧参数
//{
// //throw new NotImplementedException();
// // 缓存区可用帧数=============================
// uint i = VCI_GetReceiveNum(Help_USB_CAN.VCI_USBCAN2, 0, 0);// can1
// if (i > 0)// CAN1接收帧数
// {
// uint CAN1 = 0;
// VCI_CAN_OBJ[] obj = new VCI_CAN_OBJ[2000];// 创新科技CAN分析仪最大支持2000帧接收
// i = VCI_get接收(4, 0, CAN1, ref obj[0], 1, 0);// 注意 CAN1 通道
// #region 取一帧
// //=================================================
// byte[] bytes = new byte[13];
// bytes[0] = obj[0].DataLen; //obj[0].
// uint id = obj[0].ID; // 帧 id
// bytes[1] = (byte)(id >> 24);
// bytes[2] = (byte)(id >> 16);
// bytes[3] = (byte)(id >> 8);
// bytes[4] = (byte)(id & 0xff);
// fixed (VCI_CAN_OBJ* p_obj = &obj[0])// 8字节 第一帧
// {
// bytes[5] = p_obj->Data[0];
// bytes[6] = p_obj->Data[1];
// bytes[7] = p_obj->Data[2];
// bytes[8] = p_obj->Data[3];
// bytes[9] = p_obj->Data[4];
// bytes[10] = p_obj->Data[5];
// bytes[11] = p_obj->Data[6];
// bytes[12] = p_obj->Data[7];
// }
// return bytes;
// #endregion
// //return obj;
// }
// return null;
//}
//public unsafe object RXs()// VCI_CAN_OBJ //CAN帧参数
//{// CAN1 接收
// //throw new NotImplementedException();
// // 缓存区可用帧数=============================
// //Help_Delay.delayTime(0.005);// usb大概3~5ms
// int i = VCI_GetReceiveNum(Help_USB_CAN.VCI_USBCAN2, CAN_inD, CAN1);// can1
// if (i > 0)// CAN1接收帧数
// {
// VCI_CAN_OBJ[] obj = new VCI_CAN_OBJ[2000];// 创新科技CAN分析仪最大支持2000帧接收,间隔5ms以上
// i = VCI_get接收(4, 0, CAN1, ref obj[0], 2000, 50);// 注意 CAN1 通道
// #region 取一帧 【1 4 8】
// //=================================================
// //byte[] bytes = new byte[13];
// //bytes[0] = obj[0].DataLen; // 【1】有效字节
// //uint id = obj[0].ID; // 帧 id【4】帧id
// //bytes[1] = (byte)(id >> 24);
// //bytes[2] = (byte)(id >> 16);
// //bytes[3] = (byte)(id >> 8);
// //bytes[4] = (byte)(id & 0xff);
// //fixed (VCI_CAN_OBJ* p_obj = &obj[0])// 8字节 第一帧
// //{
// // bytes[5] = p_obj->Data[0];// 【8】包数据
// // bytes[6] = p_obj->Data[1];
// // bytes[7] = p_obj->Data[2];
// // bytes[8] = p_obj->Data[3];
// // bytes[9] = p_obj->Data[4];
// // bytes[10] = p_obj->Data[5];
// // bytes[11] = p_obj->Data[6];
// // bytes[12] = p_obj->Data[7];
// //}
// //return bytes;
// #endregion
// return obj;
// }
// return null;
//}
//public unsafe object TXs(string stringcmd)// "04000006014000200000000000"
//{//被CanOpen调用
// //throw new NotImplementedException();
// stringcmd.Replace(" ", "");//去除空白
// byte[] buffercmd = help_String.StringsToHexBytes(stringcmd);//准备报文 //去除空白 StringsToHexBytes
// VCI_CAN_OBJ[] buffer = new VCI_CAN_OBJ[10];
// string id = stringcmd.Substring(2, 8);// 从站地址 00000601
// buffer[0].ID = Convert.ToUInt32(id, 16);//从站id
// // 重发功能 0开,1关
// buffer[0].SendType = 0;//0(4秒内有重发) 1只发单次
// buffer[0].DataLen = buffercmd[0];//数据长度 DLC (<=8),即CAN帧Data有几个字节。约束了后面Data[8]中的有效字节。
// buffer[0].Data[0] = buffercmd[5];// byte8
// buffer[0].Data[1] = buffercmd[6];
// buffer[0].Data[2] = buffercmd[7];
// buffer[0].Data[3] = buffercmd[8];
// buffer[0].Data[4] = buffercmd[9];
// buffer[0].Data[5] = buffercmd[10];
// buffer[0].Data[6] = buffercmd[11];
// buffer[0].Data[7] = buffercmd[12];
// Int32 ret = VCI_set发送(Help_USB_CAN.VCI_USBCAN2, 0, CAN1, ref buffer[0], 1);// 库函数(发送TXs)
// return ret;
//}
//public int Close()
//{
// //throw new NotImplementedException();
// return (int)set_Close((UInt32)CAN设备类型.VCI_USBCAN2, CAN_inD);
//}
public int sendAndReceive<T>(string cmd, ref T t)
{
throw new NotImplementedException();
}
#endregion
}
#endregion
}
更新日期:24/3/9
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.NetworkInformation;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
//====================================
using help;// 要用到文本转换 Help_String help_String = new Help_String();//文本处理
// 1先引用 CAN_namespace 用于参数类型 // using USB_CAN;
// 2再引用 help的方法
namespace CAN_namespace
{
#region 【通讯接口】:声明,全局类型
/// <summary>
/// 【通讯接口】开,关,收,发,轮询
/// </summary>
public interface IFace_RTX // 开,关,收,发,轮询
{//更新2024/3/8
/// <summary>
/// 【连接】有人CAN模块"192.168.0.3","502"
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
bool Open<T>(T a, T b);// 【开】
/// <summary>
/// 【断开】
/// </summary>
/// <returns></returns>
bool Close();// 【关】
/// <summary>
/// 【只收】
/// </summary>
/// <returns></returns>
int RXD(ref object obj);// 【收】
//int RXs<T>(ref T obj);//测试
/// <summary>
/// 【只发】,格式148字节报文08123456781122334455667788
/// </summary>
/// <param name="cmd"></param>
/// <returns></returns>
int TXD(string cmd); // 【发】
/// <summary>
/// 【轮询】
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="cmd"></param>
/// <param name="t"></param>
/// <returns></returns>
int RTX<T>(string cmd, ref T t);//【轮询】万物皆文本
}
#endregion 【通讯接口】
#region 对象
/// <summary>
/// 【CAN模块】珠海创芯科技有限公司
/// </summary>
public class Help_USB_CAN_ZHCX : IFace_RTX // ZHCX 珠海创芯科技有限公司
{//作者qq750273008 祁成 更新日期:2024/3/8
//===============================================
//[Browsable(true)] //可浏览
//[Category("自定义属性")] // 属性分栏
//[Description("属性的说明")] //
//================================================
#region 全局
//1申明委托》委托命令
public delegate void WT_GET_Data<T>(T ciA402);//↑ui显示发送命令
public delegate void WT_SET_Data(byte[] bytes, string data);//↓下执行对象
#region CAN【数据类型】:全局:设备铭牌,主板信息,单帧信息,配置表
/*------------兼容ZLG的数据类型---------------------------------*/
//1.设备类型
/// <summary>
/// 【设备类型】(单路,双路,以太网CAN)
/// </summary>
public enum DeviceType : byte //【设备类型】USB{单路,双路},以太网{单路,双路}
{
DEV_USBCAN = 3, // USB单路CAN
DEV_USBCAN2 = 4,// USB双路CAN
VCI_USBCAN1 = 3,
VCI_USBCAN2 = 4,// 我买的属于这个(创芯科技CAN-Pro)【USB双路CAN】
VCI_USBCAN2A = 4,
VCI_USBCAN_E_U = 20,// 以太网单路CAN
VCI_USBCAN_2E_U = 21// 以太网双路CAN
}
//2.ZLGCAN系列接口卡信息的数据类型。
/// <summary>
/// 主板铭牌【31F01031C93】v3.41 VCI_ReadBoardInfo【要先打开设备】
/// </summary>
public struct VCI_BOARD_INFO //主板铭牌 unsafe
{ // VCI_ReadBoardInfo【要先运行VCI_OpenDevice(4,0,0);】
public UInt16 hw_Version;//【0x0900】硬件版本,V9.00。
public UInt16 fw_Version;//【0x0341】固件版本,v3.41
public UInt16 dr_Version;//【0x0900】驱动版本,v9.00
public UInt16 in_Version;//【0x0905】接口版本,v9.05
public UInt16 irq_Num;// 【0x00】 保留参数。
public byte can_Num; // 【0x02】 表示有几路CAN通道。
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
public char[] str_Serial_Num;// 板卡序列号。【31F01031C93】
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)]
public char[] str_hw_Type;// 设备名称【USBCAN-II】
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public UInt16[] Reserved;// 系统保留。
}
public struct VCI_BOARD_FIND // 搜索设备
{// VCI_FindUsbDevice【专用参数】
public UInt16 hw_Version;//【0x0900】 硬件版本,V9.00。 // 信息 设备【31F01031C93】v3.41
public UInt16 fw_Version;//【0x0341】 固件版本,v3.41,
public UInt16 dr_Version;//【0x0900】 驱动版本,v9.00
public UInt16 in_Version;//【0x0905】 接口版本,v9.05
public UInt16 irq_Num;// 【0x0000】 保留参数。
public byte can_Num;// 【0x02】 表示有几路CAN通道。
public byte Reserved;// 【0x00】 保留。
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public char[] str_Serial_Num;// CAN口的SN码。【43 41 4e 2d 31 43 39 33】"CAN-1C93"
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 9)]
public char[] str_hw_Type;// 设备类型。【55 53 42 43 41 4e 2d 49 49】"USBCAN-II"
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 7)]
public char[] Reserved1;// 【0x00】 保留。
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public char[] str_Usb_Serial;// 设备SN码。【31 43 39 33】// "1C93"
}
public struct VCI_BOARD_FIND2 //主板SN码
{// VCI_FindUsbDevice2【专用参数】
public UInt16 hw_Version;//【0x0900】硬件版本,V9.00。
public UInt16 fw_Version;//【0x0341】固件版本,v3.41
public UInt16 dr_Version;//【0x0900】驱动版本,v9.00
public UInt16 in_Version;//【0x0905】接口版本,v9.05
public UInt16 irq_Num;// 【0x00】 保留参数。
public byte can_Num; // 【0x02】 表示有几路CAN通道。
public byte str_Serial_Num0;// 3 //板卡序列号。【31F01031C93】
public byte str_Serial_Num1;// 1
public byte str_Serial_Num2;// F
public byte str_Serial_Num3;// 0
public byte str_Serial_Num4;// 1
public byte str_Serial_Num5;// 0
public byte str_Serial_Num6;// 3
public byte str_Serial_Num7;// 1
public byte str_Serial_Num8;// C
public byte str_Serial_Num9;// 9
public byte str_Serial_NumA;// 3
public UInt16 Reserved;// 系统保留。
}
//unsafe public struct VCI_FindUsbDevice2//使用不安全代码
//{
// public UInt16 hw_Version;
// public UInt16 fw_Version;
// public UInt16 dr_Version;
// public UInt16 in_Version;
// public UInt16 irq_Num;
// public byte can_Num;
// public fixed byte str_Serial_Num[20];
// public fixed byte str_hw_Type[40];
// public fixed byte Reserved[8];
//}
//unsafe public struct VCI_BOARD_INFO//使用不安全代码
//{
// public UInt16 hw_Version;
// public UInt16 fw_Version;
// public UInt16 dr_Version;
// public UInt16 in_Version;
// public UInt16 irq_Num;
// public byte can_Num;
// public fixed char str_Serial_Num[20]; // 【不能改】会影响到函数签名
// public fixed byte str_hw_Type[40];
// public fixed byte Reserved[8];
//}
//2-1.USB-CAN总线适配器板卡信息的数据类型1,该类型为VCI_FindUsbDevice函数的返回参数。
/// <summary>
/// USB-CAN设备主板信息,该类型为VCI_FindUsbDevice函数的返回参数。
/// </summary>
//public struct VCI_BOARD_FIND // 读取USB主板信息 设备【31F01031C93】v3.41
//{// VCI_FindUsbDevice
// public UInt16 hw_Version;//【0x0900】 硬件版本,0x0100表示V1.00。 //
// public UInt16 fw_Version;//【0x0341】 固件版本,v3.41,
// public UInt16 dr_Version;//【0x0900】 驱动版本,
// public UInt16 in_Version;//【0x0905】 接口版本,
// public UInt16 irq_Num;// 【0x0000】 保留参数。
// public byte can_Num;// 【0x02】 表示有几路CAN通道。
// public byte Reserved;// 【0x00】 保留。
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
// public char[] str_Serial_Num;// 此板卡的序列号。【43 41 4e 2d 31 43 39 33】"CAN-1C93"
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
// public char[] str_hw_Type;// 硬件类型“USBCAN V1.00”【55 53 42 43 41 4e 2d 49 49】"USBCAN-II"
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
// public char[] str_Usb_Serial;// 序列号【31 43 39 33】// "1C93"
//}
//3.定义CAN数据帧类型。
/// <summary>
/// CAN数据帧对象(单帧对象)
/// </summary>
public unsafe struct VCI_CAN_OBJ //CAN单帧对象,
{
public UInt32 ID;// 帧ID。 【u32】帧id,数据格式为靠右对齐。 详情请参照: 《8.附件1: ID对齐方式.pdf》说明文档。
public UInt32 TimeStamp; //【u32】时间值。 时间标示从CAN卡上电开始计时,计时单位为0.1ms。
public Byte TimeFlag; //标志位,=1时TimeStamp有效
public Byte SendType; //发送类型。【0】正常发送(失败有重发)【1】单次发送
public Byte RemoteFlag; //远程帧标志。 【0】数据帧,【1】远程帧(数据段空,用于呼叫从站)。
public Byte ExternFlag; //扩展帧标志。 【0】标准帧(11位ID),【1】扩展帧(29位ID)。
public Byte DataLen; //有效字节 DLC (<=8),即CAN帧Data有几个字节。约束了后面Data[8]中有效字节数。
public fixed Byte Data[8]; //数据包,如DataLen定义为3,即Data[0]、 Data[1]、 Data[2]是有效的。
public fixed Byte Reserved[3];//系统保留。
}
//public struct VCI_CAN_OBJ //CAN单帧对象,
//{// 创芯不能用这个,【bug是2000帧里只有一帧更新】
// public UInt32 ID;// 帧ID。 【u32】帧id,标准帧11bit,扩展帧29bit。
// public UInt32 TimeStamp; //【u32】时间值。从CAN卡上电开始计时,计时单位为0.1ms。
// public Byte TimeFlag; // 标志位,【1】TimeStamp值有效
// public Byte SendType; // 发送类型。【0】正常发送(失败有重发)【1】单次发送
// public Byte RemoteFlag; // 远帧标志。【0】数据帧【1】远程帧(数据段空,用于呼叫从站)。
// public Byte ExternFlag; // 扩展帧标志【0】标准帧(11位ID),【1】扩展帧(29位ID)。
// public Byte DataLen; // 单帧有效字节 DLC (<=8)约束了后面Data[8]中有效字节数。
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
// public Byte[] Data; // 数据包,如DataLen为3,Data[0]、Data[1]、Data[2]是有效的。
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
// public Byte[] Reserved; // 保留。
//}
public struct CAN_OBJ
{// 创芯不能用这个,【bug是2000帧里只有一帧更新】
public UInt32 ID;// 帧ID。 【u32】帧id,标准帧11bit,扩展帧29bit。
public UInt32 TimeStamp; //【u32】时间值。从CAN卡上电开始计时,计时单位为0.1ms。
public Byte TimeFlag; // 标志位,【1】TimeStamp值有效
public Byte SendType; // 发送类型。【0】正常发送(失败有重发)【1】单次发送
public Byte RemoteFlag; // 远帧标志。【0】数据帧【1】远程帧(数据段空,用于呼叫从站)。
public Byte ExternFlag; // 扩展帧标志【0】标准帧(11位ID),【1】扩展帧(29位ID)。
public Byte DataLen; // 【字节长度】单帧有效字节 DLC (<=8)约束了后面Data[8]中有效字节数。
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public Byte[] Data; // 【数据包】 数据包,如DataLen为3,Data[0]、Data[1]、Data[2]是有效的。
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public Byte[] Reserved; // 保留。
}
//4.定义配置CAN的数据类型
/// <summary>
/// 【初始化_配置】(参数表)
/// </summary>
public struct VCI_INIT_CONFIG // 参数配置 设备【31F01031C93】v3.41
{
/// <summary>
/// bit高低全部匹配,此帧才可以被接收。D31对应帧id最高位
/// </summary>
public UInt32 AccCode;// 【bit钥匙销子】bit全部匹配,此帧才可以被接收。否则不能接收。(//标准帧右移21bit分析)
// 相当于机械钥匙,凸起和凹槽必须匹配,才能开锁(接收)
// b31对应帧id最高位,所以11bit要左移21bit(//分析标准帧时右移21bit)
/// <summary>
/// 【bit左对齐】,使AccCode对应的bit失效,D31对应帧id最高位
/// </summary>
public UInt32 AccMask;// 【屏蔽码】。使AccCode的某个bit功能失效。左对齐,bit31~bit21置1为屏蔽AccCode的bit匹配功能,
// 相当于机械钥匙的bit销位,是否失效(bit置1为失效)
// 。屏蔽码推荐设置为0xFFFFFFFF,即全部接收。
public UInt32 Reserved;// 保留。
public byte Filter; // 【接收模式】【1】接收所有帧。【2】只收标准帧,【3】只收扩展帧。
public byte Timing0; //波特率参数,具体配置,请查看二次开发库函数说明书。(1Mbps):《Timing0=0x00,Timing1=0x14》
public byte Timing1; // 0x14 //波特率参数 1MHz(T0=0x00,T1=0x14)
public byte Mode; // 【工作模式】【0】收发模式,【1】只收,【2】自测模式(环回模式)。
}
/*------------其他数据结构描述---------------------------------*/
/// <summary>
/// T 结构体用于装载更改 CANET_UDP 与 CANET_TCP 的目标 IP 和
///端口的必要信息。此结构体在 CANETE_UDP 与 CANET_TCP 中使用。
/// </summary>
public struct CHGDESIPANDPORT // 以太网can
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
public byte[] szpwd;//【密码】
//更改目标 IP 和端口所需要的密码,长度小于 10,比如为“11223344”。
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
public byte[] szdesip;//【地址IP】
//所要更改的目标 IP,比如为“192.168.0.111”。
public Int32 desport;//【端口】
//所要更改的目标端口,比如为 4000。
public byte blisten;//【接收模式】
//所要更改的工作模式,0 表示正常模式,1 表示只听模式。
}
/// <summary>
/// 【滤帧接收】满足条件的才接收
/// </summary>
public struct VCI_FILTER_RECORD //【滤帧接收】满足条件的才接收
{
UInt32 ExtFrame;// 过滤的帧类型【1】过滤扩展帧【0】过滤标准帧。
UInt32 Start;//起始帧ID
UInt32 End; //结束帧ID
}
/*------------数据结构描述完成---------------------------------*/
#endregion CAN【数据类型】
#endregion 全局
#region 字段
#region 原始库方法【接口函数】
//方法
/*------------兼容ZLG的函数描述---------------------------------*/
[DllImport("controlcan.dll")]
public static extern Int32 VCI_OpenDevice(UInt32 DeviceType, UInt32 DeviceInd, UInt32 Reserved);
//返回值=1,表示操作成功;=0表示操作失败;=-1表示USB-CAN设备不存在或USB掉线。
//使能设备//(can通道不工作,只设备工作)
[DllImport("controlcan.dll")]
public static extern Int32 VCI_CloseDevice(UInt32 DeviceType, UInt32 DeviceInd);
//返回值=1,表示操作成功;=0表示操作失败;=-1表示USB-CAN设备不存在或USB掉线。
//关闭设备
[DllImport("controlcan.dll")]
public static extern Int32 VCI_InitCAN(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_INIT_CONFIG pInitConfig);
//初始化can通道(参数配置)b31对应帧id最高位【数据左对齐】,所以11bit要左移21bit
[DllImport("controlcan.dll")]
public static extern Int32 VCI_ReadBoardInfo(UInt32 DeviceType, UInt32 DeviceInd, ref VCI_BOARD_INFO pInfo);
//读取主板铭牌【需要先VCI_OpenDevice】 //需要设备开启后,才能读取【铭牌】
[DllImport("controlcan.dll")]
public static extern Int32 VCI_GetReceiveNum(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd);
//【循环缓存区】可用帧数(<=2000帧)
[DllImport("controlcan.dll")]
public static extern Int32 VCI_ClearBuffer(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd);
//清空缓存区
[DllImport("controlcan.dll")]
public static extern Int32 VCI_StartCAN(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd);
//CAN通道启动(启动can通道)
[DllImport("controlcan.dll")]
public static extern Int32 VCI_ResetCAN(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd);
//CAN通道复位
[DllImport("controlcan.dll")]
public static extern Int32 VCI_Transmit(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_CAN_OBJ pSend, UInt32 Length);
//返回实际发送的帧数,=-1表示USB-CAN设备不存在或USB掉线。
//Length 最大为1000,建议设为1,每次发送单帧,以提高发送效率
//CAN通道发送(单次<=10帧)
[DllImport("controlcan.dll")]
public static extern Int32 VCI_Receive(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_CAN_OBJ pReceive, UInt32 Len, Int32 WaitTime_ms);
//CAN通道接收(函数调用间隔至少应设置在5ms以上。)【Len为单次封顶帧数2500帧被读出
/*------------其他函数描述---------------------------------*/
[DllImport("controlcan.dll")]
public static extern Int32 VCI_ConnectDevice(UInt32 DevType, UInt32 DevIndex);
//设备连接
[DllImport("controlcan.dll")]
public static extern Int32 VCI_UsbDeviceReset(UInt32 DevType, UInt32 DevIndex, UInt32 Reserved);
//设备复位
[DllImport("controlcan.dll")]
public static extern Int32 VCI_FindUsbDevice(ref VCI_BOARD_FIND pInfo);
//返回前5个设备信息
//若计算机中插入多于5个适配器,则使用VCI_FindUsbDevice2函数,最大支持50个USB-CAN适配器。
[DllImport("controlcan.dll")]
public static extern Int32 VCI_FindUsbDevice2(ref VCI_BOARD_FIND2 pInfo);
//如:VCI_BOARD_INFO pInfo[50]。
[DllImport("controlcan.dll")]
public static extern Int32 VCI_SetReference(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, UInt32 RefType, ref VCI_FILTER_RECORD pData);
//设置滤帧(设备类型,设备id,通道id,参数类型,参数包)【只监听某一范围的帧】
//RefType=1,添加滤帧表 指向VCI_FILTER_RECORD结构的指针
//RefType=2,启用滤帧表
//RefType=3,清除滤帧表。
/*------------函数描述结束---------------------------------*/
#endregion 原始库方法【接口函数】
//private CancellationTokenSource cts;//线程令牌
//private ManualResetEvent resetEvent = new ManualResetEvent(true);// 暂停业务
//=====================================================
Help_String help_String = new Help_String();//文本处理
#endregion 字段
#region 属性
//public IFace_RTX help_rtx { get; set; }// 接口扩展
/// <summary>
/// ↑:byte包,文本
/// </summary>
//static public WT_GET_Data Wt_get;//↑event委托=》呼叫上ui层 让上层显示:发送命令
/// <summary>
/// ↓:byte包,文本
/// </summary>
public WT_SET_Data Wt_set;//↓委托=》呼叫下位机执行
//设备类型
public uint VCI_USBCAN { get => 3; }// USB单路CAN
public uint VCI_USBCAN2 { get => 4; }// USB双路CAN
// E表示以太网
public uint VCI_USBCAN_E_U { get => 20; }// 以太网单路CAN
public uint VCI_USBCAN_2E_U { get => 21; }// 以太网双路CAN
public uint CAN1 { get => 0; } // 字段,内部使用
public uint CAN2 { get => 1; }
public byte STATUS_OK { get => 1; }
public byte STATUS_ERR { get => 0; }
/// <summary>
/// 发现设备 5个
/// </summary>
public VCI_BOARD_FIND[] get_FindUsbDevice
{
get
{
VCI_BOARD_FIND[] pInfo = new VCI_BOARD_FIND[5];
Int32 num = VCI_FindUsbDevice(ref pInfo[0]);// 查找5个设备
return pInfo;
}
}
/// <summary>
/// USB设备id:查找50个USB设备【31F01031C93】
/// </summary>
public VCI_BOARD_FIND2[] get_FindUsbDevice2// 查,刷新设备
{
get
{
VCI_BOARD_FIND2[] pInfo = new VCI_BOARD_FIND2[50];
Int32 num = VCI_FindUsbDevice2(ref pInfo[0]);// 查找50个设备
return pInfo;
}
}
public VCI_BOARD_INFO get_ReadBoardInfo_USBCAN2// 读,设备铭牌
{
get
{
//Set_Open();
VCI_BOARD_INFO info = new VCI_BOARD_INFO();
VCI_ReadBoardInfo(VCI_USBCAN2, 0, ref info);
return info;
}
}
#endregion 属性
#region 构造
//
#endregion 构造
#region 事件
#endregion 事件
#region APP方法【 开,关,收,发,复位
/// <summary>
/// 打开CAN:设备类型,硬件id,CAN通道id,参数表
/// </summary>
/// <param name="DeviceType"></param>
/// <param name="DeviceInd"></param>
/// <param name="CANInd"></param>
/// <param name="pInitConfig"></param>
/// <returns></returns>
public bool Set_Open()// 设备类型,设备id,通道,配置参数
{//打开CAN:设备类型,硬件索引,CAN通道索引,初始化参数,
UInt32 DeviceType = VCI_USBCAN2;// 设备类型4【USB双路CAN】
UInt32 DeviceInd = 0;// 设备ID
// 【参数】配置表
VCI_INIT_CONFIG config = new VCI_INIT_CONFIG();// 参数表【结构体】
// bit全部匹配,此帧才可以被接收。否则不能接收。【左对齐】(//标准帧右移21bit分析)
config.AccCode = 0;//【bit钥匙销子】匹配id,(右移21bit分析【32-11】)b31对应帧id最高位【左对齐】
config.AccMask = 0xffffffff;// 屏蔽码。使AccCode的某个bit功能失效。左对齐,【标准帧11bit】bit31~bit21置1为屏蔽AccCode的bit匹配功能,
config.Filter = 0; // 【接收模式】【1】接收所有帧。【2】只收标准帧,【3】只收扩展帧。
config.Timing0 = 0x00;//波特率 1MHz【T0=0x00,T1=0x14】 // 查手册
config.Timing1 = 0x14;
config.Mode = 0;//【工作模式】,0正常收发,1只收,2自发自收模式(环回模式)
//==========================================================
VCI_BOARD_FIND2 bord = new VCI_BOARD_FIND2();// 设备信息【结构体】
int num = VCI_FindUsbDevice2(ref bord);// 查找USB设备【31F01031C93】v3.41
if (num < 1)
{// 找不到设备
return false;
}
Int32 sta = 1;// 故障标记
// usb硬件
sta &= VCI_使能设备(DeviceType, DeviceInd);// 通电
sta &= VCI_初始化通道(DeviceType, DeviceInd, CAN1, ref config);// CAN 1
sta &= VCI_初始化通道(DeviceType, DeviceInd, CAN2, ref config);// CAN 2
sta &= VCI_CAN通道工作(DeviceType, DeviceInd, CAN1);// CAN 1 用于发送
sta &= VCI_CAN通道工作(DeviceType, DeviceInd, CAN2);// CAN 2 用于接收
return sta == STATUS_OK ? true : false; // 1完成,0故障
//================================
//VCI_INIT_CONFIG config = new VCI_INIT_CONFIG();// 参数表
//config.AccCode = 0;// 【bit钥匙销子】bit全部匹配,此帧才可以被接收。否则不能接收。【左对齐】(//标准帧右移21bit分析)
//config.AccMask = 0xffffffff;//全部接收 // 屏蔽码。使AccCode的某个bit功能失效。左对齐,bit31~bit21置1为屏蔽AccCode的bit匹配功能,
//config.Filter = 0;//【接收模式】0或1接收所有帧。2标准帧,3扩展帧。
//config.Timing0 = 0x00;//波特率参数 1MHz(T0=0x00,T1=0x14)
//config.Timing1 = 0x14;
//config.Mode = 0;//【工作模式】,0表示正常收发模式,1表示只收模式,2自测模式
//uint i = can.set_Open(Help_USB_CAN.VCI_USBCAN2, 0, 0, ref config);// CAN 1
//i &= can.set_Open(Help_USB_CAN.VCI_USBCAN2, 0, 1, ref config);// CAN 2
}
/// <summary>
/// 关闭CAN:设备类型,设备id
/// </summary>
/// <param name="DeviceType"></param>
/// <param name="DeviceInd"></param>
/// <returns></returns>
public Int32 Set_Close(UInt32 DeviceType, UInt32 DeviceInd)
{
Int32 sta = 1;// 故障标记
sta &= VCI_CloseDevice(DeviceType, DeviceInd);//设备关
sta &= VCI_UsbDeviceReset(DeviceType, DeviceInd, 0);// 设备复位
return sta;
}
public Int32 Set_ClearBuffer(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd)
{//设备类型,设备id,通道id
Int32 sta = 1;
sta &= VCI_ClearBuffer(DeviceType, DeviceInd, CANInd);
return sta;
}
/// <summary>
/// 接收:设备类型,设备索引,CAN通道索引,参数表,最大帧数2000,超时时间
/// </summary>
/// <param name="DeviceType">设备类型</param>
/// <param name="DeviceInd">设备id</param>
/// <param name="CANInd">通道id</param>
/// <param name="pReceive">数据包</param>
/// <param name="Len">小于2500帧</param>
/// <param name="WaitTime">保留=0</param>
/// <returns></returns>
public Int32 get_Receive(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_CAN_OBJ pReceive, UInt32 Len, Int32 WaitTime)
{//VCI_CAN_OBJ pReceive 设置为数组,2000帧
// 设备类型,设备id,通道id,数据包,帧数,等待时间【保留0】
return VCI_Receive(DeviceType, DeviceInd, CANInd, ref pReceive, Len, WaitTime);
}
/// <summary>
/// 发送:设备类型,设备索引,CAN通道索引,参数表,要发帧数
/// </summary>
/// <param name="DeviceType">设备类型</param>
/// <param name="DeviceInd">设备id</param>
/// <param name="CANInd">通道id</param>
/// <param name="pSend">数据包</param>
/// <param name="Len">帧数小于1000</param>
/// <returns></returns>
public Int32 set_Send(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_CAN_OBJ pSend, UInt32 Len)
{
// 设备类型,设备id,通道id,数据包,帧数
return VCI_Transmit(DeviceType, DeviceInd, CANInd, ref pSend, Len);
}
public Int32 set_ResetCAN(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd)
{// 复位can通道
return VCI_ResetCAN(DeviceType, DeviceInd, CANInd);
}
/// <summary>
/// 获取CAN设备铭牌【需要先打开设备】
/// </summary>
/// <param name="DeviceType"></param>
/// <param name="DeviceInd"></param>
/// <param name="pInfo"></param>
/// <returns></returns>
public Int32 get_BoardInfo(UInt32 DeviceType, UInt32 DeviceInd, ref VCI_BOARD_INFO pInfo)
{//需要设备开启后,才能读取【铭牌】
return VCI_ReadBoardInfo(DeviceType, DeviceInd, ref pInfo);
//=======测试================================================
//VCI_BOARD_INFO info = new VCI_BOARD_INFO();
//uint i = can.get_BoardInfo(4, 0, ref info);
}
//==以下不再重要=======================================================================
//==以下不再重要========
/// <summary>
/// 使能硬件:设备类型,设备id。
/// </summary>
/// <param name="DeviceType">Help_USB_CAN.VCI_USBCAN2 = 4;双路CAN</param>
/// <param name="DeviceInd">第1个CAN通道是0</param>
/// <param name="Reserved">备用=0</param>
/// <returns></returns>
public Int32 VCI_使能设备(UInt32 DeviceType, UInt32 DeviceInd)
{// 相当于 插电
return VCI_OpenDevice(DeviceType, DeviceInd, 0x00);// 通电
}
/// <summary>
/// 初始化硬件:can设备类型,设备id,CAN通道id,VCI_INIT_CONFIG初始化参数结构体
/// </summary>
/// <param name="DeviceType">can设备类型</param>
/// <param name="DeviceInd">设备索引0</param>
/// <param name="CANInd">CAN通道索引0</param>
/// <param name="pInitConfig">VCI_INIT_CONFIG初始化参数结构</param>
/// <returns></returns>
public Int32 VCI_初始化通道(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_INIT_CONFIG pInitConfig)
{
return VCI_InitCAN(DeviceType, DeviceInd, CANInd, ref pInitConfig);
}
//设备类型。设备索引,CAN通道索引。初始化参数结构。
/// <summary>
/// CAN工作:设备类型,设备id,CAN通道id(返回【1】成功; 【0】失败; 【-1】设备不存在或USB掉线。)
/// </summary>
/// <param name="DeviceType"></param>
/// <param name="DeviceInd"></param>
/// <param name="CANInd"></param>
/// <returns></returns>
public Int32 VCI_CAN通道工作(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd)
{
return VCI_StartCAN(DeviceType, DeviceInd, CANInd);
}
/// <summary>
/// CAN发送:设备类型,设备索引,CAN通道索引,VCI_CAN_OBJ数组的首指针,(帧数量 最大为10)
/// </summary>
/// <param name="DeviceType"></param>
/// <param name="DeviceInd"></param>
/// <param name="CANInd"></param>
/// <param name="pSend"></param>
/// <param name="Len"></param>
/// <returns></returns>
public Int32 VCI_set发送(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_CAN_OBJ pSend, UInt32 Len)
{
return VCI_Transmit(DeviceType, DeviceInd, CANInd, ref pSend, Len);
}
/// <summary>
/// 缓冲区【小于等于2000帧】
/// </summary>
/// <param name="DeviceType"></param>
/// <param name="DeviceInd"></param>
/// <param name="CANInd"></param>
/// <returns></returns>
public Int32 VCI_get循环缓存区有效帧数(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd)
{// 【单轮循环2000帧】数据帧池满2000帧会循环,前2000帧将被丢弃。
return VCI_GetReceiveNum(DeviceType, DeviceInd, CANInd);// 缓存区,帧数
}
/// <summary>
/// CAN接收:设备类型,设备id,CAN通道id,VCI_CAN_OBJ数组的首指针,本次接收的最大帧数 2500 ,等待时间ms
/// </summary>
/// <param name="DeviceType"></param>
/// <param name="DeviceInd"></param>
/// <param name="CANInd"></param>
/// <param name="pReceive"></param>
/// <param name="Len"></param>
/// <param name="WaitTime_ms"></param>
/// <returns></returns>
public Int32 VCI_get接收(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_CAN_OBJ pReceive, UInt32 Len, Int32 WaitTime_ms)
{
//VCI_CAN_OBJ[] obj = new VCI_CAN_OBJ[2000];
//uint i = can.VCI_get接收(4, 0, 1, ref obj[0], 2000, 0);
return VCI_Receive(DeviceType, DeviceInd, CANInd, ref pReceive, Len, WaitTime_ms);
}
#endregion APP方法【 开,关,收,发,复位
#region 后台方法
#endregion 后台方法
#region 窗体移动
//private Point mouseOff;//鼠标移动位置变量
//private bool leftFlag;//标签是否为左键
//private void Frm_MouseDown(object sender, MouseEventArgs e)//鼠标按下
//{
// if (e.Button == MouseButtons.Left)
// {
// mouseOff = new Point(-e.X, -e.Y); //得到变量的值
// leftFlag = true; //点击左键按下时标注为true;
// }
//}
//private void Frm_MouseMove(object sender, MouseEventArgs e)//鼠标移动
//{
// if (leftFlag)
// {
// Point mouseSet = Control.MousePosition;
// mouseSet.Offset(mouseOff.X, mouseOff.Y); //设置移动后的位置
// //Location = mouseSet;//Form 窗体父类字段
// }
//}
//private void Frm_MouseUp(object sender, MouseEventArgs e)//鼠标松开
//{
// if (leftFlag)
// {
// leftFlag = false;//释放鼠标后标注为false;
// }
//}
#endregion 窗体移动
#region 错误
//try
//{
// byte[] buffer = Encoding.Default.GetBytes(data);//以计算机的编码发送
// serialPort.Write(buffer, 0, buffer.Length);// 开始发送
//}
//catch (Exception ex) { MessageBox.Show(ex.Message); }//显示错误
#endregion 错误
#region 接口实现
public bool Open<T>(T a, T b)//【连接】
{// 打开USB-CAN设备的can1通道
//throw new NotImplementedException();
Close();// 【关闭】
UInt32 DeviceType = VCI_USBCAN2;// 设备类型4【USB双路CAN】
UInt32 DeviceInd = 0;// 设备ID
// 配置表
VCI_INIT_CONFIG config = new VCI_INIT_CONFIG();// 参数表【结构体】
// bit全部匹配,此帧才可以被接收。否则不能接收。【左对齐】(//标准帧右移21bit分析)
config.AccCode = 0;//bit【钥匙销子】匹配id,(右移21bit分析【32-11】)b31对应帧id最高位【左对齐】
config.AccMask = 0xffffffff;// 【屏蔽码】使AccCode的某个bit功能失效。左对齐,【标准帧11bit】bit31~bit21置1为屏蔽AccCode的bit匹配功能,
config.Filter = 0; // 【滤帧方式】【1】接收所有帧。【2】只收标准帧,【3】只收扩展帧。
config.Timing0 = 0x00;//波特率 1MHz【T0=0x00,T1=0x14】 // 查手册
config.Timing1 = 0x14;
config.Mode = 0;//模式,0正常收发,1只收,2自发自收模式(环回模式)
//==========================================================
//VCI_BOARD_FIND2[] bord = new VCI_BOARD_FIND2[50];// 设备信息【结构体】
//int num = VCI_FindUsbDevice2(ref bord[0]);// 查找USB设备【31F01031C93】v3.41 VCI_FindUsbDevice2
//if (num < 1)
//{// 找不到设备
// return false;
//}
Int32 sta = 1;// 故障标记
// usb硬件
sta &= VCI_使能设备(DeviceType, DeviceInd);// 通电
sta &= VCI_初始化通道(DeviceType, DeviceInd, CAN1, ref config);// CAN 1
sta &= VCI_初始化通道(DeviceType, DeviceInd, CAN2, ref config);// CAN 2
sta &= VCI_CAN通道工作(DeviceType, DeviceInd, CAN1);// CAN 1 用于发送
sta &= VCI_CAN通道工作(DeviceType, DeviceInd, CAN2);// CAN 2 用于接收
return sta == STATUS_OK ? true : false; // 1完成,0故障
}
public bool Close()//【断开】
{
//throw new NotImplementedException();
if (Set_Close(VCI_USBCAN2, 0) == STATUS_OK)
{
return true;
}
return false;
}
public Int32 RXD(ref object Obj)//【收】 【<=2000帧】
{
//throw new NotImplementedException();
// 缓存区可用帧数=============================
//int i = VCI_GetReceiveNum(Help_USB_CAN.VCI_USBCAN2, CAN_inD, CAN1);// can1
VCI_CAN_OBJ[] obj = new VCI_CAN_OBJ[2000];// 创新科技CAN分析仪,单次最大缓存2000帧接收,间隔5ms以上
Int32 num = VCI_get接收(VCI_USBCAN2, 0, CAN1, ref obj[0], 2000, 100);// 注意 CAN1 通道
if (num > 0)// CAN1接收帧数
{
Obj = obj;
return num;
#region 取一帧 【1 4 8】
//=================================================
//byte[] bytes = new byte[13];
//bytes[0] = obj[0].DataLen; // 【1】有效字节
//uint id = obj[0].ID; // 帧 id【4】帧id
//bytes[1] = (byte)(id >> 24);
//bytes[2] = (byte)(id >> 16);
//bytes[3] = (byte)(id >> 8);
//bytes[4] = (byte)(id & 0xff);
//fixed (VCI_CAN_OBJ* p_obj = &obj[0])// 8字节 第一帧
//{
// bytes[5] = p_obj->Data[0];// 【8】包数据
// bytes[6] = p_obj->Data[1];
// bytes[7] = p_obj->Data[2];
// bytes[8] = p_obj->Data[3];
// bytes[9] = p_obj->Data[4];
// bytes[10] = p_obj->Data[5];
// bytes[11] = p_obj->Data[6];
// bytes[12] = p_obj->Data[7];
//}
//return bytes;
#endregion 取一帧
}
return 0;
}
//public int RXs<T>(ref T obj)// 待测试
//{
// //throw new NotImplementedException();
// VCI_CAN_OBJ[] obj2 = new VCI_CAN_OBJ[2000];// 创新科技CAN分析仪最大支持 <= 2000帧接收,间隔5ms以上
// int num = VCI_get接收(4, 0, CAN1, ref obj2[0], 2000, 50);
// if (num > 0)// CAN1接收帧数
// {
// //obj = obj2.ToList<T>();
// return num;
// }
// return 0;
// }
public unsafe Int32 TXD(string cmd)//【发】 "08 00000602 4064600000000000" // CAN_namespace.Iface_RTX.
{// 1 4 8 (DLC字节,帧id,Byte8数据包)
//throw new NotImplementedException();
cmd.Replace(" ", "");//头尾去除空白
byte[] buffercmd = help_String.StringsToHexBytes(cmd);//准备报文 //去除空白 StringsToHexBytes
VCI_CAN_OBJ[] buffer = new VCI_CAN_OBJ[1];
string id = cmd.Substring(2, 8);// 从站地址 00000602
// 4
buffer[0].ID = Convert.ToUInt32(id, 16);//从站id
// 重发功能 0开,1关
buffer[0].SendType = 0;//【0】正常,失败有重发 【1】只发单次,失败无重发
// 1
buffer[0].DataLen = buffercmd[0];//数据长度 DLC (<=8),即CAN帧Data有几个字节。约束了后面Data[8]中的有效字节。
// 8
//buffer[0].Data = new Byte[8];//你不应该动到这里。【检查接收是否只刷新一帧】
buffer[0].Data[0] = buffercmd[5];// byte8
buffer[0].Data[1] = buffercmd[6];
buffer[0].Data[2] = buffercmd[7];
buffer[0].Data[3] = buffercmd[8];
buffer[0].Data[4] = buffercmd[9];
buffer[0].Data[5] = buffercmd[10];
buffer[0].Data[6] = buffercmd[11];
buffer[0].Data[7] = buffercmd[12];
// 上车》发车
Int32 ret = VCI_set发送(VCI_USBCAN2, 0, CAN1, ref buffer[0], 1);// 库函数(发送TXD)
return ret;
}
public int RTX<T>(string cmd, ref T t)//【轮询】
{
throw new NotImplementedException();
}
public unsafe object sendAndReceive(string stringcmd)
{//"1803052000018705"
//"04000006014000200000000000"
//throw new NotImplementedException();
stringcmd.Replace(" ", "");//去除空白
byte[] buffercmd = help_String.StringsToHexBytes(stringcmd);//准备报文 //去除空白 StringsToHexBytes
VCI_CAN_OBJ[] buffer = new VCI_CAN_OBJ[10];
string id = stringcmd.Substring(7, 3);// 从站地址
buffer[0].ID = Convert.ToUInt32(id, 16);//从站id
buffer[0].SendType = 1;//发送帧类型。=0时为正常发送(发送失败会自动重发,重发超时时间为4秒, 4秒内没有发出则取消);=1时为单次发送
buffer[0].DataLen = buffercmd[0];//数据长度 DLC (<=8),即CAN帧Data有几个字节。约束了后面Data[8]中的有效字节。
buffer[0].Data[0] = buffercmd[5];
buffer[0].Data[1] = buffercmd[6];
buffer[0].Data[2] = buffercmd[7];
buffer[0].Data[3] = buffercmd[8];
buffer[0].Data[4] = buffercmd[9];
buffer[0].Data[5] = buffercmd[10];
buffer[0].Data[6] = buffercmd[11];
buffer[0].Data[7] = buffercmd[12];
Int32 ret = set_Send(VCI_USBCAN2, 0, 0, ref buffer[0], 1);// 发1帧
//byte[] buff = SendAndReceive(buffer, stringcmd);// 收发报文
//if (buff == null) throw new Exception("ACK 未应答。。。");
//if (buff != null)
//{
// string str = help_String.BytesToHexStrings(buff);
// return str;
//}
return null;// 发送后未接收
}
//public unsafe object RXs()// VCI_CAN_OBJ //CAN帧参数
//{
// //throw new NotImplementedException();
// // 缓存区可用帧数=============================
// uint i = VCI_GetReceiveNum(Help_USB_CAN.VCI_USBCAN2, 0, 0);// can1
// if (i > 0)// CAN1接收帧数
// {
// uint CAN1 = 0;
// VCI_CAN_OBJ[] obj = new VCI_CAN_OBJ[2000];// 创新科技CAN分析仪最大支持2000帧接收
// i = VCI_get接收(4, 0, CAN1, ref obj[0], 1, 0);// 注意 CAN1 通道
// #region 取一帧
// //=================================================
// byte[] bytes = new byte[13];
// bytes[0] = obj[0].DataLen; //obj[0].
// uint id = obj[0].ID; // 帧 id
// bytes[1] = (byte)(id >> 24);
// bytes[2] = (byte)(id >> 16);
// bytes[3] = (byte)(id >> 8);
// bytes[4] = (byte)(id & 0xff);
// fixed (VCI_CAN_OBJ* p_obj = &obj[0])// 8字节 第一帧
// {
// bytes[5] = p_obj->Data[0];
// bytes[6] = p_obj->Data[1];
// bytes[7] = p_obj->Data[2];
// bytes[8] = p_obj->Data[3];
// bytes[9] = p_obj->Data[4];
// bytes[10] = p_obj->Data[5];
// bytes[11] = p_obj->Data[6];
// bytes[12] = p_obj->Data[7];
// }
// return bytes;
// #endregion
// //return obj;
// }
// return null;
//}
//public unsafe object RXs()// VCI_CAN_OBJ //CAN帧参数
//{// CAN1 接收
// //throw new NotImplementedException();
// // 缓存区可用帧数=============================
// //Help_Delay.delayTime(0.005);// usb大概3~5ms
// int i = VCI_GetReceiveNum(Help_USB_CAN.VCI_USBCAN2, CAN_inD, CAN1);// can1
// if (i > 0)// CAN1接收帧数
// {
// VCI_CAN_OBJ[] obj = new VCI_CAN_OBJ[2000];// 创新科技CAN分析仪最大支持2000帧接收,间隔5ms以上
// i = VCI_get接收(4, 0, CAN1, ref obj[0], 2000, 50);// 注意 CAN1 通道
// #region 取一帧 【1 4 8】
// //=================================================
// //byte[] bytes = new byte[13];
// //bytes[0] = obj[0].DataLen; // 【1】有效字节
// //uint id = obj[0].ID; // 帧 id【4】帧id
// //bytes[1] = (byte)(id >> 24);
// //bytes[2] = (byte)(id >> 16);
// //bytes[3] = (byte)(id >> 8);
// //bytes[4] = (byte)(id & 0xff);
// //fixed (VCI_CAN_OBJ* p_obj = &obj[0])// 8字节 第一帧
// //{
// // bytes[5] = p_obj->Data[0];// 【8】包数据
// // bytes[6] = p_obj->Data[1];
// // bytes[7] = p_obj->Data[2];
// // bytes[8] = p_obj->Data[3];
// // bytes[9] = p_obj->Data[4];
// // bytes[10] = p_obj->Data[5];
// // bytes[11] = p_obj->Data[6];
// // bytes[12] = p_obj->Data[7];
// //}
// //return bytes;
// #endregion
// return obj;
// }
// return null;
//}
//public unsafe object TXs(string stringcmd)// "04000006014000200000000000"
//{//被CanOpen调用
// //throw new NotImplementedException();
// stringcmd.Replace(" ", "");//去除空白
// byte[] buffercmd = help_String.StringsToHexBytes(stringcmd);//准备报文 //去除空白 StringsToHexBytes
// VCI_CAN_OBJ[] buffer = new VCI_CAN_OBJ[10];
// string id = stringcmd.Substring(2, 8);// 从站地址 00000601
// buffer[0].ID = Convert.ToUInt32(id, 16);//从站id
// // 重发功能 0开,1关
// buffer[0].SendType = 0;//0(4秒内有重发) 1只发单次
// buffer[0].DataLen = buffercmd[0];//数据长度 DLC (<=8),即CAN帧Data有几个字节。约束了后面Data[8]中的有效字节。
// buffer[0].Data[0] = buffercmd[5];// byte8
// buffer[0].Data[1] = buffercmd[6];
// buffer[0].Data[2] = buffercmd[7];
// buffer[0].Data[3] = buffercmd[8];
// buffer[0].Data[4] = buffercmd[9];
// buffer[0].Data[5] = buffercmd[10];
// buffer[0].Data[6] = buffercmd[11];
// buffer[0].Data[7] = buffercmd[12];
// Int32 ret = VCI_set发送(Help_USB_CAN.VCI_USBCAN2, 0, CAN1, ref buffer[0], 1);// 库函数(发送TXs)
// return ret;
//}
//public int Close()
//{
// //throw new NotImplementedException();
// return (int)set_Close((UInt32)CAN设备类型.VCI_USBCAN2, CAN_inD);
//}
#endregion 接口实现
}
#endregion
}
4函数 VCI_FindUsbDevice2
[DllImport("controlcan.dll")]
static extern UInt32 VCI_FindUsbDevice2(ref VCI_BOARD_INFO pInfo);
unsafe public struct VCI_BOARD_INFO
{
public UInt16 hw_Version;
public UInt16 fw_Version;
public UInt16 dr_Version;
public UInt16 in_Version;
public UInt16 irq_Num;
public byte can_Num;
public fixed byte str_Serial_Num[20];
public fixed byte str_hw_Type[40];
public fixed byte Reserved[8];
}
VCI_BOARD_INFO[] vbi2 = new VCI_BOARD_INFO[500];
5单帧对象:
#region 【单帧对象】
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct VCI_CAN_OBJ //【CAN单帧对象】
{
public uint ID;// 帧ID。 【u32】帧id,标准帧11bit,扩展帧29bit。
public uint TimeStamp; //【u32】时间值。 时间标示从CAN卡上电开始计时,计时单位为0.1ms。
public byte TimeFlag; //标志位,=1时TimeStamp有效
public byte SendType; //发送类型。【0】正常发送(失败有重发20次)【1】单次发送
public byte RemoteFlag; //远程帧标志。 【0】数据帧,【1】远程帧(数据段空,用于呼叫从站)。
public byte ExternFlag; //扩展帧标志。 【0】标准帧(11位ID),【1】扩展帧(29位ID)。
public byte DataLen; //有效字节 DLC (<=8),即CAN帧Data有几个字节。约束了后面Data[8]中有效字节数。
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] Data; //数据包,如DataLen定义为3,即Data[0]、 Data[1]、 Data[2]是有效的。
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] Reserved; //系统保留。
}
#endregion