CAN总线,创芯科技USB_CAN【C#二次开发】

参考资料

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

6波特率

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: 基于创芯CAN分析仪的ControlCAN.dll是一种用于控制和管理CAN分析仪的动态链接库(DLL)。可以通过在C语言程序中调用ControlCAN.dll中的函数,来实现对CAN分析仪的配置、操作和数据读取等功能。 ControlCAN.dll提供了丰富的API函数,可以通过这些函数实现对CAN分析仪的各种操作。例如,可以使用ControlCAN.dll中的函数来初始化CAN分析仪的连接,设置CAN通信的波特率和工作模式,配置CAN分析仪的过滤器和接收数据缓冲区等。还可以通过ControlCAN.dll的函数来向CAN总线发送CAN消息,并接收和解析CAN总线上的消息。 在进行CAN数据读取时,可以通过ControlCAN.dll中的函数将CAN总线上接收到的数据读取到C语言程序中进行处理和分析。通过ControlCAN.dll提供的函数,可以方便地对接收到的CAN消息进行解析,并获取其中的数据和状态信息。 此外,ControlCAN.dll还支持对CAN分析仪进行状态查询和错误处理等功能。可以通过调用ControlCAN.dll中的函数,获取CAN分析仪当前的工作状态、连接状态和错误信息等,并进行相应的处理和判断。 综上所述,基于创芯CAN分析仪的ControlCAN.dll提供了丰富的功能接口,可以方便地在C语言程序中对CAN分析仪进行控制和数据读取。通过调用ControlCAN.dll中的函数,可以实现对CAN分析仪各种配置和操作的灵活控制。 ### 回答2: 基于创芯CAN分析仪的ControlCAN.dll的C#编程主要用于与CAN分析仪进行通信和数据交互。通过ControlCAN.dll提供的API函数,可以实现CAN分析仪的初始化、打开/关闭CAN通道、发送/接收CAN消息等功能。 首先,需要在C#项目中引入ControlCAN.dll库文件,并在代码中使用using语句导入Control_CAN命名空间。 首先,通过调用Control_CAN的初始化函数,对CAN分析仪进行初始化,指定CAN通道的波特率、CAN通道号等参数。例如: Control_CAN.VCI_INIT_CONFIG config = new Control_CAN.VCI_INIT_CONFIG(); config.AccCode = 0; config.AccMask = 0xFFFFFFFF; config.Filter = 0; config.Timing0 = 0x01; //波特率参数看CAN分析仪的说明书 config.Timing1 = 0x1C; Control_CAN.VCI_OpenDevice(Control_CAN.VCI_USBCAN1, 0, 0); 接下来,可以通过调用Control_CAN的打开CAN通道函数,打开指定的CAN通道,例如: Control_CAN.VCI_OpenDevice(Control_CAN.VCI_USBCAN1, 0, 0); 然后,可以调用Control_CAN的发送CAN消息函数,向指定的CAN通道发送CAN消息。例如: Control_CAN.VCI_CAN_OBJ[] sendMsg = new Control_CAN.VCI_CAN_OBJ[1]; sendMsg[0].ID = 0x123; sendMsg[0].SendType = 0; sendMsg[0].RemoteFlag = 0; sendMsg[0].ExternFlag = 0; sendMsg[0].DataLen = 8; sendMsg[0].Data = new byte[8] { 1, 2, 3, 4, 5, 6, 7, 8 }; Control_CAN.VCI_Transmit(Control_CAN.VCI_USBCAN1, 0, 0, sendMsg, 1); 最后,可以调用Control_CAN的接收CAN消息函数,从指定的CAN通道接收CAN消息。例如: Control_CAN.VCI_CAN_OBJ[] receiveMsg = new Control_CAN.VCI_CAN_OBJ[1]; Control_CAN.VCI_Receive(Control_CAN.VCI_USBCAN1, 0, 0, receiveMsg, 1, 1000); 通过以上的代码示例,可以在C#编程环境中实现基于创芯CAN分析仪ControlCAN.dll的CAN通信功能。注意,具体的函数调用参数和错误处理可以根据实际情况进行调整和处理。 ### 回答3: 基于创芯CAN分析仪ControlCAN.dll的C#编程可以实现CAN总线数据的读取和发送操作。ControlCAN.dll是一种动态链接库,可以用于控制CAN分析仪设备的功能。 在C#中,我们首先需要将ControlCAN.dll引入到项目中,并使用命名空间`ControlCanDLL`。之后,我们可以通过以下步骤来使用CAN分析仪的功能: 1. 初始化CAN分析仪设备:调用`VCI_OpenDevice`函数初始化CAN分析仪设备,返回设备的句柄(Handle)。 2. 配置CAN总线参数:使用`VCI_InitCAN`函数配置CAN分析仪设备的参数,如波特率、数据位等。 3. 打开CAN通道:使用`VCI_StartCAN`函数打开CAN分析仪设备的指定通道,指定通道号和设备句柄。 4. 接收CAN数据:使用`VCI_Receive`函数接收CAN总线上的数据,可以指定要接收的数据帧类型(如标准帧、扩展帧等)。 5. 发送CAN数据:使用`VCI_Transmit`函数向CAN总线发送数据,可以设置发送的数据帧类型、ID及数据内容。 6. 关闭CAN通道:使用`VCI_ResetCAN`函数关闭CAN分析仪设备的指定通道。 7. 关闭CAN分析仪设备:使用`VCI_CloseDevice`函数关闭CAN分析仪设备。 此外,还可以通过其他函数和结构体实现对CAN分析仪设备的其他功能,如过滤规则的设置、接收缓冲区的清空等。 总结起来,基于创芯CAN分析仪ControlCAN.dll的C#编程,可以实现对CAN总线的读取和发送操作,从而实现对CAN总线中数据的获取和控制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值