基本信息
源码名称:CAN 通讯源码
源码大小:0.74M
文件格式:.zip
开发语言:C#
更新时间:2019-11-14
   友情提示:(无需注册或充值,赞助后即可获取资源下载链接)

     嘿,亲!知识可是无价之宝呢,但咱这精心整理的资料也耗费了不少心血呀。小小地破费一下,绝对物超所值哦!如有下载和支付问题,请联系我们QQ(微信同号):78630559

本次赞助数额为: 2 元 
   源码介绍
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);
        }

    }
}