USBcan盒子(读写寄存器)

驱动器一套90元

can盒子449

感觉不如以太网转CAN好用 (usb实时性好,以太网调试比较直观。)

设备参数性能:
 
缓冲区2000帧。【<=2000】
 
发2001帧,触发丢弃,实收1帧。【发2003帧,实收最后3帧】

单次最大读取2000帧。

电平:

隐性【逻辑1】

 

显性【逻辑0】

 

4.接口函数库20.06.01(二次开发库)使用说明书.pdf

V2.09    2023.07.01

数据类型: 

这个厂家给的参数类型定义有问题,只做参考,用我测试好的参数类型【在文章底部】 

4个数据类型:
          DeviceType       设备类型4(USBCAN-2A,USBCAN-2C,CANalyst-II)单can为3,双can为4
          VCI_BOARD_INFO   设备信息
          VCI_CAN_OBJ      数据帧信息
          VCI_INIT_CONFIG  配置信息

//==========================
1设备类型:
 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
        }
只需要看设备类型的数值,是4还是21,【区分USB还是以太网】

//=========================
2读取设备信息之前,须先打开设备 VCI_OpenDevice(4,0,0);// 设备类型,索引,保留0
VCI_BOARD_INFO iNFO = new VCI_BOARD_INFO();
uint num = VCI_ReadBoardInfo(4, 0, ref iNFO);

        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;// 系统保留。
        }
//============================
3数据帧信息
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时为正常发送(发送失败会自动重发,重发超时时间为4秒, 4秒内没有发出则取消);=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配置信息
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 VCI_FILTER_RECORD //滤帧配置
{
  UInt32 ExtFrame;// 过滤的帧类型【1】过滤扩展帧【0】过滤标准帧。
  UInt32 Start;//起始帧ID 
  UInt32 End;  //结束帧ID 
}

函数方法: 

函数描述:

//===============
设备操作:
VCI_UsbDeviceReset    【等同于插拔一次USB设备】
VCI_FindUsbDevice2    【扫描可用设备】
VCI_OpenDevice        打开设备
                     【1连接设备】打开设备(设备类型4,设备索引0,保留0)return  1ok
VCI_CloseDevice     关闭设备(设备类型4,设备索引0)

VCI_ReadBoardInfo    读设备信息(设备类型4,设备索引0,VCI_BOARD_INFO结构指针)
VCI_SetReference    【设置滤帧】


//================
控制操作:
VCI_InitCan       【2参数设置】初始化设备(设备类型4,设备索引0,CAN通道索引0,参数结构)
VCI_StartCAN      【3CAN通道工作】启动CAN通道(设备类型4,设备索引0,CAN通道索引0) return 1成功
VCI_Transmit    发送(设备类型4,设备索引0,CAN通道索引0,VCI_CAN_OBJ数组的首指针,帧数1)
VCI_Receive     接收(设备类型4,设备索引0,CAN通道索引0,VCI_CAN_OBJ数组的首指针,帧数2500,0)

VCI_GetReceiveNum    帧数量(设备类型4,设备索引0,CAN通道索引0)return  u64 -1设备丢失
VCI_ClearBuffer      清空数据(设备类型4,设备索引0,CAN通道索引0)
VCI_ResetCAN        复位CAN通道(设备类型4,设备索引0,CAN通道索引0) return 1成功

 设备信息: CAN 2个,v3.41,序列号   31F01031C93

3 其他函数

VCI_BOARD_INFO1        设备信息
VCI_UsbDeviceReset     复位USB设备(设备类型4,设备索引0,保留0)return  1成功
VCI_OpenDevice       连接USB设备(设备类型4,设备索引0,保留0)return  1ok
VCI_FindUsbDevice2        查找USB设备(VCI_BOARD_INFO数组50)return  int可用设备数量

VCI_FindUsbDevice(ref VCI_BOARD_INFO1 pInfo);
//查找可用的usb设备
//若计算机中插入多于4个适配器,则使用VCI_FindUsbDevice2函数,最大支持50个USB-CAN适配器。

 VCI_BOARD_INFO  设备信息

//1.ZLGCAN系列接口卡信息的数据类型。
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;// 系统保留。
}
//======================================
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"
}

用于读取硬件信息,软件绑定硬件设备。 

这个配置很重要: AccCode=0x00000000接收码,AccMask=0xFFFFFFFF屏蔽码;Filter=0x01接收所有,速度1Mbps(T0=0x00,T1=0x14)Mode=0x00正常模式;

 Demo:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

/*------------兼容ZLG的数据类型---------------------------------*/

//1.ZLGCAN系列接口卡信息的数据类型。
public struct VCI_BOARD_INFO 
{ 
	public UInt16 hw_Version;// 硬件版本号,用16进制表示。比如0x0100表示V1.00。
    public UInt16 fw_Version;// 固件版本号, 
    public UInt16 dr_Version;// 驱动程序版本号,
    public UInt16 in_Version;// 接口库版本号,
    public UInt16 irq_Num;// 保留参数。
    public byte   can_Num;// 表示有几路CAN通道。
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=20)]
    public byte []str_Serial_Num;// 此板卡的序列号。
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)]
    public byte[] str_hw_Type;// 硬件类型,比如“USBCAN V1.00”(注意:包括字符串结束符’\0’)
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
    public byte[] Reserved;// 系统保留。
}

/
//2.定义CAN信息帧的数据类型。
unsafe public struct VCI_CAN_OBJ  //CAN帧结构体,
{
    public uint ID;// 帧ID。 32位变量,数据格式为靠右对齐。 详情请参照: 《8.附件1: ID对齐方式.pdf》说明文档。
    public uint TimeStamp;        //设备接收到某一帧的时间标识。 时间标示从CAN卡上电开始计时,计时单位为0.1ms。
    public byte TimeFlag;         //是否使用时间标识,为1时TimeStamp有效
    public byte SendType;         //发送帧类型。=0时为正常发送(发送失败会自动重发,重发超时时间为4秒, 4秒内没有发出则取消);=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];//系统保留。

}

//3.定义初始化CAN的数据类型
public struct VCI_INIT_CONFIG 
{
    public UInt32 AccCode;// 接收码。 SJA1000的帧过滤验收码。对经过屏蔽码过滤为“有关位”进行匹配,全部匹配成功后,此帧可以被接收。否则不接收。
    public UInt32 AccMask;// 屏蔽码。 SJA1000的帧过滤屏蔽码。对接收的CAN帧ID进行过滤,对应位为0的是“有
                          // 关位”,对应位为1的是“无关位”。屏蔽码推荐设置为0xFFFFFFFF,即全部接收。
    public UInt32 Reserved;// 保留。
    public byte Filter;   //0或1接收所有帧。2标准帧滤波,3是扩展帧滤波。
    public byte Timing0;  //波特率参数,具体配置,请查看二次开发库函数说明书。  0x00,0x14
    public byte Timing1;    // 0x14
    public byte Mode;     //模式,0表示正常模式,1表示只听模式,2自测模式
}

/*------------其他数据结构描述---------------------------------*/
//4.USB-CAN总线适配器板卡信息的数据类型1,该类型为VCI_FindUsbDevice函数的返回参数。
public struct VCI_BOARD_INFO1
{
    public UInt16 hw_Version;// 硬件版本号,用16进制表示。比如0x0100表示V1.00。
    public UInt16 fw_Version;// 固件版本号, 
    public UInt16 dr_Version;// 驱动程序版本号,
    public UInt16 in_Version;// 接口库版本号,
    public UInt16 irq_Num;// 保留参数。
    public byte can_Num;// 表示有几路CAN通道。
    public byte Reserved;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=8)]
    public byte []str_Serial_Num;// 此板卡的序列号。
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
    public byte[] str_hw_Type;// 硬件类型,比如“USBCAN V1.00”(注意:包括字符串结束符’\0’)
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
    public byte[] str_Usb_Serial;
}

/*------------数据结构描述完成---------------------------------*/

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];
    }
}


namespace WindowsApplication1
{
    public partial class Form1 : Form
    {
        const int DEV_USBCAN = 3;
        const int DEV_USBCAN2 = 4;
         /// <summary>
        /// 
        /// </summary>
        /// <param name="DeviceType"></param>
        /// <param name="DeviceInd"></param>
        /// <param name="Reserved"></param>
        /// <returns></returns>
        /*------------兼容ZLG的函数描述---------------------------------*/
        [DllImport("controlcan.dll")]
        static extern UInt32 VCI_OpenDevice(UInt32 DeviceType, UInt32 DeviceInd, UInt32 Reserved);
        [DllImport("controlcan.dll")]
        static extern UInt32 VCI_CloseDevice(UInt32 DeviceType, UInt32 DeviceInd);
        [DllImport("controlcan.dll")]
        static extern UInt32 VCI_InitCAN(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_INIT_CONFIG pInitConfig);

        [DllImport("controlcan.dll")]
        static extern UInt32 VCI_ReadBoardInfo(UInt32 DeviceType, UInt32 DeviceInd, ref VCI_BOARD_INFO pInfo);

        [DllImport("controlcan.dll")]
        static extern UInt32 VCI_GetReceiveNum(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd);
        [DllImport("controlcan.dll")]
        static extern UInt32 VCI_ClearBuffer(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd);

        [DllImport("controlcan.dll")]
        static extern UInt32 VCI_StartCAN(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd);
        [DllImport("controlcan.dll")]
        static extern UInt32 VCI_ResetCAN(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd);

        [DllImport("controlcan.dll")]
        static extern UInt32 VCI_Transmit(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_CAN_OBJ pSend, UInt32 Len);

        [DllImport("controlcan.dll")]
        static extern UInt32 VCI_Receive(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_CAN_OBJ pReceive, UInt32 Len, Int32 WaitTime);
        
        /*------------其他函数描述---------------------------------*/

        [DllImport("controlcan.dll")]
        static extern UInt32 VCI_ConnectDevice(UInt32 DevType,UInt32 DevIndex);
        [DllImport("controlcan.dll")]
        static extern UInt32 VCI_UsbDeviceReset(UInt32 DevType,UInt32 DevIndex,UInt32 Reserved);
        [DllImport("controlcan.dll")]
        static extern UInt32 VCI_FindUsbDevice(ref VCI_BOARD_INFO1 pInfo);
        /*------------函数描述结束---------------------------------*/

        static UInt32 m_devtype = 4;//USBCAN2

        UInt32 m_bOpen = 0;
        UInt32 m_devind = 0;
        UInt32 m_canind = 0;

        VCI_CAN_OBJ[] m_recobj = new VCI_CAN_OBJ[1000];

        UInt32[] m_arrdevtype = new UInt32[20];

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            comboBox_DevIndex.SelectedIndex = 0;
            comboBox_CANIndex.SelectedIndex = 0;
            textBox_AccCode.Text = "00000000";
            textBox_AccMask.Text = "FFFFFFFF";
            textBox_Time0.Text = "00";
            textBox_Time1.Text = "1C";
            comboBox_Filter.SelectedIndex = 0;              //接收所有类型
            comboBox_Mode.SelectedIndex = 2;                //还回测试模式
            comboBox_FrameFormat.SelectedIndex = 0;
            comboBox_FrameType.SelectedIndex = 0;
            textBox_ID.Text = "00000123";
            textBox_Data.Text = "00 01 02 03 04 05 06 07 ";

            //
            Int32 curindex = 0;
            comboBox_devtype.Items.Clear();

            curindex = comboBox_devtype.Items.Add("DEV_USBCAN");
            m_arrdevtype[curindex] =  DEV_USBCAN;
            //comboBox_devtype.Items[2] = "VCI_USBCAN1";
            //m_arrdevtype[2]=  VCI_USBCAN1 ;

            curindex = comboBox_devtype.Items.Add("DEV_USBCAN2");
            m_arrdevtype[curindex] = DEV_USBCAN2 ;
            //comboBox_devtype.Items[3] = "VCI_USBCAN2";
            //m_arrdevtype[3]=  VCI_USBCAN2 ;

             comboBox_devtype.SelectedIndex = 1;
            comboBox_devtype.MaxDropDownItems = comboBox_devtype.Items.Count;

        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            if (m_bOpen==1)
            {
                VCI_CloseDevice(m_devtype, m_devind);
            }
        }

        private void buttonConnect_Click(object sender, EventArgs e)
        {//连接
            if (m_bOpen==1)
            {
                VCI_CloseDevice(m_devtype, m_devind);
                m_bOpen = 0;
            }
            else
            {
                m_devtype = m_arrdevtype[comboBox_devtype.SelectedIndex];

                m_devind=(UInt32)comboBox_DevIndex.SelectedIndex;
                m_canind = (UInt32)comboBox_CANIndex.SelectedIndex;
                if (VCI_OpenDevice(m_devtype, m_devind, 0) == 0)
                {
                    MessageBox.Show("打开设备失败,请检查设备类型和设备索引号是否正确", "错误",
                            MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    return;
                }

                m_bOpen = 1;
                VCI_INIT_CONFIG config=new VCI_INIT_CONFIG();
                config.AccCode=System.Convert.ToUInt32("0x" + textBox_AccCode.Text,16);
                config.AccMask = System.Convert.ToUInt32("0x" + textBox_AccMask.Text, 16);
                config.Timing0 = System.Convert.ToByte("0x" + textBox_Time0.Text, 16);
                config.Timing1 = System.Convert.ToByte("0x" + textBox_Time1.Text, 16);
                config.Filter = (Byte)(comboBox_Filter.SelectedIndex+1);
                config.Mode = (Byte)comboBox_Mode.SelectedIndex;
                VCI_InitCAN(m_devtype, m_devind, m_canind, ref config);
            }
            buttonConnect.Text = m_bOpen==1?"断开":"连接";
            timer_rec.Enabled = m_bOpen==1?true:false;
        }

        unsafe private void timer_rec_Tick(object sender, EventArgs e)
        {
            UInt32 res = new UInt32();

            // 接收(设备类型4,设备索引0,CAN通道索引0,VCI_CAN_OBJ数组的首指针,帧数2500,0)
            res = VCI_Receive(m_devtype, m_devind, m_canind, ref m_recobj[0],1000, 100);

            /
            //IntPtr[] ptArray = new IntPtr[1];
            //ptArray[0] = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(VCI_CAN_OBJ)) * 50);
            //IntPtr pt = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)) * 1);

            //Marshal.Copy(ptArray, 0, pt, 1);


            //res = VCI_Receive(m_devtype, m_devind, m_canind, pt, 50/*50*/, 100);
            
            if (res == 0xFFFFFFFF) res = 0;//当设备未初始化时,返回0xFFFFFFFF,不进行列表显示。
            String str = "";
            for (UInt32 i = 0; i < res; i++)
            {
                //VCI_CAN_OBJ obj = (VCI_CAN_OBJ)Marshal.PtrToStructure((IntPtr)((UInt32)pt + i * Marshal.SizeOf(typeof(VCI_CAN_OBJ))), typeof(VCI_CAN_OBJ));

                str = "接收到数据: ";
                str += "  帧ID:0x" + System.Convert.ToString(m_recobj[i].ID, 16);
                str += "  帧格式:";
                if (m_recobj[i].RemoteFlag == 0)
                    str += "数据帧 ";
                else
                    str += "远程帧 ";
                if (m_recobj[i].ExternFlag == 0)
                    str += "标准帧 ";
                else
                    str += "扩展帧 ";

                //
                if (m_recobj[i].RemoteFlag == 0)
                {
                    str += "数据: ";
                    byte len = (byte)(m_recobj[i].DataLen % 9);
                    byte j = 0;
                    fixed (VCI_CAN_OBJ* m_recobj1 = &m_recobj[i])
                    {
                        if (j++ < len)
                            str += " " + System.Convert.ToString(m_recobj1->Data[0], 16);
                        if (j++ < len)
                            str += " " + System.Convert.ToString(m_recobj1->Data[1], 16);
                        if (j++ < len)
                            str += " " + System.Convert.ToString(m_recobj1->Data[2], 16);
                        if (j++ < len)
                            str += " " + System.Convert.ToString(m_recobj1->Data[3], 16);
                        if (j++ < len)
                            str += " " + System.Convert.ToString(m_recobj1->Data[4], 16);
                        if (j++ < len)
                            str += " " + System.Convert.ToString(m_recobj1->Data[5], 16);
                        if (j++ < len)
                            str += " " + System.Convert.ToString(m_recobj1->Data[6], 16);
                        if (j++ < len)
                            str += " " + System.Convert.ToString(m_recobj1->Data[7], 16);
                    }
                }

                listBox_Info.Items.Add(str);
                listBox_Info.SelectedIndex = listBox_Info.Items.Count - 1;
            }
            //Marshal.FreeHGlobal(ptArray[0]);
            //Marshal.FreeHGlobal(pt);
        }

        private void button_StartCAN_Click(object sender, EventArgs e)
        {
            if (m_bOpen == 0)
                return;
            VCI_StartCAN(m_devtype, m_devind, m_canind);
        }

        private void button_StopCAN_Click(object sender, EventArgs e)
        {
            if (m_bOpen == 0)
                return;
            VCI_ResetCAN(m_devtype, m_devind, m_canind);
        }

        unsafe private void button_Send_Click(object sender, EventArgs e)
        {
            if(m_bOpen==0)
                return;

            VCI_CAN_OBJ sendobj = new VCI_CAN_OBJ();
            //sendobj.Init();
            sendobj.RemoteFlag = (byte)comboBox_FrameFormat.SelectedIndex;
            sendobj.ExternFlag = (byte)comboBox_FrameType.SelectedIndex;
            sendobj.ID = System.Convert.ToUInt32("0x"+textBox_ID.Text,16);
            int len = (textBox_Data.Text.Length+1) / 3;
            sendobj.DataLen =System.Convert.ToByte(len);
            String strdata = textBox_Data.Text;
            int i=-1;
            if(i++<len-1)
                sendobj.Data[0]=System.Convert.ToByte("0x" +strdata.Substring(i * 3, 2),16);
            if (i++ < len - 1)
                sendobj.Data[1]=System.Convert.ToByte("0x" +strdata.Substring(i * 3, 2),16);
            if (i++ < len - 1)
                sendobj.Data[2]=System.Convert.ToByte("0x" +strdata.Substring(i * 3, 2),16);
            if (i++ < len - 1)
                sendobj.Data[3]=System.Convert.ToByte("0x" +strdata.Substring(i * 3, 2),16);
            if (i++ < len - 1)
                sendobj.Data[4]=System.Convert.ToByte("0x" +strdata.Substring(i * 3, 2),16);
            if (i++ < len - 1)
                sendobj.Data[5]=System.Convert.ToByte("0x" +strdata.Substring(i * 3, 2),16);
            if (i++ < len - 1)
                sendobj.Data[6]=System.Convert.ToByte("0x" +strdata.Substring(i * 3, 2),16);
            if (i++ < len - 1)
                sendobj.Data[7] = System.Convert.ToByte("0x" + strdata.Substring(i * 3, 2), 16);

            if(VCI_Transmit(m_devtype,m_devind,m_canind,ref sendobj,1)==0)
            {
                MessageBox.Show("发送失败", "错误",
                        MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
        }

        private void button_Clear_Click(object sender, EventArgs e)
        {
            listBox_Info.Items.Clear();
        }

    }
}

库函数   VCI_

关闭函数

VCI_CloseDevice(m_devtype, m_devind);// 4,0

static UInt32 m_devtype = 4;//USBCAN2
UInt32 m_devind = 0;

连接: 

VCI_OpenDevice       打开硬件设备
#include "ControlCan.h"
int nDeviceType = 4; /* USBCAN-2A或USBCAN-2C或CANalyst-II */
int nDeviceInd = 0; /* 第1个设备 */
DWORD dwRel;
dwRel = VCI_OpenDevice(nDeviceType, nDeviceInd, 0);
if(dwRel != 1)
{
MessageBox(_T("打开设备失败!"), _T("警告"), MB_OK|MB_ICONQUESTION);
return FALSE;
}

if (VCI_OpenDevice(m_devtype, m_devind, 0) == 0)

VCI_InitCAN(m_devtype, m_devind, m_canind, ref config);

timer_rec.Enabled = m_bOpen==1?true:false;     //  开启定时器

else
            {
                m_devtype = m_arrdevtype[comboBox_devtype.SelectedIndex];

                m_devind=(UInt32)comboBox_DevIndex.SelectedIndex;
                m_canind = (UInt32)comboBox_CANIndex.SelectedIndex;
                if (VCI_OpenDevice(m_devtype, m_devind, 0) == 0)
                {
                    MessageBox.Show("打开设备失败,请检查设备类型和设备索引号是否正确", "错误",
                            MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    return;
                }

                m_bOpen = 1;
                VCI_INIT_CONFIG config=new VCI_INIT_CONFIG();
                config.AccCode=System.Convert.ToUInt32("0x" + textBox_AccCode.Text,16);
                config.AccMask = System.Convert.ToUInt32("0x" + textBox_AccMask.Text, 16);
                config.Timing0 = System.Convert.ToByte("0x" + textBox_Time0.Text, 16);
                config.Timing1 = System.Convert.ToByte("0x" + textBox_Time1.Text, 16);
                config.Filter = (Byte)(comboBox_Filter.SelectedIndex+1);
                config.Mode = (Byte)comboBox_Mode.SelectedIndex;
                VCI_InitCAN(m_devtype, m_devind, m_canind, ref config);
            }
            buttonConnect.Text = m_bOpen==1?"断开":"连接";
            timer_rec.Enabled = m_bOpen==1?true:false;
        }

初始化CAN: 

VCI_InitCAN

需要用到配置表:   VCI_INIT_CONFIG 

CAN启动:VCI_StartCAN

 private void button_StartCAN_Click(object sender, EventArgs e)
        {
            if (m_bOpen == 0)
                return;
            VCI_StartCAN(m_devtype, m_devind, m_canind);
          // 启动CAN通道(设备类型4,设备索引0,CAN通道索引0) return 1成功
        }

复位CAN

private void button_StopCAN_Click(object sender, EventArgs e)
        {
            if (m_bOpen == 0)
                return;
            VCI_ResetCAN(m_devtype, m_devind, m_canind);
        }

CAN发送

 unsafe private void button_Send_Click(object sender, EventArgs e)
        {
            if(m_bOpen==0)
                return;

            VCI_CAN_OBJ sendobj = new VCI_CAN_OBJ();
            //sendobj.Init();
            sendobj.RemoteFlag = (byte)comboBox_FrameFormat.SelectedIndex;
            sendobj.ExternFlag = (byte)comboBox_FrameType.SelectedIndex;
            sendobj.ID = System.Convert.ToUInt32("0x"+textBox_ID.Text,16);
            int len = (textBox_Data.Text.Length+1) / 3;
            sendobj.DataLen =System.Convert.ToByte(len);
            String strdata = textBox_Data.Text;
            int i=-1;
            if(i++<len-1)
                sendobj.Data[0]=System.Convert.ToByte("0x" +strdata.Substring(i * 3, 2),16);
            if (i++ < len - 1)
                sendobj.Data[1]=System.Convert.ToByte("0x" +strdata.Substring(i * 3, 2),16);
            if (i++ < len - 1)
                sendobj.Data[2]=System.Convert.ToByte("0x" +strdata.Substring(i * 3, 2),16);
            if (i++ < len - 1)
                sendobj.Data[3]=System.Convert.ToByte("0x" +strdata.Substring(i * 3, 2),16);
            if (i++ < len - 1)
                sendobj.Data[4]=System.Convert.ToByte("0x" +strdata.Substring(i * 3, 2),16);
            if (i++ < len - 1)
                sendobj.Data[5]=System.Convert.ToByte("0x" +strdata.Substring(i * 3, 2),16);
            if (i++ < len - 1)
                sendobj.Data[6]=System.Convert.ToByte("0x" +strdata.Substring(i * 3, 2),16);
            if (i++ < len - 1)
                sendobj.Data[7] = System.Convert.ToByte("0x" + strdata.Substring(i * 3, 2), 16);

            if(VCI_Transmit(m_devtype,m_devind,m_canind,ref sendobj,1)==0)
            {
                MessageBox.Show("发送失败", "错误",
                        MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
        }

接收显示

res = VCI_Receive(m_devtype, m_devind, m_canind, ref m_recobj[0],1000, 100);

 unsafe private void timer_rec_Tick(object sender, EventArgs e)
        {
            UInt32 res = new UInt32();

            res = VCI_Receive(m_devtype, m_devind, m_canind, ref m_recobj[0],1000, 100);

            /
            //IntPtr[] ptArray = new IntPtr[1];
            //ptArray[0] = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(VCI_CAN_OBJ)) * 50);
            //IntPtr pt = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)) * 1);

            //Marshal.Copy(ptArray, 0, pt, 1);


            //res = VCI_Receive(m_devtype, m_devind, m_canind, pt, 50/*50*/, 100);
            
            if (res == 0xFFFFFFFF) res = 0;//当设备未初始化时,返回0xFFFFFFFF,不进行列表显示。
            String str = "";
            for (UInt32 i = 0; i < res; i++)
            {
                //VCI_CAN_OBJ obj = (VCI_CAN_OBJ)Marshal.PtrToStructure((IntPtr)((UInt32)pt + i * Marshal.SizeOf(typeof(VCI_CAN_OBJ))), typeof(VCI_CAN_OBJ));

                str = "接收到数据: ";
                str += "  帧ID:0x" + System.Convert.ToString(m_recobj[i].ID, 16);
                str += "  帧格式:";
                if (m_recobj[i].RemoteFlag == 0)
                    str += "数据帧 ";
                else
                    str += "远程帧 ";
                if (m_recobj[i].ExternFlag == 0)
                    str += "标准帧 ";
                else
                    str += "扩展帧 ";

                //
                if (m_recobj[i].RemoteFlag == 0)
                {
                    str += "数据: ";
                    byte len = (byte)(m_recobj[i].DataLen % 9);
                    byte j = 0;
                    fixed (VCI_CAN_OBJ* m_recobj1 = &m_recobj[i])
                    {
                        if (j++ < len)
                            str += " " + System.Convert.ToString(m_recobj1->Data[0], 16);
                        if (j++ < len)
                            str += " " + System.Convert.ToString(m_recobj1->Data[1], 16);
                        if (j++ < len)
                            str += " " + System.Convert.ToString(m_recobj1->Data[2], 16);
                        if (j++ < len)
                            str += " " + System.Convert.ToString(m_recobj1->Data[3], 16);
                        if (j++ < len)
                            str += " " + System.Convert.ToString(m_recobj1->Data[4], 16);
                        if (j++ < len)
                            str += " " + System.Convert.ToString(m_recobj1->Data[5], 16);
                        if (j++ < len)
                            str += " " + System.Convert.ToString(m_recobj1->Data[6], 16);
                        if (j++ < len)
                            str += " " + System.Convert.ToString(m_recobj1->Data[7], 16);
                    }
                }

                listBox_Info.Items.Add(str);
                listBox_Info.SelectedIndex = listBox_Info.Items.Count - 1;
            }
            //Marshal.FreeHGlobal(ptArray[0]);
            //Marshal.FreeHGlobal(pt);
        }

定时器

private System.Windows.Forms.Timer timer_rec;

最后:

参数类型定义错误会导致接口函数工作不正常。用我调试好的参数类型

创芯USB_CAN【二次开发】-CSDN博客

你复制 :3二次开发库文件【C#】

  • 5
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值