实例介绍
【实例简介】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小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明
网友评论
我要评论