周立功CAN pci接口卡提供的示例代码都是VC,VB和Delphi的,没有C#.net的例子。但是在使用C#调用CAN api的时候,由于这些api对数据类型的校验非常严格,所以,调试起来比较麻烦。摸索了一段时间,终于使用C# 2.0 VS.2008调用CAN api可以正常的发送接收数据了。
现在把API的声明提供如下,有同样需求的,就可以少走很多弯路了。
view plaincopy to clipboardprint?
01.public sealed class CANApi
02. {
03. //接口卡类型定义
04. public enum PCIDeviceType
05. {
06. VCI_PCI5121 =1,
07. VCI_PCI9810 =2,
08. VCI_USBCAN1 =3,
09. VCI_USBCAN2 =4,
10. VCI_PCI9820 =5,
11. VCI_CAN232 =6,
12. VCI_PCI5110 =7,
13. VCI_CANLITE =8,
14. VCI_ISA9620 =9,
15. VCI_ISA5420 =10,
16. VCI_PC104CAN = 11,
17. VCI_CANETE =12,
18. VCI_DNP9810 =13,
19. VCI_PCI9840 =14,
20. VCI_PCI9820I =16
21. }
22.
23. //函数调用返回状态值
24. public static readonly int STATUS_OK =1;
25. public static readonly int STATUS_ERR =0;
26.
27. public enum ErrorType
28. {
29. //CAN错误码
30. ERR_CAN_OVERFLOW =0x0001, //CAN控制器内部FIFO溢出
31. ERR_CAN_ERRALARM =0x0002, //CAN控制器错误报警
32. ERR_CAN_PASSIVE =0x0004, //CAN控制器消极错误
33. ERR_CAN_LOSE =0x0008, //CAN控制器仲裁丢失
34. ERR_CAN_BUSERR =0x0010, //CAN控制器总线错误
35.
36. //通用错误码
37. ERR_DEVICEOPENED =0x0100, //设备已经打开
38. ERR_DEVICEOPEN =0x0200, //打开设备错误
39. ERR_DEVICENOTOPEN =0x0400, //设备没有打开
40. ERR_BUFFEROVERFLOW =0x0800, //缓冲区溢出
41. ERR_DEVICENOTEXIST =0x1000, //此设备不存在
42. ERR_LOADKERNELDLL =0x2000, //装载动态库失败
43. ERR_CMDFAILED =0x4000, //执行命令失败错误码
44. ERR_BUFFERCREATE =0x8000 //内存不足
45.
46. }
47.
48.
49.
50. //1.ZLGCAN系列接口卡信息的数据类型。
51. [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
52. public struct VCI_BOARD_INFO
53. {
54. public ushort hw_Version;
55. public ushort fw_Version;
56. public ushort dr_Version;
57. public ushort in_Version;
58. public ushort irq_Num;
59. public byte can_Num;
60. [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst = 20)]
61. public string str_Serial_Num;
62. [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst = 40)]
63. public string str_hw_Type;
64. [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = System.Runtime.InteropServices.UnmanagedType.U2)]
65. public ushort[] Reserved;
66. }
67.
68. //2.定义CAN信息帧的数据类型。
69. [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
70. public struct VCI_CAN_OBJ
71. {
72. public uint ID;
73. public uint TimeStamp;
74. public byte TimeFlag;
75. public byte SendType;
76. public byte RemoteFlag;//是否是远程帧
77. public byte ExternFlag;//是否是扩展帧
78. public byte DataLen;
79. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8, ArraySubType = UnmanagedType.I1)]
80. public byte[] Data;
81. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3, ArraySubType = UnmanagedType.I1)]
82. public byte[] Reserved;
83. }
84.
85. //3.定义CAN控制器状态的数据类型。
86. [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
87. public struct VCI_CAN_STATUS
88. {
89. public byte ErrInterrupt;
90. public byte regMode;
91. public byte regStatus;
92. public byte regALCapture;
93. public byte regECCapture;
94. public byte regEWLimit;
95. public byte regRECounter;
96. public byte regTECounter;
97. public uint Reserved;
98. }
99.
100. //4.定义错误信息的数据类型。
101. [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
102. public struct VCI_ERR_INFO
103. {
104. public uint ErrCode;
105.
106. [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst = 3, ArraySubType = System.Runtime.InteropServices.UnmanagedType.I1)]
107. public byte[] Passive_ErrData;
108.
109. public byte ArLost_ErrData;
110. }
111.
112. //5.定义初始化CAN的数据类型
113. [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
114. public struct VCI_INIT_CONFIG
115. {
116. public uint AccCode;
117. public uint AccMask;
118. public uint Reserved;
119. public byte Filter;
120. public byte Timing0;
121. public byte Timing1;
122. public byte Mode;
123. }
124. [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
125. public struct CHGDESIPANDPORT
126. {
127. [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst = 10)]
128. public string szpwd;
129.
130. [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst = 20)]
131. public string szdesip;
132.
133. public int desport;
134. }
135.
136. #region API函数
137.
138. [DllImport("ControlCAN.dll", EntryPoint = "VCI_OpenDevice", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
139. public static extern uint VCI_OpenDevice(uint DeviceType, uint DeviceInd, uint Reserved);
140.
141. [DllImport("ControlCAN.dll", EntryPoint = "VCI_CloseDevice", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
142. public static extern uint VCI_CloseDevice(uint DeviceType, uint DeviceInd);
143.
144. [DllImport("ControlCAN.dll", EntryPoint = "VCI_InitCAN", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
145. public static extern uint VCI_InitCAN(uint DeviceType, uint DeviceInd, uint CANInd, ref VCI_INIT_CONFIG pInitConfig);
146.
147.
148. [DllImport("ControlCAN.dll", EntryPoint = "VCI_ReadBoardInfo", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
149. public static extern uint VCI_ReadBoardInfo(uint DeviceType, uint DeviceInd, ref VCI_BOARD_INFO pInfo);
150.
151. [DllImport("ControlCAN.dll", EntryPoint = "VCI_ReadErrInfo", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
152. public static extern uint VCI_ReadErrInfo(uint DeviceType, uint DeviceInd, uint CANInd, ref VCI_ERR_INFO pErrInfo);
153.
154.
155. [DllImport("ControlCAN.dll", EntryPoint = "VCI_ReadCANStatus", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
156. public static extern uint VCI_ReadCANStatus(uint DeviceType, uint DeviceInd, uint CANInd, ref VCI_CAN_STATUS pCANStatus);
157.
158. [DllImport("ControlCAN.dll", EntryPoint = "VCI_GetReference", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
159. public static extern uint VCI_GetReference(uint DeviceType, uint DeviceInd, uint CANInd, uint RefType, object pData);
160.
161. [DllImport("ControlCAN.dll", EntryPoint = "VCI_SetReference", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
162. public static extern uint VCI_SetReference(uint DeviceType, uint DeviceInd, uint CANInd, uint RefType, object pData);
163.
164. [DllImport("ControlCAN.dll", EntryPoint = "VCI_GetReceiveNum", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
165. public static extern uint VCI_GetReceiveNum(uint DeviceType, uint DeviceInd, uint CANInd);
166.
167. [DllImport("ControlCAN.dll", EntryPoint = "VCI_ClearBuffer", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
168. public static extern uint VCI_ClearBuffer(uint DeviceType, uint DeviceInd, uint CANInd);
169.
170. [DllImport("ControlCAN.dll", EntryPoint = "VCI_StartCAN", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
171. public static extern uint VCI_StartCAN(uint DeviceType, uint DeviceInd, uint CANInd);
172.
173. [DllImport("ControlCAN.dll", EntryPoint = "VCI_ResetCAN", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
174. public static extern uint VCI_ResetCAN(uint DeviceType, uint DeviceInd, uint CANInd);
175.
176. [DllImport("ControlCAN.dll", EntryPoint = "VCI_Transmit", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
177. public static extern uint VCI_Transmit(uint DeviceType, uint DeviceInd, uint CANInd, ref VCI_CAN_OBJ pSend, uint Len);
178.
179. [DllImport("ControlCAN.dll", EntryPoint = "VCI_Receive", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
180. public static extern uint VCI_Receive(uint DeviceType, uint DeviceInd, uint CANInd, ref VCI_CAN_OBJ pReceive, uint Len, int WaitTime);
181.
182.
183. #endregion
184. }
public sealed class CANApi
{
//接口卡类型定义
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错误码
ERR_CAN_OVERFLOW =0x0001, //CAN控制器内部FIFO溢出
ERR_CAN_ERRALARM =0x0002, //CAN控制器错误报警
ERR_CAN_PASSIVE =0x0004, //CAN控制器消极错误
ERR_CAN_LOSE =0x0008, //CAN控制器仲裁丢失
ERR_CAN_BUSERR =0x0010, //CAN控制器总线错误
//通用错误码
ERR_DEVICEOPENED =0x0100, //设备已经打开
ERR_DEVICEOPEN =0x0200, //打开设备错误
ERR_DEVICENOTOPEN =0x0400, //设备没有打开
ERR_BUFFEROVERFLOW =0x0800, //缓冲区溢出
ERR_DEVICENOTEXIST =0x1000, //此设备不存在
ERR_LOADKERNELDLL =0x2000, //装载动态库失败
ERR_CMDFAILED =0x4000, //执行命令失败错误码
ERR_BUFFERCREATE =0x8000 //内存不足
}
//1.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;
}
//2.定义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;
}
//3.定义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;
}
//4.定义错误信息的数据类型。
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct VCI_ERR_INFO
{
public uint ErrCode;
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst = 3, ArraySubType = System.Runtime.InteropServices.UnmanagedType.I1)]
public byte[] Passive_ErrData;
public byte ArLost_ErrData;
}
//5.定义初始化CAN的数据类型
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct VCI_INIT_CONFIG
{
public uint AccCode;
public uint AccMask;
public uint Reserved;
public byte Filter;
public byte Timing0;
public byte Timing1;
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;
}
#region API函数
[DllImport("ControlCAN.dll", EntryPoint = "VCI_OpenDevice", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public static extern uint VCI_OpenDevice(uint DeviceType, uint DeviceInd, uint Reserved);
[DllImport("ControlCAN.dll", EntryPoint = "VCI_CloseDevice", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public static extern uint VCI_CloseDevice(uint DeviceType, uint DeviceInd);
[DllImport("ControlCAN.dll", 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", EntryPoint = "VCI_ReadBoardInfo", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public static extern uint VCI_ReadBoardInfo(uint DeviceType, uint DeviceInd, ref VCI_BOARD_INFO pInfo);
[DllImport("ControlCAN.dll", 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", 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", 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", 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", EntryPoint = "VCI_GetReceiveNum", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public static extern uint VCI_GetReceiveNum(uint DeviceType, uint DeviceInd, uint CANInd);
[DllImport("ControlCAN.dll", EntryPoint = "VCI_ClearBuffer", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public static extern uint VCI_ClearBuffer(uint DeviceType, uint DeviceInd, uint CANInd);
[DllImport("ControlCAN.dll", EntryPoint = "VCI_StartCAN", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public static extern uint VCI_StartCAN(uint DeviceType, uint DeviceInd, uint CANInd);
[DllImport("ControlCAN.dll", EntryPoint = "VCI_ResetCAN", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public static extern uint VCI_ResetCAN(uint DeviceType, uint DeviceInd, uint CANInd);
[DllImport("ControlCAN.dll", 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", EntryPoint = "VCI_Receive", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public static extern uint VCI_Receive(uint DeviceType, uint DeviceInd, uint CANInd, ref VCI_CAN_OBJ pReceive, uint Len, int WaitTime);
#endregion
}
注意:在使用过程中,需要把ControlCAN.dll并kerneldlls文件夹及其下面的所有DLL都添加到工程中,并且把这些文件的“Copy到输出文件”属性设置为“常拷贝”。
发送和接收比较的容易出问题,示例代码如下:
view plaincopy to clipboardprint?
01.CANApi.VCI_CAN_OBJ[] frameInfo = new CANApi.VCI_CAN_OBJ[1];
02. frameInfo[0].DataLen = (byte)(ss.Length);
03.
04. frameInfo[0].Data = data;
05. frameInfo[0].Reserved = new byte[3];
06.
07. frameInfo[0].RemoteFlag = (byte)this.combFrameFormat.SelectedIndex;
08. frameInfo[0].ExternFlag = (byte)this.combFrameType.SelectedIndex;
09.
10. uint frameID = 0;
11. if (!uint.TryParse(this.txtFrameID.Text, System.Globalization.NumberStyles.AllowHexSpecifier, null, out frameID))
12. frameID = 0;
13. if (frameInfo[0].ExternFlag == 1)
14. {
15. frameInfo[0].ID = frameID;
16. }
17. else
18. {
19. frameInfo[0].ID = frameID | 0x0000FFFF;
20. }
21. frameInfo[0].SendType = (byte)this.combSendFormat.SelectedIndex;
22.
23. CANApi.VCI_Transmit(this.mDeviceType, this.mDeviceIndex, this.mCANIndex, ref frameInfo[0], 1);
CANApi.VCI_CAN_OBJ[] frameInfo = new CANApi.VCI_CAN_OBJ[1];
frameInfo[0].DataLen = (byte)(ss.Length);
frameInfo[0].Data = data;
frameInfo[0].Reserved = new byte[3];
frameInfo[0].RemoteFlag = (byte)this.combFrameFormat.SelectedIndex;
frameInfo[0].ExternFlag = (byte)this.combFrameType.SelectedIndex;
uint frameID = 0;
if (!uint.TryParse(this.txtFrameID.Text, System.Globalization.NumberStyles.AllowHexSpecifier, null, out frameID))
frameID = 0;
if (frameInfo[0].ExternFlag == 1)
{
frameInfo[0].ID = frameID;
}
else
{
frameInfo[0].ID = frameID | 0x0000FFFF;
}
frameInfo[0].SendType = (byte)this.combSendFormat.SelectedIndex;
CANApi.VCI_Transmit(this.mDeviceType, this.mDeviceIndex, this.mCANIndex, ref frameInfo[0], 1);
view plaincopy to clipboardprint?
01.CANApi.VCI_CAN_OBJ[] frameInfos = new CANApi.VCI_CAN_OBJ[50];
02.len = (int)CANApi.VCI_Receive(this.mDeviceType, this.mDeviceIndex, this.mCANIndex, ref frameInfos[0], 50, 200);
03. if (len <= 0)
04. {
05. //注意:如果没有读到数据则必须调用此函数来读取出当前的错误码,
06. //千万不能省略这一步(即使你可能不想知道错误码是什么)
07. CANApi.VCI_ReadErrInfo(this.mDeviceType, this.mDeviceIndex, this.mCANIndex, ref errInfo);
08. }
09. else
10. {...
CANApi.VCI_CAN_OBJ[] frameInfos = new CANApi.VCI_CAN_OBJ[50];
len = (int)CANApi.VCI_Receive(this.mDeviceType, this.mDeviceIndex, this.mCANIndex, ref frameInfos[0], 50, 200);
if (len <= 0)
{
//注意:如果没有读到数据则必须调用此函数来读取出当前的错误码,
//千万不能省略这一步(即使你可能不想知道错误码是什么)
CANApi.VCI_ReadErrInfo(this.mDeviceType, this.mDeviceIndex, this.mCANIndex, ref errInfo);
}
else
{...
运行效果图如下:
本文来自CSDN博客,出处:http://blog.csdn.net/zztfj/archive/2010/11/19/6020924.aspx
用户202164 2011-6-16 16:40