diff --git a/CANHelper/ControlCAN.dll b/CANHelper/ControlCAN.dll
new file mode 100644
index 0000000..daf472a
Binary files /dev/null and b/CANHelper/ControlCAN.dll differ
diff --git a/CANHelper/USBCAN/CANHelper.cs b/CANHelper/USBCAN/CANHelper.cs
new file mode 100644
index 0000000..4e0bf77
--- /dev/null
+++ b/CANHelper/USBCAN/CANHelper.cs
@@ -0,0 +1,346 @@
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Threading;
+
+namespace USBCAN
+{
+ ///
+ /// CAN帮助类
+ ///
+ ///
+ /// 使用方法:
+ ///
+ /// CANHelper.Instance.Initialize(); // 在首次使用时需要初始化,初始化失败时会抛出异常
+ /// CANHelper.Instance.ConsumptionFrameEvent += (CAN_API.VCI_CAN_OBJ frame){ /* TODO:在这里消费掉数据帧,注意,这里是异步调用 */ }
+ /// CANHelper.Instance.SendData(0x1111, data); // 向CAN发送数据,具体方法参阅注释
+ ///
+ ///
+ public sealed class CANHelper : IDisposable
+ {
+ ///
+ /// CAN实例
+ ///
+ public static readonly CANHelper Instance = new CANHelper();
+
+ #region 公开属性
+ ///
+ /// CAN是否打开
+ ///
+ public bool IsOpen { private set; get; } = false;
+ #endregion
+
+ #region 释放
+ ///
+ /// Flag: 标识Disposed是否已经被调用
+ ///
+ private bool _IsDisposed = false;
+
+ ///
+ /// 公开的Dispose方法
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// 实际Dispose方法
+ ///
+ /// 是否由用户调用
+ private void Dispose(bool disposing)
+ {
+ if (_IsDisposed)
+ return;
+
+ if (disposing)
+ {
+ // 释放托管成员
+ }
+
+ // 释放非托管成员
+
+ // 关闭CAN设备
+ CloseDevice();
+
+ // 标识为已执行Dispose
+ _IsDisposed = true;
+ }
+
+ ///
+ /// 析构
+ ///
+ ~CANHelper()
+ {
+ // 释放非托管内存
+ Dispose(false);
+ }
+ #endregion
+
+ #region 打开与关闭
+ ///
+ /// 初始化并打开CAN设备
+ ///
+ public void Initialize()
+ {
+ // 如果已经打开,直接返回
+ if (IsOpen)
+ return;
+
+ // 打开设备
+ if (CAN_API.VCI_OpenDevice(_DeviceType, _DeviceInd, _CANInd) == CAN_API.STATUS_ERR)
+ throw new Exception("CAN设备打开失败,错误信息:" + ReadErrorMessage());
+
+ // 构造CAN配置信息
+ CAN_API.VCI_INIT_CONFIG pInitConfig = new CAN_API.VCI_INIT_CONFIG
+ {
+ AccCode = 0x00000000, // 表示全部接收(全部接收: AccCode:0x00000000)
+ AccMask = 0xFFFFFFFF, // ( AccMask:0xFFFFFFFF)
+ Reserved = 0x00, // 保留,填0
+ Filter = 0x01, // 滤波方式 01
+ Timing0 = 0x01, // ( 相当于波特率1000kbps )
+ Timing1 = 0x14, // ( 相当于波特率1000kbps )
+ Mode = 0x00 // 正常模式; 0:正常模式,可以IO。 1:表示只听模式(只接收,不影响总线)
+ };
+ // 初始化CAN
+ if (CAN_API.VCI_InitCAN(_DeviceType, _DeviceInd, _CANInd, ref pInitConfig) == CAN_API.STATUS_ERR)
+ throw new Exception("CAN初始化失败,错误信息:" + ReadErrorMessage());
+
+ // 启动CAN
+ if (CAN_API.VCI_StartCAN(_DeviceType, _DeviceInd, _CANInd) == CAN_API.STATUS_ERR)
+ throw new Exception("CAN启动失败,错误信息:" + ReadErrorMessage());
+
+ // 若未出错,标识打开
+ IsOpen = true;
+
+ // 初始化消息帧缓冲区,上限为128帧报文,若满了还未消费则阻塞
+ _FrameBuffer = new BlockingCollection(128);
+
+ // 生产者消费者开始工作
+ StartWork();
+ }
+
+ ///
+ /// 关闭CAN设备
+ ///
+ public void CloseDevice()
+ {
+ if (IsOpen)
+ {
+ // 关闭设备
+ if (CAN_API.VCI_CloseDevice(_DeviceType, _DeviceInd) == CAN_API.STATUS_ERR)
+ throw new Exception("CAN设备关闭失败,错误信息:" + ReadErrorMessage());
+
+ IsOpen = false;
+ }
+ }
+ #endregion
+
+ #region 公开方法
+ ///
+ /// 读取错误信息
+ ///
+ ///
+ public string ReadErrorMessage()
+ {
+ CAN_API.VCI_ERR_INFO errInfo = new CAN_API.VCI_ERR_INFO();
+ try
+ {
+ // 尝试读取错误信息
+ if (CAN_API.VCI_ReadErrInfo(_DeviceType, _DeviceInd, _CANInd, ref errInfo) == CAN_API.STATUS_ERR)
+ return "读取错误信息失败";
+ }
+ catch (Exception ex)
+ {
+ return string.Format("读取错误信息时发生异常({0})", ex.Message);
+ }
+
+ if (errInfo.ErrCode == 0x00)
+ {
+ // 若无错误信息,则返回‘无错误信息’
+ return "无错误信息";
+ }
+
+ // 由于可能同时出现多种错误,使用按位与的方式读取错误信息
+ List errMsgList = new List();
+ if ((errInfo.ErrCode & (uint)CAN_API.ErrorType.ERR_CAN_OVERFLOW) != 0)
+ errMsgList.Add("CAN控制器内部FIFO溢出");
+ if ((errInfo.ErrCode & (uint)CAN_API.ErrorType.ERR_CAN_ERRALARM) != 0)
+ errMsgList.Add("CAN控制器错误报警");
+ if ((errInfo.ErrCode & (uint)CAN_API.ErrorType.ERR_CAN_PASSIVE) != 0)
+ errMsgList.Add("CAN控制器消极错误");
+ if ((errInfo.ErrCode & (uint)CAN_API.ErrorType.ERR_CAN_LOSE) != 0)
+ errMsgList.Add("CAN控制器仲裁丢失");
+ if ((errInfo.ErrCode & (uint)CAN_API.ErrorType.ERR_CAN_BUSERR) != 0)
+ errMsgList.Add("CAN控制器总线错误");
+ if ((errInfo.ErrCode & (uint)CAN_API.ErrorType.ERR_DEVICEOPENED) != 0)
+ errMsgList.Add("设备已经打开");
+ if ((errInfo.ErrCode & (uint)CAN_API.ErrorType.ERR_DEVICEOPEN) != 0)
+ errMsgList.Add("打开设备错误");
+ if ((errInfo.ErrCode & (uint)CAN_API.ErrorType.ERR_DEVICENOTOPEN) != 0)
+ errMsgList.Add("设备没有打开");
+ if ((errInfo.ErrCode & (uint)CAN_API.ErrorType.ERR_BUFFEROVERFLOW) != 0)
+ errMsgList.Add("缓冲区溢出");
+ if ((errInfo.ErrCode & (uint)CAN_API.ErrorType.ERR_DEVICENOTEXIST) != 0)
+ errMsgList.Add("此设备不存在");
+ if ((errInfo.ErrCode & (uint)CAN_API.ErrorType.ERR_LOADKERNELDLL) != 0)
+ errMsgList.Add("装载动态库失败");
+ if ((errInfo.ErrCode & (uint)CAN_API.ErrorType.ERR_CMDFAILED) != 0)
+ errMsgList.Add("执行命令失败");
+ if ((errInfo.ErrCode & (uint)CAN_API.ErrorType.ERR_BUFFERCREATE) != 0)
+ errMsgList.Add("内存不足");
+
+ if (errMsgList.Count == 0)
+ {
+ // 若未检测到错误信息,则返回‘未知错误’
+ return "未知错误";
+ }
+ else
+ {
+ // 否则将错误信息以'|'拼接返回
+ return string.Join("|", errMsgList);
+ }
+ }
+
+ ///
+ /// 向CAN发送数据帧
+ ///
+ /// 发送帧ID
+ /// 数据数组(数组长度必须为8)
+ public void SendData(uint frameID, byte[] data)
+ {
+ CAN_API.VCI_CAN_OBJ frameInfo = new CAN_API.VCI_CAN_OBJ
+ {
+ ID = frameID, // 帧ID
+ SendType = 0, // 正常发送
+ RemoteFlag = 0, // 非远程帧
+ ExternFlag = 0, // 非扩展帧
+ DataLen = 8, // 数据长度
+ Data = data, // 数据
+ Reserved = new byte[3] // 预留
+ };
+ SendData(frameInfo);
+ }
+
+ ///
+ /// 向CAN发送数据帧
+ ///
+ /// 帧信息
+ public void SendData(CAN_API.VCI_CAN_OBJ frameInfo)
+ {
+ // 发送一帧数据
+ if (CAN_API.VCI_Transmit(_DeviceType, _DeviceInd, _CANInd, ref frameInfo, 1) == CAN_API.STATUS_ERR)
+ throw new Exception("数据发送失败,错误信息:" + ReadErrorMessage());
+ }
+
+ #endregion
+
+ #region 生产者消费者模式 - 生产数据帧,发出事件消费数据帧
+ ///
+ /// 帧缓冲区(生产者消费者队列)
+ ///
+ private BlockingCollection _FrameBuffer;
+ ///
+ /// 生产者线程
+ ///
+ private Thread _ProducerThread;
+ ///
+ /// 消费者线程
+ ///
+ private Thread _ConsumerThread;
+ ///
+ /// 消费帧事件委托
+ ///
+ /// 报文帧
+ public delegate void ConsumptionFrameEventHandler(CAN_API.VCI_CAN_OBJ frame);
+ ///
+ /// 消费帧事件
+ ///
+ public event ConsumptionFrameEventHandler ConsumptionFrameEvent;
+
+ ///
+ /// 开始工作线程
+ ///
+ private void StartWork()
+ {
+ // 启动生产者与消费者线程
+ // 优先级设置为高
+
+ _ProducerThread = new Thread(new ThreadStart(Producer))
+ {
+ IsBackground = true,
+ Priority = ThreadPriority.Highest
+ };
+ _ConsumerThread = new Thread(new ThreadStart(Consumer))
+ {
+ IsBackground = true,
+ Priority = ThreadPriority.Highest
+ };
+ _ProducerThread.Start();
+ _ConsumerThread.Start();
+ }
+
+ ///
+ /// 生产者
+ ///
+ private void Producer()
+ {
+ // 分配一个缓冲区,最大能同时容纳100帧数据
+ IntPtr readBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(CAN_API.VCI_CAN_OBJ)) * 100); ;
+ while (IsOpen)
+ {
+ // var n = CAN_API.VCI_GetReceiveNum(_DeviceType, _DeviceInd, _CANInd);
+ // 接收数据,超时时间100ms,最大接收100个
+ uint len = CAN_API.VCI_Receive(_DeviceType, _DeviceInd, _CANInd, readBuffer, 100, 100);
+
+ if (len == 0)
+ {
+ // 如果未读到数据,读取错误信息
+ ReadErrorMessage();
+ }
+ else
+ {
+ // 将读取到的每一帧数据构造帧对象VCI_CAN_OBJ,装入帧缓冲区中(生产产品到库存)
+ for (int i = 0; i < len; i++)
+ {
+ // 实例化帧对象,装入帧缓冲区
+ _FrameBuffer.Add((CAN_API.VCI_CAN_OBJ)Marshal.PtrToStructure((IntPtr)((uint)readBuffer + i * Marshal.SizeOf(typeof(CAN_API.VCI_CAN_OBJ))), typeof(CAN_API.VCI_CAN_OBJ)));
+ }
+ }
+ }
+ }
+
+ ///
+ /// 消费者
+ ///
+ private void Consumer()
+ {
+ while (IsOpen)
+ {
+ // 从队列中获取帧(该方法会线程安全的阻塞,当有数据装入时立刻返回)
+ var frame = _FrameBuffer.Take();
+ // 消费帧
+ if (ConsumptionFrameEvent != null)
+ ConsumptionFrameEvent(frame);
+ }
+ }
+ #endregion
+
+ #region 私有成员
+ ///
+ /// 设备类型
+ ///
+ private const uint _DeviceType = (uint)CAN_API.PCIDeviceType.VCI_USBCAN1;
+ ///
+ /// 设备ID
+ ///
+ private const uint _DeviceInd = 0;
+ ///
+ /// 第几路CAN
+ ///
+ private const uint _CANInd = 0;
+ #endregion
+ }
+}
diff --git a/CANHelper/USBCAN/CAN_API.cs b/CANHelper/USBCAN/CAN_API.cs
new file mode 100644
index 0000000..a111c98
--- /dev/null
+++ b/CANHelper/USBCAN/CAN_API.cs
@@ -0,0 +1,262 @@
+using System;
+using System.Runtime.InteropServices;
+
+
+namespace USBCAN
+{
+ public sealed class CAN_API
+ {
+ #region 数据类型定义
+ ///
+ /// 接口卡类型定义
+ ///
+ public enum PCIDeviceType
+ {
+ VCI_PCI5121 = 1,
+ VCI_PCI9810 = 2,
+ VCI_USBCAN1 = 3,
+ VCI_USBCAN2 = 4,
+ VCI_PCI9820 = 5,
+ VCI_CAN232 = 6,
+ VCI_PCI5110 = 7,
+ VCI_CANLITE = 8,
+ VCI_ISA9620 = 9,
+ VCI_ISA5420 = 10,
+ VCI_PC104CAN = 11,
+ VCI_CANETE = 12,
+ VCI_DNP9810 = 13,
+ VCI_PCI9840 = 14,
+ VCI_PCI9820I = 16
+ }
+
+ //函数调用返回状态值
+ ///
+ /// 正常状态
+ ///
+ public static readonly int STATUS_OK = 1;
+ ///
+ /// 发生错误
+ ///
+ public static readonly int STATUS_ERR = 0;
+
+ ///
+ /// 错误类型
+ ///
+ public enum ErrorType
+ {
+ // --------------- CAN错误码 -------------------
+ ///
+ /// CAN错误码:CAN控制器内部FIFO溢出
+ ///
+ ERR_CAN_OVERFLOW = 0x0001,
+ ///
+ /// CAN错误码:CAN控制器错误报警
+ ///
+ ERR_CAN_ERRALARM = 0x0002,
+ ///
+ /// CAN错误码:CAN控制器消极错误
+ ///
+ ERR_CAN_PASSIVE = 0x0004,
+ ///
+ /// CAN错误码:CAN控制器仲裁丢失
+ ///
+ ERR_CAN_LOSE = 0x0008,
+ ///
+ /// CAN错误码:CAN控制器总线错误
+ ///
+ ERR_CAN_BUSERR = 0x0010,
+
+ // --------------- 通用错误码 -------------------
+ ///
+ /// 通用错误码:设备已经打开
+ ///
+ ERR_DEVICEOPENED = 0x0100,
+ ///
+ /// 通用错误码:打开设备错误
+ ///
+ ERR_DEVICEOPEN = 0x0200,
+ ///
+ /// 通用错误码:设备没有打开
+ ///
+ ERR_DEVICENOTOPEN = 0x0400,
+ ///
+ /// 通用错误码:缓冲区溢出
+ ///
+ ERR_BUFFEROVERFLOW = 0x0800,
+ ///
+ /// 通用错误码:此设备不存在
+ ///
+ ERR_DEVICENOTEXIST = 0x1000,
+ ///
+ /// 通用错误码:装载动态库失败
+ ///
+ ERR_LOADKERNELDLL = 0x2000,
+ ///
+ /// 通用错误码:执行命令失败错误码
+ ///
+ ERR_CMDFAILED = 0x4000,
+ ///
+ /// 通用错误码:内存不足
+ ///
+ ERR_BUFFERCREATE = 0x8000
+ }
+
+ ///
+ /// ZLGCAN系列接口卡信息
+ ///
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ public struct VCI_BOARD_INFO
+ {
+ public ushort hw_Version;
+ public ushort fw_Version;
+ public ushort dr_Version;
+ public ushort in_Version;
+ public ushort irq_Num;
+ public byte can_Num;
+ [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst = 20)]
+ public string str_Serial_Num;
+ [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst = 40)]
+ public string str_hw_Type;
+ [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = System.Runtime.InteropServices.UnmanagedType.U2)]
+ public ushort[] Reserved;
+ }
+
+ ///
+ /// CAN信息帧
+ ///
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ 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;
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8, ArraySubType = UnmanagedType.I1)]
+ public byte[] Data;
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3, ArraySubType = UnmanagedType.I1)]
+ public byte[] Reserved;
+ }
+
+ ///
+ /// CAN控制器状态
+ ///
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ public struct VCI_CAN_STATUS
+ {
+ public byte ErrInterrupt;
+ public byte regMode;
+ public byte regStatus;
+ public byte regALCapture;
+ public byte regECCapture;
+ public byte regEWLimit;
+ public byte regRECounter;
+ public byte regTECounter;
+ public uint Reserved;
+ }
+
+ ///
+ /// 错误信息
+ ///
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ public struct VCI_ERR_INFO
+ {
+ public uint ErrCode;
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3, ArraySubType = UnmanagedType.I1)]
+ public byte[] Passive_ErrData;
+
+ public byte ArLost_ErrData;
+ }
+
+ ///
+ /// 初始化CAN的配置信息
+ ///
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ public struct VCI_INIT_CONFIG
+ {
+ ///
+ /// 验收码
+ ///
+ public uint AccCode;
+ ///
+ /// 屏蔽码
+ ///
+ public uint AccMask;
+ ///
+ /// 预留,填0
+ ///
+ public uint Reserved;
+ ///
+ /// 滤波方式
+ ///
+ public byte Filter;
+ public byte Timing0;
+ public byte Timing1;
+ ///
+ /// 模式:0:正常|1:只听
+ ///
+ public byte Mode;
+ }
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ public struct CHGDESIPANDPORT
+ {
+ [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst = 10)]
+ public string szpwd;
+
+ [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst = 20)]
+ public string szdesip;
+
+ public int desport;
+ }
+ #endregion
+
+ #region API函数
+
+ [DllImport("ControlCAN.dll", SetLastError = true, EntryPoint = "VCI_OpenDevice", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
+ public static extern uint VCI_OpenDevice(uint DeviceType, uint DeviceInd, uint Reserved);
+
+ [DllImport("ControlCAN.dll", SetLastError = true, EntryPoint = "VCI_CloseDevice", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
+ public static extern uint VCI_CloseDevice(uint DeviceType, uint DeviceInd);
+
+ [DllImport("ControlCAN.dll", SetLastError = true, EntryPoint = "VCI_ResetCAN", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
+ public static extern uint VCI_ResetCAN(uint DeviceType, uint DeviceInd, uint CANInd);
+
+ [DllImport("ControlCAN.dll", SetLastError = true, EntryPoint = "VCI_InitCAN", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
+ public static extern uint VCI_InitCAN(uint DeviceType, uint DeviceInd, uint CANInd, ref VCI_INIT_CONFIG pInitConfig);
+
+ [DllImport("ControlCAN.dll", SetLastError = true, EntryPoint = "VCI_Transmit", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
+ public static extern uint VCI_Transmit(uint DeviceType, uint DeviceInd, uint CANInd, ref VCI_CAN_OBJ pSend, uint Len);
+
+ [DllImport("ControlCAN.dll", SetLastError = true, EntryPoint = "VCI_Receive", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
+ public static extern uint VCI_Receive(uint DeviceType, uint DeviceInd, uint CANInd, IntPtr pReceive, uint Len, int WaitTime);
+
+ [DllImport("ControlCAN.dll", SetLastError = true, EntryPoint = "VCI_GetReceiveNum", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
+ public static extern uint VCI_GetReceiveNum(uint DeviceType, uint DeviceInd, uint CANInd);
+
+ [DllImport("ControlCAN.dll", SetLastError = true, EntryPoint = "VCI_ClearBuffer", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
+ public static extern uint VCI_ClearBuffer(uint DeviceType, uint DeviceInd, uint CANInd);
+
+ [DllImport("ControlCAN.dll", SetLastError = true, EntryPoint = "VCI_ReadErrInfo", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
+ public static extern uint VCI_ReadErrInfo(uint DeviceType, uint DeviceInd, uint CANInd, ref VCI_ERR_INFO pErrInfo);
+
+ [DllImport("ControlCAN.dll", SetLastError = true, EntryPoint = "VCI_StartCAN", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
+ public static extern uint VCI_StartCAN(uint DeviceType, uint DeviceInd, uint CANInd);
+
+ [DllImport("ControlCAN.dll", SetLastError = true, EntryPoint = "VCI_SetReference", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
+ public static extern uint VCI_SetReference(uint DeviceType, uint DeviceInd, uint CANInd, uint RefType, object pData);
+
+ [DllImport("ControlCAN.dll", SetLastError = true, EntryPoint = "VCI_GetReference", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
+ public static extern uint VCI_GetReference(uint DeviceType, uint DeviceInd, uint CANInd, uint RefType, object pData);
+
+ [DllImport("ControlCAN.dll", SetLastError = true, EntryPoint = "VCI_ReadCANStatus", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
+ public static extern uint VCI_ReadCANStatus(uint DeviceType, uint DeviceInd, uint CANInd, ref VCI_CAN_STATUS pCANStatus);
+
+ [DllImport("ControlCAN.dll", SetLastError = true, EntryPoint = "VCI_ReadBoardInfo", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
+ public static extern uint VCI_ReadBoardInfo(uint DeviceType, uint DeviceInd, ref VCI_BOARD_INFO pInfo);
+
+ #endregion
+ }
+}
diff --git a/CANHelper/kerneldlls/kerneldll.ini b/CANHelper/kerneldlls/kerneldll.ini
new file mode 100644
index 0000000..ed6204d
--- /dev/null
+++ b/CANHelper/kerneldlls/kerneldll.ini
@@ -0,0 +1,28 @@
+[KERNELDLL]
+COUNT=26
+1=PCI5121.dll
+2=PCI9810B.dll
+3=USBCAN.dll
+4=USBCAN.dll
+5=PCI9820B.dll
+6=CAN232.dll
+7=PCI5121.dll
+8=CANLite.dll
+9=ISA9620B.dll
+10=ISA5420.dll
+11=PC104CAN.dll
+12=CANETE.dll
+13=DNP9810B.dll
+14=PCI9840B.dll
+15=PC104C2.dll
+16=PCI9820I.dll
+17=CANET_TCP.dll
+18=pec9920.dll
+19=pci50xx_u.dll
+20=USBCAN_E.dll
+21=USBCAN_E.dll
+22=pci50xx_u.dll
+23=topcliff_can.dll
+24=pcie9221.dll
+25=CANWIFI_TCP.dll
+26=CANWIFI_UDP.dll
diff --git a/CANHelper/kerneldlls/usbcan.dll b/CANHelper/kerneldlls/usbcan.dll
new file mode 100644
index 0000000..0d5e36a
Binary files /dev/null and b/CANHelper/kerneldlls/usbcan.dll differ