汽车电子技术论坛
直播中

王锐

8年用户 7经验值
擅长:嵌入式技术 处理器/DSP 控制/MCU
私信 关注
[资料]

基于.net2.0的汽车电子***协议的封装

从事汽车电子的人应该都知道CCP协议,这是我半年从事汽车电子测试软件开发所熟悉知道的协议。
CCP(CAN Calibration Protocol)是一种基于CAN总线的ECU(Electronic Control Unit)标定协议,汽车上的助力转向系统EPS就用到CCP协议通过CAN进行传输。
CCP协议里面有很多指令,每一条指令都有对应的捂手信号,通过捂手来保证数据传输的正确性。我们经常用到的CCP指令主要有如下指令:
1、连接指令,主要包括Polling模式和DAQ模式以及正常模式(可能这边表述不是很专业)的连接指令。
正常模式连接指令:主要发送三条指令进行连接:第一条:SendMessageD(newbyte[] { 0x01, Ctr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, id, 8, 10)、
第二条:SendMessageD(new byte[] { 0x14, Ctr,0x00, 0x00, 0x00, 0x00, 0x00, 0x36 }, id, 8, 10)、第三条:SendMessageD(newbyte[] { 0x14, Ctr, 0x01, 0x00, 0x00, 0x00, 0x00, 0x36 }, id, 8, 10)。这三条指令都有各自对应的捂手信号,进行连接的时候依次发送。
Polling模式指令:主要发送五条指令:依次是SendMessageD(newbyte[] { 0x01, Ctr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, id, 8, 10)、SendMessageD(new byte[] { 0x12, Ctr, 0x01, 0x00, 0x00,0x00, 0x00, 0x00 }, id, 8, 10)、SendMessageD(newbyte[] { 0x13, Ctr, pSeed[0], pSeed[1], pSeed[2], pSeed[3], 0x00, 0x00 }, id,8, 10)、SendMessageD(new byte[] { 0x14, Ctr, 0x00, 0x00, 0x00,0x00, 0x01, 0x10 }, id, 8, 10)、SendMessageD(newbyte[] { 0x14, Ctr, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01 }, id, 8, 10),发送的时候依次发送,没发送一条都会有对应的握手信号。发送第三条指令时,涉及到一个地址解密算法,这个算法是通过调用C++封装的一个非托管dll文件来进行解密的,发送第三条数据时,要先进行解密,然后将解密好的4个字节的数组放在第三条指令的地址位进行发送。
DAQ模式连接:主要发送五条指令:依次是SendMessageD(newbyte[] { 0x01, Ctr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, id, 8, 10)、SendMessageD(new byte[] { 0x12, Ctr, 0x01, 0x00, 0x00,0x00, 0x00, 0x00 }, id, 8, 10)、SendMessageD(newbyte[] { 0x13, Ctr, pSeed[0], pSeed[1], pSeed[2], pSeed[3], 0x00, 0x00 }, id,8, 10)、SendMessageD(new byte[] { 0x14, Ctr, 0x00, 0x00, 0x00,0x00, 0x01, 0x10 }, id, 8, 10)、SendMessageD(newbyte[] { 0x14, Ctr, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01 }, id, 8, 10),发送的指令和Polling模式指令一样,仅仅可能是解密的算法可能会不同,这个每一家都可以自己进行设计,同样调用解密的dll文件也是一样同Polling模式指令。
2、写入数据指令:写入数据主要有两条指令:SendMessageD(new byte[] { 0x02, Ctr,0x00, 0x00, (byte)(0xFF & (address >> 24)), (byte)(0xFF &(address >> 16)), (byte)(0xFF & (address >> 8)), (byte)(0xFF& address) }, id, 8, 10),这一条指令主要是发送要写入数据的变量的地址,指令最后四个字节的地址主要根据变量的大小端以及变量的大小进行计算;SendMessageD(newbyte[] { 0x03, Ctr, AnalysisVarS.Size, bytedata[0], bytedata[1], bytedata[2],bytedata[3], bytedata[4] }, id, 8, 10),这条指令主要发送要写入的数据,数据要根据变量的大小、类型、以及变量的算法进行处理过后才能够进行发送。
3、读取数据指令:读取数据只有一条指令:SendMessageD(new byte[] { 0x0F, Ctr,AnalysisVarS.Size, 0x00, (byte)(0xFF & (address >> 24)), (byte)(0xFF& (address >> 16)), (byte)(0xFF & (address >> 8)),(byte)(0xFF & address) }, id, 8, 10),只需要发送要读取的变量的地址就可以,返回的握手信号中会有要读取的变量的值。
下面是我基于.net2.0封装的CCP的一些常用的指令,已经在我们公司的EPS测试软件上验证过,目前没有出现问题。下面是源码:
public static classCCP
    {
        #region 构造函数
        static CCP()
        {
            _ctr = 0;
            MCUAndPCLinkCPPStateE =CPPOrderStateEnum.NullCCPOrderState;
            AutoResetEvent = newAutoResetEvent(true);
            PollingPath = null;
            DAQPath = null;
        }
        #endregion
        #region 私有变量
        ///
        /// 用于存储地址
        ///
        private static int address = 0;//地址大小
        ///
        /// 用于CCP通信延迟计数
        ///
        private static int count = 0;
        ///
        /// 用于存储解密数据
        ///
        private static byte[] pSeed = newbyte[4];
        ///
        /// 用于存储上传或是下传的数据
        ///
        private static byte[] bytedata = newbyte[5];
        ///
        /// 存储上传数据临时数组
        ///
        private static byte[] TempBuf;
        ///
        /// 存储A2L文件中解析好的字节地址、变量大小、数组大小、地址类型
        ///
        private static AnalysisVarStructAnalysisVarS = new AnalysisVarStruct();
        #endregion
        #region AutoResetEvent
        ///
        /// 线程同步,并将其状态设置为有信号(每一次只允许一个线程工作,每次开线程前都要Set一下。)
        ///
        public static AutoResetEventAutoResetEvent;
        #endregion
        #region 定义命令序号Ctr属性
        ///
        /// 命令序号_ctr字段
        ///
        private static byte _ctr;
        ///
        /// 命令序号Ctr属性
        ///
        public static byte Ctr
        {
            get
            {
                if (_ctr >= 255) _ctr = 0;
                return _ctr;
            }
            set
            {
                _ctr = value;
                if (_ctr >= 255) _ctr = 0;
            }
        }
        #endregion
        #region SeedKey状态标志
        ///
        /// 打开Polling功能的DLL路径
        ///
        public static string PollingPath;
        ///
        /// 打开DAQ功能的DLL路径
        ///
        public static string DAQPath;
        #endregion
        #region CCP枚举状态
        #region CPP指令枚举状态
        ///
        /// CPP指令枚举状态
        ///
        public enum CPPOrderStateEnum
        {
            #region MCU和PC连接功能枚举状态
            Send0x01CCPOrderState = 1,
            Send0x01CCPOrderStateSuccess = 2,
            Send0x12CCPOrderPollingState = 3,
            Send0x12CCPOrderPollingStateSuccess= 4,
            Send0x13CCPOrderPollingState = 5,
            Send0x13CCPOrderPollingStateSuccess= 6,
            Send0x12CCPOrderDAQState = 7,
            Send0x12CCPOrderDAQStateSuccess =8,
            Send0x13CPPOrderDAQState = 9,
            Send0x13CPPOrderDAQStateSuccess =10,
            Send0x14CCPOrderOneState = 11,
            Send0x14CCPOrderOneStateSuccess =12,
            Send0x14CCPOrderTwoState = 13,
            Send0x14CCPOrderTwoStateSuccess =14,
            MCULinkPCStateSuccess = 15,
            #endregion
            #region Polling模式枚举状态(采集量上传数据枚举状态;标定量下发数据枚举状态)
            Send0x0FCCPOrderState = 23,
            Send0x0FCCPOrderStateSuccess = 24,
            CCPUpDataStateSuccess = 25,
            Send0x02CCPOrderState = 26,
            Send0x02CCPOrderStateSuccess = 27,
            Send0x03CCPOrderState = 28,
            Send0x03CCPOrderStateSuccess = 29,
            CCPDownDataStateSuccess = 30,
            #endregion
            #region 没有发送任何CPP指令(空状态)
            NullCCPOrderState = 100,
            #endregion
        }
        #endregion
        #region MCU和PC连接CCP指令枚举状态
        ///
        /// MCU和PC连接CCP指令枚举状态
        ///
        private static CPPOrderStateEnumMCUAndPCLinkCPPStateE;
        #endregion
        #region 下传数据CCP指令枚举状态
        ///
        /// 下传数据CCP指令枚举状态
        ///
        private static CPPOrderStateEnumDownDataCCPStateE;
        #endregion
        #region 上传数据CCP指令枚举状态
        ///
        /// 上传数据CCP指令枚举状态
        ///
        private static CPPOrderStateEnumUpDataCCPStateE;
        #endregion
        #endregion
        #region 定义存储A2L文件中的变量、算法集合的变量
        ///
        /// 存储采集变量信息的结构体
        ///
        public struct VariableInformationStruct
        {
            ///
            /// 采集变量的名字
            ///
            public string Name;//采集变量的名字
            ///
            /// 采集变量的地址
            ///
            public string Address;//采集变量的地址
            ///
            /// 采集变量的地址类型
            ///
            public string Address_Type;//采集变量的地址类型
            ///
            /// 采集变量的数据类型
            ///
            public string Type;//采集变量的数据类型
            ///
            /// 采集变量的数据类型的大小
            ///
            public string Size;//采集变量的数据类型的大小
            ///
            /// 采集变量的算法
            ///
            public string Conversion;//采集变量的算法
            ///
            /// 数组变量的数组大小(如果是数组类型的变量)
            ///
            public string Array_Size;//数组变量的数组大小(如果是数组类型的变量)
            ///
            /// 变量类型的名字
            ///
            public string Variable_Type_Name;//变量类型的名字
        }
        #endregion
        #region 将A2L文件中变量的地址、变量大小、数组大小、地址类型字符串解析成字节存储在AnalysisVarStruct结构体中
        ///
        /// 存储A2L文件中解析好的字节地址、变量大小、数组大小、地址类型
        ///
        public struct AnalysisVarStruct
        {
            ///
            /// 变量地址
            ///
            public byte[] Address;
            ///
            /// 变量大小
            ///
            public byte Size;
            ///
            /// 数组大小
            ///
            public byte Array_Size;
            ///
            /// 算法
            ///
            public double Conversion;
            ///
            /// 地址类型,即大小端
            ///
            public string Address_Type;
        }
        ///
        /// 将A2L文件中变量的地址、变量大小、数组大小、地址类型字符串解析成字节存储在AnalysisVarStruct结构体中
        ///
        /// 输入的结构体变量信息,里面包括地址、变量大小、数组大小、地址类型
        /// 将字符串地址、变量大小、数组大小、地址类型解析成字节存储到AnalysisVarStruct结构体当中
       public static bool Deal_Dictionary_Data(out AnalysisVarStructAnalysisVarS, VariableInformationStruct VariableInformationS)
        {
            AnalysisVarS = newAnalysisVarStruct();
            try
            {
                AnalysisVarS.Address = newbyte[4];
                AnalysisVarS.Size =Convert.ToByte(VariableInformationS.Size);
                for (int i = 1; i
                {
                    AnalysisVarS.Address[i - 1]= Convert.ToByte(VariableInformationS.Address.Substring(i * 2, 2), 16);
                }
                AnalysisVarS.Array_Size =Convert.ToByte(VariableInformationS.Array_Size);
                if(VariableInformationS.Conversion != "NULL METHOD")
                {
                    AnalysisVarS.Conversion =Convert.ToDouble(VariableInformationS.Conversion.Substring(2));
                }
                else
                {
                    AnalysisVarS.Conversion =1;
                }
                AnalysisVarS.Address_Type =VariableInformationS.Address_Type;
                return true;
            }
            catch
            {
                return false;
            }
        }
        #endregion
        #region 接收CAN发送的数据信息结构体
        ///
        /// 接收CAN发送的数据信息结构体
        ///
        public struct CanRecDataStruct
        {
            ///
            /// 存储CAN接收到的8个字节数据
            ///
            public byte[] bytedata;
            ///
            /// true表示CAN接收到信息;false表示CAN没有接收到信息
            ///
            public bool status;
            ///
            /// ID号
            ///
            public int id;
        }
        ///
        /// 定义CAN发接收数据信息结构体变量
        ///
        public static CanRecDataStructCanRecDataS;
        #endregion
        #region CAN发送数据事件
        ///
        /// 定义CAN发送数据委托
        ///
        /// 要发送的8个字节的数据
        /// PC端CAN的ID号
        ///
        /// 发送等待接收时间
        /// true:发送成功;false:发送失败
        public delegate boolSendMessageDelegate(byte[] can_send_byte, int id, int dlc, long timeout);
        ///
        /// CAN发送数据事件
        ///
        public static event SendMessageDelegateSendMessageD;
        #endregion
        #region 处理要下传的数据
        ///
        /// 处理要下传的数据
        ///
        /// 要处理的数据
        /// 处理之后的数据
        /// 要处理的数据对应的变量的结构体信息
        public static void DealDownData(outbyte[] bytedata, double data, VariableInformationStruct VariableInformationS)
        {
            #region 定义变量
            double match = 0;
            bytedata = new byte[5];
            Int64 datavalue = 0;
            #endregion
            #region 根据算法处理数据
            if (VariableInformationS.Conversion!= "NULL METHOD")
                match =Convert.ToDouble(VariableInformationS.Conversion.Substring(2));
            else match = 1;
            data = data * match;
            #endregion
            #region 判断变量类型判断数据是否溢出,并作出处理
            switch (VariableInformationS.Type)
            {
                case "SBYTE":
                    if (data > ((0xFF - 1) /2))
                    {
                        data = data - 0xFF - 1;
                    }
                    break;
                case "SWORD":
                    if (data > ((0xFFFF - 1)/ 2))
                    {
                        data = data - 0xFFFF -1;
                    }
                    break;
                case "SLONG":
                    if (data > ((0xFFFFFFFF- 1) / 2))
                    {
                        data = data -0xFFFFFFFF - 1;
                    }
                    break;
            }
            #endregion
            datavalue = (Int64)data;
            #region 根据大小端处理数据,并将其赋值给bytedata数组
            if(VariableInformationS.Address_Type == "BYTE_ORDER MSB_FIRST")
            {//大端高字节在前对应第一个元素
                switch(VariableInformationS.Size)
                {//高字节在前
                    case "1":
                        bytedata[0] =(byte)(0xFF & (datavalue >> 0));
                        bytedata[1] =bytedata[2] = bytedata[3] = bytedata[4] = 0x00;
                        break;
                    case "2":
                        bytedata[0] =(byte)(0xFF & (datavalue >> 8));
                        bytedata[1] =(byte)(0xFF & (datavalue >> 0));
                        bytedata[2] =bytedata[3] = bytedata[4] = 0x00;
                        break;
                    case "4":
                        bytedata[0] =(byte)(0xFF & (datavalue >> 24));
                        bytedata[1] =(byte)(0xFF & (datavalue >> 16));
                        bytedata[2] =(byte)(0xFF & (datavalue >> 8));
                        bytedata[3] = (byte)(0xFF &(datavalue >> 0));
                        bytedata[4] = 0x00;
                        break;
                }
            }
            else if(VariableInformationS.Address_Type == "BYTE_ORDER MSB_LAST")
            {
                switch(VariableInformationS.Size)
                {//低字节在前对应第一个元素
                    case "1":
                        bytedata[0] =(byte)(0xFF & (datavalue >> 0));
                        bytedata[1] =bytedata[2] = bytedata[3] = bytedata[4] = 0x00;
                        break;
                    case "2":
                        bytedata[0] =(byte)(0xFF & (datavalue >> 0));
                        bytedata[1] =(byte)(0xFF & (datavalue >> 8));
                        bytedata[2] =bytedata[3] = bytedata[4] = 0x00;
                        break;
                    case "4":
                        bytedata[0] =(byte)(0xFF & (datavalue >> 0));
                        bytedata[1] =(byte)(0xFF & (datavalue >> 8));
                        bytedata[2] = (byte)(0xFF &(datavalue >> 16));
                        bytedata[3] =(byte)(0xFF & (datavalue >> 24));
                        bytedata[4] = 0x00;
                        break;
                }
            }
            #endregion
        }
        #endregion
        #region 处理上传数据
        public static void DealUpData(byte[]bytedata, out double data, VariableInformationStruct VariableInformationS)
        {
            #region 定义变量
            double match = 0;
            data = 0;
            #endregion
            #region 根据大小端处理数据,并将其赋值给bytedata数组
            if(VariableInformationS.Address_Type == "BYTE_ORDER MSB_FIRST")
            {//大端高字节在前对应第一个元素
                switch(VariableInformationS.Size)
                {//高字节在前
                    case "1":
                        data = bytedata[0];
                        break;
                    case "2":
                        data = ((bytedata[0]<< 8) | bytedata[1]);
                        break;
                    case "4":
                        data = ((bytedata[0]<< 24) | (bytedata[1] << 16) | (bytedata[2] << 8) |bytedata[3]);
                        break;
                }
            }
            else if(VariableInformationS.Address_Type == "BYTE_ORDER MSB_LAST")
            {
                switch(VariableInformationS.Size)
                {//低字节在前对应第一个元素
                    case "1":
                        data = bytedata[0];
                        break;
                    case "2":
                        data = ((bytedata[1] << 8)| bytedata[0]);
                        break;
                    case "4":
                        data = ((bytedata[3]<< 24) | (bytedata[2] << 16) | (bytedata[1] << 8) |bytedata[0]);
                        break;
                }
            }
            #endregion
            #region 判断变量类型判断数据是否溢出,并作出处理
            switch (VariableInformationS.Type)
            {
                case "SBYTE":
                    if (data > ((0xFF - 1) /2))
                    {
                        data = data - 0xFF - 1;
                    }
                    break;
                case "SWORD":
                    if (data > ((0xFFFF - 1)/ 2))
                    {
                        data = data - 0xFFFF -1;
                    }
                    break;
                case "SLONG":
                    if (data > ((0xFFFFFFFF- 1) / 2))
                    {
                        data = data -0xFFFFFFFF - 1;
                    }
                    break;
            }
            #endregion
            #region 根据算法处理数据
            if (VariableInformationS.Conversion!= "NULL METHOD")
                match =Convert.ToDouble(VariableInformationS.Conversion.Substring(2));
            else match = 1;
            data = (data / match);
            #endregion
        }
        #endregion
        #region MCU和PC进行连接
        ///
        /// MCU和PC进行连接
        ///
        /// PC端CAN的ID号
        /// pollingPath路径
        /// dAQPath路径
        /// true:连接成功;false:连接失败
        public static bool MCUAndPCLink(int id,string pollingPath, string dAQPath)
        {
           try
            {
                #region 等待线程信号
                AutoResetEvent.WaitOne();
                #endregion
                #region 定义变量
                count = 0;
                byte pKey = 10;
                UInt16 sizeKey = 10;
               #endregion
                #region 获取.dll解密文件路径
                if (pollingPath == null)PollingPath = "";
                else PollingPath = pollingPath;
                if (dAQPath == null) DAQPath ="";
                else DAQPath = dAQPath;
                #endregion
                #region 初始化状态机
                MCUAndPCLinkCPPStateE =CPPOrderStateEnum.Send0x01CCPOrderState;
                #endregion
                #region 没有SeedKey连接
                if (PollingPath == ""&& DAQPath == "")
                {
                    while (true)
                    {
                        switch(MCUAndPCLinkCPPStateE)//发送0x01和0x14指令给下位机创建连接
                        {
                            #region 发送0x01CPP指令
                            caseCPPOrderStateEnum.Send0x01CCPOrderState:
                                count = 0;
                               MCUAndPCLinkCPPStateE = CPPOrderStateEnum.Send0x01CCPOrderStateSuccess;
                                if(!SendMessageD(new byte[] { 0x01, Ctr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },id, 8, 10))//发送连接的第一条指令
                                {
                                   MCUAndPCLinkCPPStateE = CPPOrderStateEnum.NullCCPOrderState;
                                    returnfalse;
                                }
                                break;
                            #endregion
                            #region 发送两次0x14CPP指令
                            caseCPPOrderStateEnum.Send0x14CCPOrderOneState:
                                count = 0;
                               MCUAndPCLinkCPPStateE =CPPOrderStateEnum.Send0x14CCPOrderOneStateSuccess;
                                if(!SendMessageD(new byte[] { 0x14, Ctr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36 }, id,8, 10))
                                {
                                   MCUAndPCLinkCPPStateE = CPPOrderStateEnum.NullCCPOrderState;
                                    returnfalse;
                                }
                                break;
                            caseCPPOrderStateEnum.Send0x14CCPOrderTwoState:
                                count = 0;
                               MCUAndPCLinkCPPStateE =CPPOrderStateEnum.Send0x14CCPOrderTwoStateSuccess;
                                if (!SendMessageD(new byte[] {0x14, Ctr, 0x01, 0x00, 0x00, 0x00, 0x00, 0x36 }, id, 8, 10))
                                {
                                   MCUAndPCLinkCPPStateE = CPPOrderStateEnum.NullCCPOrderState;
                                    return false;
                                }
                                break;
                            #endregion
                        }
                        if(MCUAndPCLinkCPPStateE == CPPOrderStateEnum.MCULinkPCStateSuccess)
                        {
                           MCUAndPCLinkCPPStateE = CPPOrderStateEnum.NullCCPOrderState;
                            return true;
                        }
                        #region 循环超时
                        if (count > 1000)
                        {
                           MCUAndPCLinkCPPStateE = CPPOrderStateEnum.NullCCPOrderState;
                            return false;
                        }
                        #endregion
                        #region 线程休眠,循环次数++
                        Thread.Sleep(1);
                        count++;
                        #endregion
                    }
                }
                #endregion
                #region 有SeedKey连接
                else if (PollingPath !="" || DAQPath != "")
                {
                    while (true)
                    {
                        switch(MCUAndPCLinkCPPStateE)
                        {
                            #region 发送0x01CPP指令
                            caseCPPOrderStateEnum.Send0x01CCPOrderState:
                                count = 0;
                               MCUAndPCLinkCPPStateE = CPPOrderStateEnum.Send0x01CCPOrderStateSuccess;
                                if(!SendMessageD(new byte[] { 0x01, Ctr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },id, 8, 10))//发送连接的第一条指令
                                {
                                   MCUAndPCLinkCPPStateE = CPPOrderStateEnum.NullCCPOrderState;
                                    returnfalse;
                                }
                                break;
                            #endregion
                            #region Polling模式
                            caseCPPOrderStateEnum.Send0x12CCPOrderPollingState:
                                count = 0;
                               MCUAndPCLinkCPPStateE =CPPOrderStateEnum.Send0x12CCPOrderPollingStateSuccess;
                                if(!SendMessageD(new byte[] { 0x12, Ctr, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 },id, 8, 10))
                                {
                                   MCUAndPCLinkCPPStateE = CPPOrderStateEnum.NullCCPOrderState;
                                    returnfalse;
                                }
                                break;
                            caseCPPOrderStateEnum.Send0x13CCPOrderPollingState:
                                count = 0;
                               Array.Copy(CanRecDataS.bytedata, 4, pSeed, 0, 4);
                                CallDll.Function_Dll(PollingPath,"ASAP1A_CCP_ComputeKeyFromSeed", pSeed, 10, out pKey, 10, outsizeKey);
                               CallDll.Achieve_Secret_Key(ref pKey, out pSeed, sizeKey);
                               MCUAndPCLinkCPPStateE = CPPOrderStateEnum.Send0x13CCPOrderPollingStateSuccess;
                                if(!SendMessageD(new byte[] { 0x13, Ctr, pSeed[0], pSeed[1], pSeed[2], pSeed[3],0x00, 0x00 }, id, 8, 10))
                                {
                                    MCUAndPCLinkCPPStateE= CPPOrderStateEnum.NullCCPOrderState;
                                    returnfalse;
                                }
                                break;
                            #endregion
                            #region DAQ模式
                            caseCPPOrderStateEnum.Send0x12CCPOrderDAQState:
                                count = 0;
                               MCUAndPCLinkCPPStateE =CPPOrderStateEnum.Send0x12CCPOrderDAQStateSuccess;
                                if (!SendMessageD(new byte[] {0x12, Ctr, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 }, id, 8, 10))
                                {
                                   MCUAndPCLinkCPPStateE = CPPOrderStateEnum.NullCCPOrderState;
                                    return false;
                                }
                                break;
                            caseCPPOrderStateEnum.Send0x13CPPOrderDAQStateSuccess:
                                count = 0;
                                PollingPath = "";
                               Array.Copy(CanRecDataS.bytedata, 4, pSeed, 0, 4);
                               CallDll.Function_Dll(DAQPath, "ASAP1A_CCP_ComputeKeyFromSeed",pSeed, 0, out pKey, 0, out sizeKey);
                                CallDll.Achieve_Secret_Key(refpKey, out pSeed, sizeKey);
                               MCUAndPCLinkCPPStateE =CPPOrderStateEnum.Send0x13CPPOrderDAQStateSuccess;
                                if(!SendMessageD(new byte[] { 0x13, Ctr, pSeed[0], pSeed[1], pSeed[2], pSeed[3],0x00, 0x00 }, id, 8, 10))
                                {
                                   MCUAndPCLinkCPPStateE = CPPOrderStateEnum.NullCCPOrderState;
                                    returnfalse;
                                }
                                break;
                            #endregion
                            #region 发送两次0x14CPP指令
                            caseCPPOrderStateEnum.Send0x14CCPOrderOneState:
                                count = 0;
                               MCUAndPCLinkCPPStateE =CPPOrderStateEnum.Send0x14CCPOrderOneStateSuccess;
                                if(!SendMessageD(new byte[] { 0x14, Ctr, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10 },id, 8, 10))
                                {
                                   MCUAndPCLinkCPPStateE = CPPOrderStateEnum.NullCCPOrderState;
                                    returnfalse;
                                }
                                break;
                            caseCPPOrderStateEnum.Send0x14CCPOrderTwoState:
                                count = 0;
                               MCUAndPCLinkCPPStateE =CPPOrderStateEnum.Send0x14CCPOrderTwoStateSuccess;
                                if (!SendMessageD(newbyte[] { 0x14, Ctr, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01 }, id, 8, 10))
                                {
                                   MCUAndPCLinkCPPStateE = CPPOrderStateEnum.NullCCPOrderState;
                                    returnfalse;
                                }
                                break;
                            #endregion
                        }
                        if(MCUAndPCLinkCPPStateE == CPPOrderStateEnum.MCULinkPCStateSuccess)
                        {
                           MCUAndPCLinkCPPStateE = CPPOrderStateEnum.NullCCPOrderState;
                            return true;
                        }
                        #region 循环超时
                        if (count > 1000)//连接失败
                        {
                           MCUAndPCLinkCPPStateE = CPPOrderStateEnum.NullCCPOrderState;
                            return false;
                        }
                        #endregion
                        #region 线程休眠,循环次数++
                        Thread.Sleep(1);
                        count++;
                        #endregion
                    }
                }
                MCUAndPCLinkCPPStateE =CPPOrderStateEnum.NullCCPOrderState;
                return true;
                #endregion
            }
            catch { MCUAndPCLinkCPPStateE =CPPOrderStateEnum.NullCCPOrderState; return false; }
            finally { AutoResetEvent.Set(); }
        }
        #endregion
        #region 下发数据
        #region 下发选中的单个标定量
        ///
        /// 下发选中的单个标定量
        ///
        /// PC端CAN的ID号
        /// 下传的数据
        /// 需要下传的A2L文件里的结构体变量
        /// true:下传成功;false:下传失败
        public static bool CCPDownOneData(intid, double data, VariableInformationStruct VariableInformationS)
        {
            try
            {
                #region 等待线程信号
                AutoResetEvent.WaitOne();
                #endregion
                #region 定义变量
                count = 0;
                address = 0;//地址大小
                int firstFew = 0;//第几个数组元素
                #endregion
                #region 数据处理
                //AnalysisVarStruct AnalysisVarS = newAnalysisVarStruct();//清除上次数据记录
                Deal_Dictionary_Data(outAnalysisVarS, VariableInformationS);
                //byte[] bytedata = newbyte[5];
                DealDownData(out bytedata,data, VariableInformationS);
                #endregion
                #region 地址处理
                address =(AnalysisVarS.Address[0] << 24) + (AnalysisVarS.Address[1] << 16) +(AnalysisVarS.Address[2] << 8) + AnalysisVarS.Address[3];
                if (VariableInformationS.Name.Contains("--"))
                {
                    firstFew =Convert.ToInt32(VariableInformationS.Name.Substring(VariableInformationS.Name.LastIndexOf("--")+ 2));
                    address +=AnalysisVarS.Size * firstFew;
                }
                if(VariableInformationS.Address_Type == "BYTE_ORDER MSB_LAST")
                {
                    address = ((address &0x000000FF) << 24) + ((address & 0x0000FF00) << 8) + ((address& 0x00FF0000) >> 8) + ((address & 0x00FF0000) >> 24);
                }
                #endregion
                DownDataCCPStateE =CPPOrderStateEnum.Send0x02CCPOrderState;
                while (true)
                {
                    switch (DownDataCCPStateE)
                    {
                        caseCPPOrderStateEnum.Send0x02CCPOrderState:
                            DownDataCCPStateE =CPPOrderStateEnum.Send0x02CCPOrderStateSuccess;//标记0x02指令已经开始发送
                            if(!SendMessageD(new byte[] { 0x02, Ctr, 0x00, 0x00, (byte)(0xFF & (address>> 24)), (byte)(0xFF & (address >> 16)), (byte)(0xFF &(address >> 8)), (byte)(0xFF & address) }, id, 8, 10))
                            {
                               DownDataCCPStateE = CPPOrderStateEnum.NullCCPOrderState;
                                return false;
                            }
                            count = 0;
                            break;
                        caseCPPOrderStateEnum.Send0x03CCPOrderState:
                            DownDataCCPStateE =CPPOrderStateEnum.Send0x03CCPOrderStateSuccess;//标记0x02指令已经开始发送
                            if(!SendMessageD(new byte[] { 0x03, Ctr, AnalysisVarS.Size, bytedata[0],bytedata[1], bytedata[2], bytedata[3], bytedata[4] }, id, 8, 10))
                            {
                               DownDataCCPStateE = CPPOrderStateEnum.NullCCPOrderState;
                                return false;
                            }
                            count = 0;
                            break;
                    }
                    if (DownDataCCPStateE ==CPPOrderStateEnum.CCPDownDataStateSuccess)//下传数据成功
                    {
                        count = 0;
                        DownDataCCPStateE =CPPOrderStateEnum.NullCCPOrderState;
                        return true;
                    }
                    if (count >= 1000)//下传数据失败
                    {
                        DownDataCCPStateE =CPPOrderStateEnum.NullCCPOrderState;
                        return false;
                    }
                    Thread.Sleep(1);
                    count++;
                }
            }
            catch { DownDataCCPStateE =CPPOrderStateEnum.NullCCPOrderState; return false; }
            finally { AutoResetEvent.Set(); }
        }
        #endregion
        #region 下发选中的多个标定量
        ///
        /// 下发选中的多个标定量
        ///
        /// PC端CAN的ID号
        /// 存储需要下传数据的泛型集合
        /// 存储需要下传的A2L文件变量的泛型集合
        /// true:下传成功;false:下传失败
        public static bool CCPDownManyData(intid, Dictionary dicData, Dictionary VariableInformationDic)
        {
            try
            {
                #region 等待线程信号
                AutoResetEvent.WaitOne();
                #endregion
                #region 定义变量
                count = 0;
                address = 0;//地址大小
                int firstFew = 0;//第几个数组元素
                #endregion
                foreach (KeyValuePair dic in VariableInformationDic)
                {
                    #region 数据处理
                    //AnalysisVarStruct AnalysisVarS= new AnalysisVarStruct();//清除上次数据记录
                    Deal_Dictionary_Data(outAnalysisVarS, dic.Value);
                    //byte[] bytedata = newbyte[5];
                    DealDownData(out bytedata,dicData[dic.Key], dic.Value);
                    #endregion
                    #region 地址处理
                    address =(AnalysisVarS.Address[0] << 24) + (AnalysisVarS.Address[1] << 16) +(AnalysisVarS.Address[2] << 8) + AnalysisVarS.Address[3];
                    if (dic.Value.Name.Contains("--"))
                    {
                        firstFew =Convert.ToInt32(dic.Value.Name.Substring(dic.Value.Name.LastIndexOf("--")+ 2));
                        address +=AnalysisVarS.Size * firstFew;
                    }
                    if (dic.Value.Address_Type== "BYTE_ORDER MSB_LAST")
                    {
                        address = ((address& 0x000000FF) << 24) + ((address & 0x0000FF00) << 8) +((address & 0x00FF0000) >> 8) + ((address & 0x00FF0000) >>24);
                    }
                    #endregion
                    DownDataCCPStateE =CPPOrderStateEnum.Send0x02CCPOrderState;
                    while (true)
                    {
                        switch(DownDataCCPStateE)
                        {
                            caseCPPOrderStateEnum.Send0x02CCPOrderState:
                               DownDataCCPStateE = CPPOrderStateEnum.Send0x02CCPOrderStateSuccess;//标记0x02指令已经开始发送
                                if(!SendMessageD(new byte[] { 0x02, Ctr, 0x00, 0x00, (byte)(0xFF & (address>> 24)), (byte)(0xFF & (address >> 16)), (byte)(0xFF &(address >> 8)), (byte)(0xFF & address) }, id, 8, 10))
                                {
                                   DownDataCCPStateE = CPPOrderStateEnum.NullCCPOrderState;
                                    returnfalse;
                                }
                                count = 0;
                                break;
                            caseCPPOrderStateEnum.Send0x03CCPOrderState:
                               DownDataCCPStateE = CPPOrderStateEnum.Send0x03CCPOrderStateSuccess;//标记0x02指令已经开始发送
                                if(!SendMessageD(new byte[] { 0x03, Ctr, AnalysisVarS.Size, bytedata[0],bytedata[1], bytedata[2], bytedata[3], bytedata[4] }, id, 8, 10))
                                {
                                   DownDataCCPStateE = CPPOrderStateEnum.NullCCPOrderState;
                                    returnfalse;
                                }
                                count = 0;
                                break;
                        }
                        if (DownDataCCPStateE== CPPOrderStateEnum.CCPDownDataStateSuccess)//下传数据成功
                        {
                            DownDataCCPStateE =CPPOrderStateEnum.Send0x02CCPOrderState;
                            count = 0;
                            break;
                        }
                        if (count >= 1000)//下传数据失败
                        {
                            DownDataCCPStateE =CPPOrderStateEnum.NullCCPOrderState;
                            return false;
                        }
                        Thread.Sleep(1);
                        count++;
                    }
                }
                DownDataCCPStateE =CPPOrderStateEnum.NullCCPOrderState;
                return true;
            }
            catch
            {
                DownDataCCPStateE =CPPOrderStateEnum.NullCCPOrderState;
                return false;
            }
            finally { AutoResetEvent.Set(); }
        }
        #endregion
        #endregion
        #region 上传数据
        #region 上传单个数据
        ///
        /// 上传单个数据
        ///
        /// PC端CAN的ID号
        /// 上传的数据
        /// 需要上传的A2L文件里的结构体变量
        /// true:上传成功;false:上传失败
        public static bool CCPUpOneData(int id,out double dicData, VariableInformationStruct VariableInformationS)
        {
            dicData = 0;
            try
            {
                #region 等待线程信号
                AutoResetEvent.WaitOne();
                #endregion
                #region 定义变量
                count = 0;
                int firstFew = 0;//第几个数组元素
                address = 0;//地址大小
                #endregion
                #region 获取地址
                //AnalysisVarStructAnalysisVarS = new AnalysisVarStruct();//清除上次数据记录
                Deal_Dictionary_Data(out AnalysisVarS,VariableInformationS);
                address =(AnalysisVarS.Address[0] << 24) + (AnalysisVarS.Address[1] << 16) +(AnalysisVarS.Address[2] << 8) + AnalysisVarS.Address[3];
                if(VariableInformationS.Name.Contains("--"))
                {
                    firstFew =Convert.ToInt32(VariableInformationS.Name.Substring(VariableInformationS.Name.LastIndexOf("--")+ 2));
                    address +=AnalysisVarS.Size * firstFew;
                }
                if (VariableInformationS.Address_Type== "BYTE_ORDER MSB_LAST")
                {
                    address = ((address &0x000000FF) << 24) + ((address & 0x0000FF00) << 8) + ((address& 0x00FF0000) >> 8) + ((address & 0x00FF0000) >> 24);
                }
                #endregion
                UpDataCCPStateE =CPPOrderStateEnum.Send0x0FCCPOrderState;
                while (true)
                {
                    switch (UpDataCCPStateE)
                    {
                        caseCPPOrderStateEnum.Send0x0FCCPOrderState:
                            UpDataCCPStateE =CPPOrderStateEnum.Send0x0FCCPOrderStateSuccess;
                            if(!SendMessageD(new byte[] { 0x0F, Ctr, AnalysisVarS.Size, 0x00, (byte)(0xFF& (address >> 24)), (byte)(0xFF & (address >> 16)),(byte)(0xFF & (address >> 8)), (byte)(0xFF & address) }, id, 8,10))
                            {
                                UpDataCCPStateE= CPPOrderStateEnum.NullCCPOrderState;
                                return false;
                            }
                            count = 0;
                            break;
                    }
                    if (UpDataCCPStateE ==CPPOrderStateEnum.CCPUpDataStateSuccess)//成功
                    {
                        count = 0;
                        DealUpData(TempBuf, outdicData, VariableInformationS);
                        UpDataCCPStateE =CPPOrderStateEnum.NullCCPOrderState;
                        return true;
                    }
                    if (count >= 1000)//失败
                    {
                        count = 0;
                        UpDataCCPStateE =CPPOrderStateEnum.NullCCPOrderState;
                        return false;
                    }
                    Thread.Sleep(1);//让线程休息50ms
                    count++;
                }
            }
            catch { UpDataCCPStateE =CPPOrderStateEnum.NullCCPOrderState; return false; }
            finally { AutoResetEvent.Set(); }
        }
        #endregion
        #region 上传多个数据
        ///
        /// 上传多个数据
        ///
        /// PC端CAN的ID号
        /// 存储上传的数据的泛型集合
        /// 存储需要上传的A2L文件变量的泛型集合
        ///
        public static bool CCPUpManyData(intid, out Dictionary dicData, Dictionary variableInformationStructDic)
        {
            dicData = new Dictionary();
            try
            {
                #region 等待线程信号
                AutoResetEvent.WaitOne();
                #endregion
                #region 定义变量
                count = 0;
                int firstFew = 0;//第几个数组元素
                address = 0;//地址大小
                double data = 0;
                #endregion
                UpDataCCPStateE =CPPOrderStateEnum.Send0x0FCCPOrderState;
                foreach (KeyValuePair dic in variableInformationStructDic)
                {
                    #region 获取地址
                    //AnalysisVarStructAnalysisVarS = new AnalysisVarStruct();//清除上次数据记录
                    Deal_Dictionary_Data(outAnalysisVarS, dic.Value);
                    address = (AnalysisVarS.Address[0]<< 24) + (AnalysisVarS.Address[1] << 16) + (AnalysisVarS.Address[2]<< 8) + AnalysisVarS.Address[3];
                    if(dic.Value.Name.Contains("--"))
                    {
                        firstFew =Convert.ToInt32(dic.Value.Name.Substring(dic.Value.Name.LastIndexOf("--")+ 2));
                        address +=AnalysisVarS.Size * firstFew;
                    }
                    if (dic.Value.Address_Type== "BYTE_ORDER MSB_LAST")
                    {
                        address = ((address & 0x000000FF)<< 24) + ((address & 0x0000FF00) << 8) + ((address &0x00FF0000) >> 8) + ((address & 0x00FF0000) >> 24);
                    }
                    #endregion
                    while (true)
                    {
                        switch(UpDataCCPStateE)
                        {
                            caseCPPOrderStateEnum.Send0x0FCCPOrderState:
                                UpDataCCPStateE= CPPOrderStateEnum.Send0x0FCCPOrderStateSuccess;
                                if (!SendMessageD(newbyte[] { 0x0F, Ctr, AnalysisVarS.Size, 0x00, (byte)(0xFF & (address>> 24)), (byte)(0xFF & (address >> 16)), (byte)(0xFF &(address >> 8)), (byte)(0xFF & address) }, id, 8, 10))
                                {
                                    count = 0;
                                   UpDataCCPStateE = CPPOrderStateEnum.NullCCPOrderState;
                                    returnfalse;
                                }
                                count = 0;
                                break;
                        }
                        if (UpDataCCPStateE ==CPPOrderStateEnum.CCPUpDataStateSuccess)
                        {
                            UpDataCCPStateE =CPPOrderStateEnum.Send0x0FCCPOrderState;
                            DealUpData(TempBuf,out data, dic.Value);
                           dicData.Add(dic.Key, data);
                            count = 0;
                            break;
                        }
                        if (count >= 1000)
                        {
                            count = 0;
                            UpDataCCPStateE =CPPOrderStateEnum.NullCCPOrderState;
                            return false;
                        }
                        Thread.Sleep(1);//让线程休息50ms
                        count++;
                    }
                }
                UpDataCCPStateE =CPPOrderStateEnum.NullCCPOrderState;
                return true;
            }
            catch { UpDataCCPStateE =CPPOrderStateEnum.NullCCPOrderState; return false; }
            finally { AutoResetEvent.Set(); }
        }
        #endregion
        #endregion
        #region 响应CPP指令
        #region 响应CPP指令线程
        ///
        /// 响应CPP指令线程
        ///
        public static ThreadCCPOrderResponseThread;
        #endregion
        #region 响应CPP指令
        ///
        /// 响应CPP指令
        ///
        public static void CCPOrderResponse()
        {
            while (true)
            {
                try
                {
                    if (CanRecDataS.status)//表示CAN收到数据了
                    {
                        CanRecDataS.status =false;
                        switch(MCUAndPCLinkCPPStateE)
                        {
                            #region 发送0x01CPP指令
                            caseCPPOrderStateEnum.Send0x01CCPOrderStateSuccess:
                                if (PollingPath!= "" && PollingPath != null)
                                    MCUAndPCLinkCPPStateE =CPPOrderStateEnum.Send0x12CCPOrderPollingState;
                                else if(DAQPath != "" && DAQPath != null)
                                   MCUAndPCLinkCPPStateE = CPPOrderStateEnum.Send0x12CCPOrderDAQState;
                                else
                                   MCUAndPCLinkCPPStateE = CPPOrderStateEnum.Send0x14CCPOrderOneState;
                                break;
                            #endregion
                            #region Polling模式
                            caseCPPOrderStateEnum.Send0x12CCPOrderPollingStateSuccess:
                               MCUAndPCLinkCPPStateE = CPPOrderStateEnum.Send0x13CCPOrderPollingState;
                                break;
                            caseCPPOrderStateEnum.Send0x13CCPOrderPollingStateSuccess:
                                if (DAQPath !="" && DAQPath != null)
                                   MCUAndPCLinkCPPStateE = CPPOrderStateEnum.Send0x12CCPOrderDAQState;
                                else
                                   MCUAndPCLinkCPPStateE = CPPOrderStateEnum.Send0x14CCPOrderOneState;
                                break;
                            #endregion
                            #region DAQ模式
                            caseCPPOrderStateEnum.Send0x12CCPOrderDAQStateSuccess:
                               MCUAndPCLinkCPPStateE =CPPOrderStateEnum.Send0x13CPPOrderDAQStateSuccess;
                                break;
                            caseCPPOrderStateEnum.Send0x13CPPOrderDAQStateSuccess:
                               MCUAndPCLinkCPPStateE = CPPOrderStateEnum.Send0x14CCPOrderOneState;
                                break;
                            #endregion
                            #region 发送两次0x14CCP指令
                            caseCPPOrderStateEnum.Send0x14CCPOrderOneStateSuccess:
                               MCUAndPCLinkCPPStateE = CPPOrderStateEnum.Send0x14CCPOrderTwoState;
                                break;
                            caseCPPOrderStateEnum.Send0x14CCPOrderTwoStateSuccess://连接成功
                               MCUAndPCLinkCPPStateE = CPPOrderStateEnum.MCULinkPCStateSuccess;
                                break;
                            #endregion
                        }
                        switch(DownDataCCPStateE)
                        {
                            caseCPPOrderStateEnum.Send0x02CCPOrderStateSuccess:
                                DownDataCCPStateE= CPPOrderStateEnum.Send0x03CCPOrderState;
                                break;
                            caseCPPOrderStateEnum.Send0x03CCPOrderStateSuccess:
                               DownDataCCPStateE = CPPOrderStateEnum.CCPDownDataStateSuccess;
                                break;
                        }
                        switch(UpDataCCPStateE)
                        {
                            caseCPPOrderStateEnum.Send0x0FCCPOrderStateSuccess:
                                TempBuf = new byte[5];
                               Array.Copy(CanRecDataS.bytedata, 3, TempBuf, 0, 5);
                                UpDataCCPStateE= CPPOrderStateEnum.CCPUpDataStateSuccess;
                                break;
                        }
                    }
                    Thread.Sleep(1);
                }
                catch { }
            }
        }
        #endregion
        #region 打开响应CPP指令线程
        ///
        /// 打开响应CPP指令线程
        ///
        ///
        public static boolOpenCCPOrderResponseThread()
        {
            try
            {
                //打开CCP响应线程
                if (CCPOrderResponseThread !=null) CCPOrderResponseThread.Abort();
               CCPOrderResponseThread = new Thread(new ThreadStart(CCPOrderResponse));
               CCPOrderResponseThread.IsBackground = true;
                CCPOrderResponseThread.Start();
                while(!CCPOrderResponseThread.IsAlive == true) Thread.Sleep(1);
                return true;
            }
            catch { return false; }
        }
        #endregion
        #region 关闭响应CPP指令线程
        ///
        /// 关闭响应CPP指令线程
        ///
        ///
        public static boolCloseCCPOrderResponseThread()
        {
            try
            {
                if (CCPOrderResponseThread !=null)
                {
                    if(CCPOrderResponseThread.IsAlive==true)CCPOrderResponseThread.Abort();
                }
                return true;
            }
            catch { return false; }
        }
        #endregion
        #endregion
    }

调用很简单,里面有一个发送数据的委托事件,只需要将CAN发送数据的函数添加到该时间里,然后调用对应的静态函数来实现数据的读写以及连接。这个静态内中添加了线程互斥信号AutoResetEvent AutoResetEvent,通过AutoResetEvent AutoResetEvent可以实现多线程共同访问该静态类,不会出现资源被无端修改等情况的发生,它能确保线程的互斥和同步,这个已经在我们公司生产EPS的生产线软件中做过验证,通过上位机软件利用CAN同时测试4EPS模块,大大的节省了时间。
有兴趣的可以加我:
QQ:1343263021 微信:18862121743   QQ群:100300621
寻求项目合作:单片机、上位机
联系电话:18862121743

回帖(2)

abc

2017-9-7 08:37:49
學習了,謝謝~~
举报

贾梦琦

2018-9-15 16:56:08
受到警告
提示: 作者被禁止或删除 内容自动屏蔽
举报

更多回帖

×
20
完善资料,
赚取积分