using CompressorXN_Common; using CompressorXN_Log; using CompressorXN_Model.Enums; using System; using System.Runtime.InteropServices; using System.Threading; using thinger.DataConvertLib; using USB2XXX; namespace CompressorXN_Communication.TuMos { public class TMSCANHelper : BaseTMS { private static Int32 SendMsgNum = 0; private static Int32 ret = 0; private static Thread CANSendMsgThread = null; //private static Thread CANSenAdditionalMsgThread = null; private static Thread CANReadMsgThread = null; /// /// 启动线程 /// public static void CAN_StartTask() { //清空接收缓冲区数据 ret = USB2CAN.CAN_ClearMsg(DevHandle, ReadCANIndex); if (ret != USB2CAN.CAN_SUCCESS) { Console.WriteLine("Clear Message Failed!"); return; } else { Console.WriteLine("Clear Message Success!"); } //启动CAN接收数据 ret = USB2CAN.CAN_StartGetMsg(DevHandle, ReadCANIndex); if (ret != USB2CAN.CAN_SUCCESS) { Console.WriteLine("Start CAN failed!"); return; } else { Console.WriteLine("Start CAN Success!"); } if (CANReadMsgThread == null) { CANReadMsgThread = new Thread(new ThreadStart(ReadCanMsgThread)); CANReadMsgThread.Start(); } if (CANSendMsgThread == null) { CANSendMsgThread = new Thread(new ThreadStart(SendCanMsgThread)); CANSendMsgThread.Start(); } GlobalVar.CAN_ReadMsgFlag = true; GlobalVar.CAN_SendMsgFlag = true; // CANSendMsgThread = new Thread(new ThreadStart(SendCanMsgThread)); //// CANSenAdditionalMsgThread = new Thread(new ThreadStart(SendAdditionalCanMsg)); // CANReadMsgThread = new Thread(new ThreadStart(ReadCanMsgThread)); // //清空接收缓冲区数据 // ret = USB2CAN.CAN_ClearMsg(DevHandle, ReadCANIndex); // if (ret != USB2CAN.CAN_SUCCESS) // { // Console.WriteLine("Clear Message Failed!"); // return; // } // else // { // Console.WriteLine("Clear Message Success!"); // } // //启动CAN接收数据 // ret = USB2CAN.CAN_StartGetMsg(DevHandle, ReadCANIndex); // if (ret != USB2CAN.CAN_SUCCESS) // { // Console.WriteLine("Start CAN failed!"); // return; // } // else // { // Console.WriteLine("Start CAN Success!"); // } // //启动接收数据线程 // GlobalVar.CAN_ReadMsgFlag = true; // CANReadMsgThread.Start(); // //CANSenAdditionalMsgThread.Start(); // //启动发送数据线程 // GlobalVar.CAN_SendMsgFlag = true; // CANSendMsgThread.Start(); } /// /// 停止线程 /// public static void CAN_StopTask() { GlobalVar.CAN_SendMsgFlag = false; } /// /// 发送CAN数据 /// public static void SendCanMsgThread() { while (true) { if (!GlobalVar.CAN_SendMsgFlag) { Thread.Sleep(10); continue; } USB2CAN.CAN_MSG[] CanMsg = new USB2CAN.CAN_MSG[1]; CanMsg[0] = new USB2CAN.CAN_MSG { ExternFlag = GlobalVar.agreementMsgVM.FrameType == "EXTEND" ? (byte)1 : (byte)0, //bit[0] - 是否是扩展帧,bit[7] - 当前帧为错误帧 RemoteFlag = 0,//bit[0]-是否是远程帧,bit[6..5]-当前帧通道号,bit[7]-发送帧标志 ID = Convert.ToUInt32(GlobalVar.agreementMsgVM.SendId, 16),//报文ID DataLen = (byte)(GlobalVar.agreementMsgVM.FrameLen & 0xFF)//数据长度(<=8),即Data中有效数据长度 }; switch (GlobalVar.stepEnum) { case StepEnum.idling: string idlingHex = GlobalVar.agreementMsgVM.IdlingHex; if (!string.IsNullOrEmpty(idlingHex)) { CanMsg[0].Data = ByteArrayLib.GetByteArrayFromHexString(idlingHex); } break; case StepEnum.speed1: string speed1Hex = GlobalVar.agreementMsgVM.Speed1Hex; if (!string.IsNullOrEmpty(speed1Hex)) { Console.WriteLine($"{DateTime.Now.ToString("mm:ss fff")}:speed1Hex=={speed1Hex}"); CanMsg[0].Data = ByteArrayLib.GetByteArrayFromHexString(speed1Hex); } break; case StepEnum.speed2: string speed2Hex = GlobalVar.agreementMsgVM.Speed2Hex; if (!string.IsNullOrEmpty(speed2Hex)) { Console.WriteLine($"{DateTime.Now.ToString("mm:ss fff")}:speed2Hex=={speed2Hex}"); CanMsg[0].Data = ByteArrayLib.GetByteArrayFromHexString(speed2Hex); } break; case StepEnum.speed3: string speed3Hex = GlobalVar.agreementMsgVM.Speed3Hex; if (!string.IsNullOrEmpty(speed3Hex)) { Console.WriteLine($"{DateTime.Now.ToString("mm:ss fff")}:speed3Hex=={speed3Hex}"); CanMsg[0].Data = ByteArrayLib.GetByteArrayFromHexString(speed3Hex); } break; case StepEnum.endolead: string endoleadHex = GlobalVar.agreementMsgVM.EndoleadHex; if (string.IsNullOrEmpty(endoleadHex)) { CanMsg[0].Data = ByteArrayLib.GetByteArrayFromHexString(endoleadHex); } break; case StepEnum.singleDriver: string singleDriverHex = GlobalVar.agreementMsgVM.SingleDriverHex; if (!string.IsNullOrEmpty(singleDriverHex)) { CanMsg[0].Data = ByteArrayLib.GetByteArrayFromHexString(singleDriverHex); } break; } int SendedNum = USB2CAN.CAN_SendMsg(DevHandle, WriteCANIndex, CanMsg, (UInt32)CanMsg.Length); if (SendedNum >= 0) { SendMsgNum += SendedNum; Console.WriteLine($"{DateTime.Now.ToString("mm:ss fff")}:Success send frames:{SendMsgNum}"); } else { Console.WriteLine("Send CAN data failed!"); break; } //附加报文 if (!string.IsNullOrEmpty(GlobalVar.agreementMsgVM.SendAdditionalRules.AdditionalSendId)) { Thread.Sleep(GlobalVar.agreementMsgVM.SendAdditionalRules.AdditionalPeriod); USB2CAN.CAN_MSG[] additionalCanMsg = new USB2CAN.CAN_MSG[1]; additionalCanMsg[0] = new USB2CAN.CAN_MSG { ExternFlag = GlobalVar.agreementMsgVM.FrameType == "EXTEND" ? (byte)1 : (byte)0, //bit[0] - 是否是扩展帧,bit[7] - 当前帧为错误帧 RemoteFlag = 0,//bit[0]-是否是远程帧,bit[6..5]-当前帧通道号,bit[7]-发送帧标志 ID = Convert.ToUInt32(GlobalVar.agreementMsgVM.SendAdditionalRules.AdditionalSendId, 16),//报文ID DataLen = 8,//数据长度(<=8),即Data中有效数据长度 Data = ByteArrayLib.GetByteArrayFromHexString(GlobalVar.agreementMsgVM.SendAdditionalRules.AdditionalContent) }; SendedNum = USB2CAN.CAN_SendMsg(DevHandle, WriteCANIndex, additionalCanMsg, (UInt32)additionalCanMsg.Length); if (SendedNum >= 0) { SendMsgNum += SendedNum; Console.WriteLine("Success send frames:{0}", SendMsgNum); } else { Console.WriteLine("Send CAN data failed!"); break; } } //Thread.Sleep(45); Thread.Sleep(GlobalVar.agreementMsgVM.SendPeriod); } } /// /// 发送附加报文 /// public static void SendAdditionalCanMsg() { while (GlobalVar.CAN_SendMsgFlag) { //附加报文 if (!string.IsNullOrEmpty(GlobalVar.agreementMsgVM.SendAdditionalRules.AdditionalSendId)) { USB2CAN.CAN_MSG[] additionalCanMsg = new USB2CAN.CAN_MSG[1]; additionalCanMsg[0] = new USB2CAN.CAN_MSG { ExternFlag = GlobalVar.agreementMsgVM.FrameType == "EXTEND" ? (byte)1 : (byte)0, //bit[0] - 是否是扩展帧,bit[7] - 当前帧为错误帧 RemoteFlag = 0,//bit[0]-是否是远程帧,bit[6..5]-当前帧通道号,bit[7]-发送帧标志 ID = Convert.ToUInt32(GlobalVar.agreementMsgVM.SendAdditionalRules.AdditionalSendId, 16),//报文ID DataLen = 8,//数据长度(<=8),即Data中有效数据长度 Data = ByteArrayLib.GetByteArrayFromHexString(GlobalVar.agreementMsgVM.SendAdditionalRules.AdditionalContent) }; int SendedNum = USB2CAN.CAN_SendMsg(DevHandle, WriteCANIndex, additionalCanMsg, (UInt32)additionalCanMsg.Length); if (SendedNum >= 0) { SendMsgNum += SendedNum; Console.WriteLine("Success send additional frames:{0}", SendMsgNum); } else { Console.WriteLine("Send CAN additional data failed!"); break; } } Thread.Sleep(GlobalVar.agreementMsgVM.SendAdditionalRules.AdditionalPeriod); } } /// /// 接收CAN数据 /// public static void ReadCanMsgThread() { while (true) { if (!GlobalVar.CAN_ReadMsgFlag) { Thread.Sleep(10); continue; } USB2CAN.CAN_MSG[] CanMsgBuffer = new USB2CAN.CAN_MSG[1024]; //申请数据缓冲区 IntPtr pt = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(USB2CAN.CAN_MSG)) * CanMsgBuffer.Length); int CanNum = USB2CAN.CAN_GetMsgWithSize(DevHandle, ReadCANIndex, pt, CanMsgBuffer.Length); if (CanNum > 0) { for (int i = 0; i < CanNum; i++) { //从缓冲区中获取数据 CanMsgBuffer[i] = (USB2CAN.CAN_MSG)Marshal.PtrToStructure((IntPtr)((UInt32)pt + i * Marshal.SizeOf(typeof(USB2CAN.CAN_MSG))), typeof(USB2CAN.CAN_MSG)); //判断获取的是不是目标报文 if (CanMsgBuffer[i].ID == Convert.ToUInt32(GlobalVar.agreementMsgVM.ReciveId, 16) && CanMsgBuffer[i].DataLen == 8) { //如果信号值不为空,要过滤信号值 if (!string.IsNullOrEmpty(GlobalVar.agreementMsgVM.ReciveSignalVal)) { Console.WriteLine("接收目标报文"); if (Convert.ToUInt32(GlobalVar.agreementMsgVM.ReciveSignalVal, 16) == CanMsgBuffer[i].Data[0]) { //记录日志 //LogHelper.Error(null,$"CanMsgBuffer[{i}].ID={CanMsgBuffer[i].ID};CanMsgBuffer[{i}].Data=" + StringLib.GetHexStringFromByteArray(CanMsgBuffer[i].Data)); GetCANReciveValHelper.GetReciveVal(CanMsgBuffer[i].Data);//从接收报文中解析实际值 } } else { GetCANReciveValHelper.GetReciveVal(CanMsgBuffer[i].Data);//从接收报文中解析实际值 } } } } else if (CanNum < 0) { Console.WriteLine("Get CAN data error!"); LogHelper.Error(null, "Get CAN data error!"); break; } //释放数据缓冲区,必须释放,否则程序运行一段时间后会报内存不足 Marshal.FreeHGlobal(pt); //Thread.Sleep(GlobalVar.agreementMsgVM.RecivePeriod); Thread.Sleep(50); } } /// /// 获取CAN总状态 /// private static void GetCanStatus() { USB2CAN.CAN_STATUS CANStatus = new USB2CAN.CAN_STATUS(); ret = USB2CAN.CAN_GetStatus(DevHandle, WriteCANIndex, ref CANStatus); if (ret == USB2CAN.CAN_SUCCESS) { Console.WriteLine("TSR = {0:X8}", CANStatus.TSR); Console.WriteLine("ESR = {0:X8}", CANStatus.ESR); Console.WriteLine("CAN控制器接收错误计数 = {0}", CANStatus.RECounter); Console.WriteLine("CAN控制器发送错误计数 = {0}", CANStatus.TECounter); Console.WriteLine("最后的错误代码 = {0}", CANStatus.LECode); } else { Console.WriteLine("Get CAN status error!\n"); } } } }