实例介绍
【实例简介】CAN 通讯源码
【实例截图】
【实例截图】

【核心代码】
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
namespace CANBaseDevice
{
public enum STATUS
{
STATUS_ERR = 0,
STATUS_OK
}
public enum CAN_BAUDRATE
{
BAUD_5K = 5,
BAUD_10K = 10,
BAUD_20K = 20,
BAUD_40K = 40,
BAUD_50K = 50,
BAUD_80K = 80,
BAUD_100K = 100,
BAUD_125K = 125,
BAUD_200K = 200,
BAUD_250K = 250,
BAUD_400K = 400,
BAUD_500K = 500,
BAUD_666K = 666,
BAUD_800K = 800,
BAUD_1000K = 1000
}
public enum CAN_BOARD_TYPE
{
BOARDTYPE_PCI9810 = 2,
BOARDTYPE_USBCAN1 = 3,
BOARDTYPE_USBCAN2 = 4,
BOARDTYPE_PCI9820 = 5,
BOARDTYPE_PCI9840 = 14,
BOARDTYPE_PCI9820I = 16,
BOARDTYPE_CANTCP = 17,
BOARDTYPE_PCI5010U = 19,
BOARDTYPE_USBCANEU = 20,
BOARDTYPE_USBCAN2EU = 21,
BOARDTYPE_PCI5020U = 22,
BOARDTYPE_PCIE9221 = 24
}
//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 = 8)]
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];
}
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;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] Reserved;
}
//4.定义错误信息的数据类型。
public struct VCI_ERR_INFO
{
public UInt32 ErrCode;
public byte Passive_ErrData1;
public byte Passive_ErrData2;
public byte Passive_ErrData3;
public byte ArLost_ErrData;
}
//5.定义初始化CAN的数据类型
public struct VCI_INIT_CONFIG
{
public UInt32 AccCode;
public UInt32 AccMask;
public UInt32 Reserved;
public byte Filter;
public byte Timing0;
public byte Timing1;
public byte Mode;
}
public class CANDevice
{
//****************************************************************CAN接口函数库********************************************************************//
//CAN接口库函数
[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_ReadErrInfo(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_ERR_INFO pErrInfo);
[DllImport("controlcan.dll")]
public static extern UInt32 VCI_ReadCANStatus(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_CAN_STATUS pCANStatus);
[DllImport("controlcan.dll")]
public static extern UInt32 VCI_GetReference(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, UInt32 RefType, byte[] pData);
[DllImport("controlcan.dll")]
public unsafe static extern UInt32 VCI_SetReference(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, UInt32 RefType, byte* pData);
[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", CharSet = CharSet.Ansi)]
public static extern UInt32 VCI_Receive(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, IntPtr pReceive, UInt32 Len, Int32 WaitTime);
static UInt32 m_DeviceType = 14; //针对ZLG PCI9840I型号卡
// static readonly UInt32 m_DeviceIndex = 0; //设备索引号 有多个设备时该值累加
// static UInt32[] m_ChNo = new UInt32[4]; //9840I CAN通道号
protected const uint m_ErrCode = 0xFFFFFFFF;
protected const uint m_TimeOut = 0;
private int[] m_curBaudRate = null;
private int chNumber = 4;
/// <summary>
/// 打开CAN设备
/// </summary>
/// <param name="deviceType">CAN类型</param>
/// <param name="ChNum">通道数</param>
/// <param name="BaudRate">波特率 从5到1000</param>
/// <returns></returns>
public bool DeviceOpen(UInt32 deviceType, int ChNum, int BaudRate1, int BaudRate2, int BaudRate3, int BaudRate4)
{
bool bRet = false;
m_DeviceType = deviceType;
chNumber = ChNum;
MakeChnum(BaudRate1, BaudRate2, BaudRate3, BaudRate4);
if (!OpenCAN(0) || !InitCAN())
{
return bRet;
}
//if (!StartCAN())
//{
// return bRet;
//}
return (bRet = true);
}
void MakeChnum(int BaudRate1, int BaudRate2, int BaudRate3, int BaudRate4)
{
switch (chNumber)
{
case 1:
m_curBaudRate = new int[1];
m_curBaudRate[0] = BaudRate1;
break;
case 2:
m_curBaudRate = new int[2];
m_curBaudRate[0] = BaudRate1;
m_curBaudRate[1] = BaudRate2;
break;
case 3:
m_curBaudRate = new int[3];
m_curBaudRate[0] = BaudRate1;
m_curBaudRate[1] = BaudRate2;
m_curBaudRate[2] = BaudRate3;
break;
case 4:
m_curBaudRate = new int[4];
m_curBaudRate[0] = BaudRate1;
m_curBaudRate[1] = BaudRate2;
m_curBaudRate[2] = BaudRate3;
m_curBaudRate[3] = BaudRate4;
break;
default:
break;
}
}
bool OpenCAN(uint DevIndex)
{
bool bRet = false;
if (VCI_OpenDevice(m_DeviceType, DevIndex, 0) == (uint)STATUS.STATUS_ERR)
{
return bRet;
}
return (bRet = true);
}
//生成CAN配置参数
private VCI_INIT_CONFIG MakeCANParam(byte Tim0, byte Tim1)
{
VCI_INIT_CONFIG DevConfig = new VCI_INIT_CONFIG();
DevConfig.AccCode = 0x00;
DevConfig.AccMask = 0xffffffff;
DevConfig.Filter = 0x01;
DevConfig.Timing0 = Tim0;
DevConfig.Timing1 = Tim1;
DevConfig.Mode = 0x00;
return DevConfig;
}
/// <summary>
/// 不同的通道初始化不同的波特率
/// </summary>
/// <returns></returns>
unsafe bool InitCAN()
{
bool bRet = false;
byte Time0 = 0x00;
byte Time1 = 0x1C; //default 500k
UInt32 baud;
for (int iCh = 0; iCh < chNumber; iCh)
{
switch (m_curBaudRate[iCh])
{
case (int)CAN_BAUDRATE.BAUD_5K:
Time0 = 0xbf;
Time1 = 0xff;
baud = 0x1C01C1;
break;
case (int)CAN_BAUDRATE.BAUD_10K:
Time0 = 0x31;
Time1 = 0x1c;
baud = 0x1C00E0;
break;
case (int)CAN_BAUDRATE.BAUD_20K:
Time0 = 0x18;
Time1 = 0x1c;
baud = 0x1600B3;
break;
case (int)CAN_BAUDRATE.BAUD_40K:
Time0 = 0x87;
Time1 = 0xff;
break;
case (int)CAN_BAUDRATE.BAUD_50K:
Time0 = 0x09;
Time1 = 0x1c;
baud = 0x1C002C;
break;
case (int)CAN_BAUDRATE.BAUD_80K:
Time0 = 0x83;
Time1 = 0xff;
break;
case (int)CAN_BAUDRATE.BAUD_100K:
Time0 = 0x04;
Time1 = 0x1c;
baud = 0x160023;
break;
case (int)CAN_BAUDRATE.BAUD_125K:
Time0 = 0x03;
Time1 = 0x1c;
baud = 0x1C0011;
break;
case (int)CAN_BAUDRATE.BAUD_200K:
Time0 = 0x81;
Time1 = 0xfa;
break;
case (int)CAN_BAUDRATE.BAUD_250K:
Time0 = 0x01;
Time1 = 0x1c;
baud = 0x1C0008;
break;
case (int)CAN_BAUDRATE.BAUD_400K:
Time0 = 0x80;
Time1 = 0xfa;
break;
case (int)CAN_BAUDRATE.BAUD_500K:
Time0 = 0x00;
Time1 = 0x1C;
baud = 0x060007;
break;
case (int)CAN_BAUDRATE.BAUD_666K:
Time0 = 0x80;
Time1 = 0xb6;
break;
case (int)CAN_BAUDRATE.BAUD_800K:
Time0 = 0x00;
Time1 = 0x16;
baud = 0x060004;
break;
case (int)CAN_BAUDRATE.BAUD_1000K:
Time0 = 0x00;
Time1 = 0x14;
baud = 0x060003;
break;
default:
break;
}
VCI_INIT_CONFIG DevConfig = MakeCANParam(Time0, Time1);
if (m_DeviceType == (UInt32)CAN_BOARD_TYPE.BOARDTYPE_PCI5010U || m_DeviceType == (UInt32)CAN_BOARD_TYPE.BOARDTYPE_USBCANEU
|| m_DeviceType == (UInt32)CAN_BOARD_TYPE.BOARDTYPE_USBCAN2EU || m_DeviceType == (UInt32)CAN_BOARD_TYPE.BOARDTYPE_PCI5020U)
{
uint iRet = VCI_SetReference(m_DeviceType, 0, (uint)iCh, 0, (byte*)&baud);
}
// NativeMethods.VCI_InitCAN(m_DeviceType, 0, (uint)iCh, ref DevConfig);
if (VCI_InitCAN(m_DeviceType, 0, (uint)iCh, ref DevConfig) == (uint)STATUS.STATUS_ERR)
{
// NativeMethods.VCI_CloseDevice(m_DeviceType, 0);
return bRet;
}
}
return (bRet = true);
}
/// <summary>
/// 复位CAN卡通道 当出现某一通道数据无响应时使用 waysion 20190606
/// </summary>
/// <param name="CANChIndex"></param>
/// <returns></returns>
public uint ResetCAN(uint CANChIndex)
{
return VCI_ResetCAN(m_DeviceType, 0, CANChIndex);
}
//bool StartCAN()
//{
// bool bRet = false;
// for (int chNo = 0; chNo < chNumber; chNo)
// {
// if (NativeMethods.VCI_StartCAN(m_DeviceType, 0, m_ChNo[chNo]) == (uint)STATUS.STATUS_ERR)
// {
// NativeMethods.VCI_CloseDevice(m_DeviceType, 0);
// return bRet;
// }
// }
// return (bRet = true);
//}
public uint StartCAN(int chNo)
{
// return NativeMethods.VCI_StartCAN(m_DeviceType, 0, m_ChNo[chNo]);
return VCI_StartCAN(m_DeviceType, 0, (uint)chNo);
}
unsafe public uint TransmitData(uint FrameID, uint DevIndex, int ChNo, byte ExternFlag, byte DataLen, byte[] FrameBuffer)
{
int index = 0;
VCI_CAN_OBJ objData = new VCI_CAN_OBJ();//第一个MBS的数据结构
objData.SendType = 0x00;
objData.RemoteFlag = 0x00;
objData.ExternFlag = ExternFlag;
objData.ID = FrameID;
objData.DataLen = DataLen;
objData.TimeFlag = 1;
while (index < DataLen)
{
objData.Data[index] = FrameBuffer[index];
index ;
}
int nTimeOut = 3000;
VCI_SetReference(m_DeviceType, DevIndex, (uint)ChNo, 4, (byte*)&nTimeOut);
// return NativeMethods.VCI_Transmit(m_DeviceType, DevIndex, m_ChNo[ChNo], ref objData, 1);
return VCI_Transmit(m_DeviceType, DevIndex, (uint)ChNo, ref objData, 1);
}
public uint ClearCurrentChBuffer(uint DevIndex, int ChNo)
{
return VCI_ClearBuffer(m_DeviceType, DevIndex, (uint)ChNo);
}
//DevIndex 设备索引 0-1 ChNo 通道号 0-3
unsafe public uint ReceiveData(uint FrameCount, uint DevIndex, int ChNo, int Timeout, ref byte[] getData, ref uint retId)
{
uint uRet = 0;
if (VCI_GetReceiveNum(m_DeviceType, DevIndex, (uint)ChNo) == 0)
return 0;
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(VCI_CAN_OBJ)) * (Int32)FrameCount);
uRet = VCI_Receive(m_DeviceType, DevIndex, (uint)ChNo, ptr, FrameCount, Timeout);
//System.Diagnostics.Trace.WriteLine(string.Format("uRet:{0}\n", uRet));
if (uRet == 0 || uRet == m_ErrCode)
{
VCI_ERR_INFO ErrNum = new VCI_ERR_INFO();
UInt32 Error;
Error = VCI_ReadErrInfo(m_DeviceType, DevIndex, (uint)ChNo, ref ErrNum);
Process_ErrorPacket(ErrNum.ErrCode);
VCI_ClearBuffer(m_DeviceType, DevIndex, (uint)ChNo);
}
else
{
int iFrm = 0;
VCI_CAN_OBJ objData = (VCI_CAN_OBJ)Marshal.PtrToStructure((IntPtr)((UInt32)ptr
iFrm * Marshal.SizeOf(typeof(VCI_CAN_OBJ))), typeof(VCI_CAN_OBJ));
// pv_debug_log.pv_debug_printf(string.Format("Receive_ObjData gedatalength: {0}", getData.Length), (uint)loglevel.log_debug_level);
for (int iLen = 0; iLen < objData.DataLen; iLen)
{
getData[iLen] = (byte)(objData.Data[iLen]);
}
retId = objData.ID;
}
Marshal.FreeHGlobal(ptr);
return uRet;
}
public void Close_Device(uint DevType, uint DevIndex)
{
VCI_CloseDevice(DevType, DevIndex);
}
private void Process_ErrorPacket(uint ErrCode)
{
string Err_str = "未知错误";
switch (ErrCode)
{
case 0x0100:
Err_str = "CAN-1设备已经打开";
break;
case 0x0200:
Err_str = "CAN-1打开设备错误";
break;
case 0x0400:
Err_str = "CAN-1设备没有打开";
break;
case 0x0800:
Err_str = "CAN-1缓冲区溢出";
break;
case 0x1000:
Err_str = "CAN-1此设备不存在";
break;
case 0x2000:
Err_str = "CAN-1装载动态库错误";
break;
case 0x4000:
Err_str = "CAN-1装执行命令失败错误";
break;
case 0x8000:
Err_str = "CAN-1内存不足";
break;
case 0x0001:
Err_str = "CAN-1can控制器内部FIFO溢出";
break;
case 0x0002:
Err_str = "CAN-1can控制器错误报警";
break;
case 0x0004:
Err_str = "CAN-1can控制器消极错误";
break;
case 0x0008:
Err_str = "CAN-1can控制器仲裁错误";
break;
case 0x0010:
Err_str = "can控制器总线错误";
break;
default:
break;
}
System.Diagnostics.Trace.WriteLine(Err_str);
}
}
}
好例子网口号:伸出你的我的手 — 分享!
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明


网友评论
我要评论