完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
从事汽车电子的人应该都知道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结构体中 /// /// /// 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发送数据委托 /// /// /// PC端CAN的ID号 /// /// /// 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号 /// /// /// 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号 /// 下传的数据 /// /// 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号 /// /// /// public static bool CCPDownManyData(intid, Dictionary { try { #region 等待线程信号 AutoResetEvent.WaitOne(); #endregion #region 定义变量 count = 0; address = 0;//地址大小 int firstFew = 0;//第几个数组元素 #endregion foreach (KeyValuePair { #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号 /// /// /// 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号 /// /// /// public static bool CCPUpManyData(intid, out Dictionary { 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 { #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同时测试4个EPS模块,大大的节省了时间。 有兴趣的可以加我: QQ:1343263021 微信:18862121743 QQ群:100300621 寻求项目合作:单片机、上位机 联系电话:18862121743 |
|
相关推荐
|
|
只有小组成员才能发言,加入小组>>
1873 浏览 0 评论
5117 浏览 2 评论
8324 浏览 1 评论
3324 浏览 1 评论
7295 浏览 0 评论
新能源车维修技术交流,维修技术思维导图指南(12-09持继更新,分享原文件)
4310浏览 3评论
2127浏览 3评论
990浏览 1评论
《新能源车维修技术自学,链接汇总AI智能分类》超4000案例
5778浏览 1评论
1753浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-23 21:22 , Processed in 1.065461 second(s), Total 78, Slave 58 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号