基于创芯CAN分析仪ControlCAN.dll的C#二次开发库

1.API

class API
    {
        /*------------兼容ZLG的函数描述---------------------------------*/
        [DllImport("controlcan.dll")]
        public static extern UInt32 VCI_OpenDevice(UInt32 DeviceType, UInt32 DeviceInd, UInt32 Reserved);
        [DllImport("controlcan.dll")]
        public static extern UInt32 VCI_CloseDevice(UInt32 DeviceType, UInt32 DeviceInd);
        [DllImport("controlcan.dll")]
        public static extern UInt32 VCI_InitCAN(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_INIT_CONFIG pInitConfig);

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

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

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

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

        [DllImport("controlcan.dll")]
        public static extern UInt32 VCI_Receive(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_CAN_OBJ pReceive, UInt32 Len, Int32 WaitTime);

        /*------------其他函数描述---------------------------------*/

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

2.C# 与C++对应的数据模型

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

    //1.ZLGCAN系列接口卡信息的数据类型。
    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;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
        public byte[] str_Serial_Num;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)]
        public byte[] str_hw_Type;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
        public byte[] Reserved;
    }

    /
    //2.定义CAN信息帧的数据类型。
    unsafe public struct VCI_CAN_OBJ  //使用不安全代码
    {
        public uint ID;
        public uint TimeStamp;        //时间标识
        public byte TimeFlag;         //是否使用时间标识
        public byte SendType;         //发送标志。保留,未用
        public byte RemoteFlag;       //是否是远程帧
        public byte ExternFlag;       //是否是扩展帧
        public byte DataLen;          //数据长度
        public fixed byte Data[8];    //数据
        public fixed byte Reserved[3];//保留位

    }

    //3.定义初始化CAN的数据类型
    public struct VCI_INIT_CONFIG
    {
        public UInt32 AccCode;
        public UInt32 AccMask;
        public UInt32 Reserved;
        public byte Filter;   //0或1接收所有帧。2标准帧滤波,3是扩展帧滤波。
        public byte Timing0;  //波特率参数,具体配置,请查看二次开发库函数说明书。
        public byte Timing1;
        public byte Mode;     //模式,0表示正常模式,1表示只听模式,2自测模式
    }

    /*------------其他数据结构描述---------------------------------*/
    //4.USB-CAN总线适配器板卡信息的数据类型1,该类型为VCI_FindUsbDevice函数的返回参数。
    public struct VCI_BOARD_INFO1
    {
        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 byte Reserved;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] str_Serial_Num;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
        public byte[] str_hw_Type;
        [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];
        }
    }

    public enum DevType
    {
        DEV_USBCAN = 3,
        DEV_USBCAN2 = 4
    }

    public class Data
    {

        public static Dictionary<int, byte[]> Bitrate = new Dictionary<int, byte[]>()
        {
            {10000,    new byte[]{0x31,0x1C}},
            {20000,    new byte[]{0x18,0x1C}},
            {40000,    new byte[]{0x87,0xFF}},
            {50000,    new byte[]{0x09,0x1C}},
            {80000,    new byte[]{0x83,0xFF}},
            {100000,   new byte[]{0x04,0x1C}},
            {125000,   new byte[]{0x03,0x1C}},
            {200000,   new byte[]{0x81,0xFA}},
            {250000,   new byte[]{0x01,0x1C}},
            {400000,   new byte[]{0x80,0xFA}},
            {500000,   new byte[]{0x00,0x1C}},
            {666000,   new byte[]{0x80,0xB6}},
            {800000,   new byte[]{0x00,0x16}},
            {1000000,  new byte[]{0x00,0x14}},
            {33330, new byte[]{0x09,0x6F}},
            {66660, new byte[]{0x04,0x6F}},
            {83330, new byte[]{0x03,0x6F}},
        };

    }

3. C#动态库实现

    /// <summary>
    /// 珠海创芯科技CAN总线分析仪
    /// </summary>
    public class CAN_zhcxgd : InterfaceCAN
    {
        private readonly object lock_send = new object();
        private VCI_CAN_OBJ[] _vCI_CAN_OBJs = new VCI_CAN_OBJ[2500];
        private DevType _devType = DevType.DEV_USBCAN2;
        private uint _devIndex = 0;
        private int _bitrate;
        public byte[] Bitrate { get => Data.Bitrate[_bitrate]; }
        public uint int_DevType { get => (uint)_devType; }
        public uint ChannelCount { get => _devType == DevType.DEV_USBCAN ? (uint)1 : (uint)2; }

        public void SetParameters(int devIndex, int bitrate, params object[] parms)
        {
            _devIndex = (uint)devIndex;
            _bitrate = bitrate;
        }
        public bool Close()
        {
            var result = API.VCI_CloseDevice(int_DevType, _devIndex);
            return result == 1;
        }

        public bool Open()
        {
            var result = API.VCI_OpenDevice(int_DevType, _devIndex, 0) == 1;
            if (!result)
                return false;

            result = Start(Bitrate);
            if (!result)
                return false;

            return true;
        }


        public bool Send(FrameData frameData)
        {
            lock (lock_send)
            {
                VCI_CAN_OBJ vCI_CAN_OBJ = new VCI_CAN_OBJ();
                vCI_CAN_OBJ.RemoteFlag = frameData.RemoteFlag;
                vCI_CAN_OBJ.ExternFlag = frameData.ExternFlag;
                vCI_CAN_OBJ.ID = (uint)frameData.Id;
                vCI_CAN_OBJ.DataLen = frameData.DataLen;

                WriteUnsafeData(ref vCI_CAN_OBJ, frameData.Data);

                var result = API.VCI_Transmit(int_DevType, _devIndex, (uint)frameData.ChannelId, ref vCI_CAN_OBJ, 1);

                return result == 1;
            }

        }

        public List<FrameData> Receive()
        {
            List<FrameData> frameDatas = new List<FrameData>();
            for (int i = 0; i < ChannelCount; i++)
            {
                frameDatas.AddRange(Receive((uint)i));
            }
            return frameDatas;
        }

        private List<FrameData> Receive(uint channelId)
        {
            var result = API.VCI_Receive(int_DevType, _devIndex, channelId, ref _vCI_CAN_OBJs[0], 2500, 100);

            if (result < 0)
                return null;

            List<FrameData> receiveDatas = new List<FrameData>();

            for (int i = 0; i < result; i++)
            {
                FrameData receiveData = new FrameData();
                receiveData.ChannelId = (int)channelId;
                receiveData.Id = (int)_vCI_CAN_OBJs[i].ID;
                receiveData.DataLen = _vCI_CAN_OBJs[i].DataLen;
                receiveData.Data = ReadUnsafeData(ref _vCI_CAN_OBJs[i]);
                receiveData.TimeStamp = (long)_vCI_CAN_OBJs[i].TimeStamp;
                receiveData.RemoteFlag = _vCI_CAN_OBJs[i].RemoteFlag;
                receiveData.ExternFlag = _vCI_CAN_OBJs[i].ExternFlag;
                receiveData.SendType = _vCI_CAN_OBJs[i].SendType;
                receiveData.TimeFlag = _vCI_CAN_OBJs[i].TimeFlag;

                unsafe
                {
                    receiveData.Reserved = new byte[3];
                    receiveData.Reserved[0] = _vCI_CAN_OBJs[i].Reserved[0];
                    receiveData.Reserved[1] = _vCI_CAN_OBJs[i].Reserved[1];
                    receiveData.Reserved[2] = _vCI_CAN_OBJs[i].Reserved[2];
                }

                receiveDatas.Add(receiveData);
            }

            return receiveDatas;
        }

        unsafe private void WriteUnsafeData(ref VCI_CAN_OBJ data, byte[] buffer)
        {
            fixed (byte* ptr = data.Data)
                for (int i = 0; i < buffer.Length; i++)
                {
                    ptr[i] = buffer[i];
                }
        }

        unsafe private byte[] ReadUnsafeData(ref VCI_CAN_OBJ data)
        {
            var buffer = new byte[data.DataLen];
            fixed (byte* ptr = data.Data)
                for (int index = 0; index < data.DataLen; index++)
                {
                    buffer[index] = ptr[index];
                }
            return buffer;

        }

        /// <summary>
        /// 启动CAN 
        /// </summary>
        /// <param name="bitrate"></param>
        /// <returns></returns>
        private bool Start(byte[] bitrate)
        {

            for (uint i = 0; i < ChannelCount; i++)
            {
                if (!Init(i, bitrate))
                    return false;

                if (!Start(i))
                    return false;
            }

            return true;
        }

        private bool Init(uint channelNum, byte[] bitrate)
        {
            VCI_INIT_CONFIG config = new VCI_INIT_CONFIG();
            config.AccCode = Convert.ToUInt32("0x00000000", 16);
            config.AccMask = Convert.ToUInt32("0xFFFFFFFF", 16);
            config.Timing0 = bitrate[0];
            config.Timing1 = bitrate[1];
            config.Filter = 1;
            config.Mode = 0;
            var result = API.VCI_InitCAN(int_DevType, _devIndex, channelNum, ref config);
            return result == 1;
        }

        private bool Start(uint channelNum)
        {
            var result = API.VCI_StartCAN(int_DevType, _devIndex, channelNum);
            return result == 1;
        }

    }

4.使用

 static void Main(string[] args)
        {
            CAN_zhcxgd cAN_Zhcxgd = new CAN_zhcxgd();
            cAN_Zhcxgd.SetParameters(0, 100000);
            cAN_Zhcxgd.Open();

            cAN_Zhcxgd.Send(new FrameData() { ChannelId = 0, Id = 1, Data = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }, DataLen = 8 });

            List<FrameData> frameDatas = cAN_Zhcxgd.Receive();
            foreach (FrameData frameData in frameDatas)
            {
                //做点什么
            }
        }

5.源码以及CANPlus.cs(自用dll)

源码

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值