using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; /*------------兼容ZLG的数据类型---------------------------------*/ //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 = 4)] 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];//保留位 } //3.定义初始化CAN的数据类型 public struct VCI_INIT_CONFIG { public UInt32 AccCode; public UInt32 AccMask; public UInt32 Reserved; public byte Filter; //0或1接收所有帧。2标准帧滤波,3是扩展帧滤波。 public byte Timing0; //波特率参数,具体配置,请查看二次开发库函数说明书。 public byte Timing1; public byte Mode; //模式,0表示正常模式,1表示只听模式,2自测模式 } /*------------其他数据结构描述---------------------------------*/ //4.USB-CAN总线适配器板卡信息的数据类型1,该类型为VCI_FindUsbDevice函数的返回参数。 public struct VCI_BOARD_INFO1 { public UInt16 hw_Version; public UInt16 fw_Version; public UInt16 dr_Version; public UInt16 in_Version; public UInt16 irq_Num; public byte can_Num; public byte Reserved; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] str_Serial_Num; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] str_hw_Type; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] str_Usb_Serial; } public struct CHGDESIPANDPORT { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] public byte[] szpwd; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] public byte[] szdesip; public Int32 desport; public void Init() { szpwd = new byte[10]; szdesip = new byte[20]; } } public unsafe struct UdsAppMsgInfo { public UInt32 xUdsId; public UInt32 xDataLen; public byte xUdsRequest; public fixed byte aDataBuf[150]; } public unsafe struct UdsAppResponseInfo { public bool isPositiveResponse; public byte responseDataLength; public fixed byte responseData[100]; } public struct UdsDID { public byte DID_High; public byte DID_Low; } public struct UdsDIDList { public UdsDID fingerPrint; public UdsDID eraseFlash; public UdsDID checkProgramIndependence; public UdsDID checkCRCofBlock; } public struct FileDownloadDataType { public bool isDownloadFlag; public UInt32 memoryStartAddr; public UInt32 memorySize; public UInt16 fileBlockCRC16; public byte[] fileDownloadDataBuff; } namespace WindowsFormsApplication1 { public partial class Form1 : Form { const int DEV_USBCAN = 3; const int DEV_USBCAN2 = 4; UInt32 receCount = new UInt32(); /// /// /// /// /// /// /// /*------------兼容ZLG的函数描述---------------------------------*/ [DllImport("controlcan.dll")] static extern UInt32 VCI_OpenDevice(UInt32 DeviceType, UInt32 DeviceInd, UInt32 Reserved); [DllImport("controlcan.dll")] static extern UInt32 VCI_CloseDevice(UInt32 DeviceType, UInt32 DeviceInd); [DllImport("controlcan.dll")] static extern UInt32 VCI_InitCAN(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_INIT_CONFIG pInitConfig); [DllImport("controlcan.dll")] static extern UInt32 VCI_ReadBoardInfo(UInt32 DeviceType, UInt32 DeviceInd, ref VCI_BOARD_INFO pInfo); [DllImport("controlcan.dll")] static extern UInt32 VCI_GetReceiveNum(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd); [DllImport("controlcan.dll")] static extern UInt32 VCI_ClearBuffer(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd); [DllImport("controlcan.dll")] static extern UInt32 VCI_StartCAN(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd); [DllImport("controlcan.dll")] static extern UInt32 VCI_ResetCAN(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd); [DllImport("controlcan.dll")] static extern UInt32 VCI_Transmit(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_CAN_OBJ pSend, UInt32 Len); [DllImport("controlcan.dll")] static extern UInt32 VCI_Receive(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_CAN_OBJ pReceive, UInt32 Len, Int32 WaitTime); /*------------其他函数描述---------------------------------*/ [DllImport("controlcan.dll")] static extern UInt32 VCI_ConnectDevice(UInt32 DevType, UInt32 DevIndex); [DllImport("controlcan.dll")] static extern UInt32 VCI_UsbDeviceReset(UInt32 DevType, UInt32 DevIndex, UInt32 Reserved); [DllImport("controlcan.dll")] static extern UInt32 VCI_FindUsbDevice(ref VCI_BOARD_INFO1 pInfo); private delegate void CrossThreadOperationControl(); /*------------函数描述结束---------------------------------*/ /*------------全局变量声明---------------------------------*/ //private float X;//当前窗体的宽度 //private float Y;//当前窗体的高度 //private bool IsFirst = true; bool isForm1Colsed = false; byte controllerChooseFlag = 0xFF; static UInt32 m_devtype = 4;//USBCAN2 UInt32 m_devind = 0; UInt32 m_canind = 0; UInt32[] m_arrdevtype = new UInt32[20]; bool UpdateServiceSwitch = false; VCI_CAN_OBJ[] receobj = new VCI_CAN_OBJ[20]; bool buttStartCan = false; bool buttStartDownload = false; public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { } private void Form1_Load(object sender, EventArgs e) { Int32 curindex = 0; comboBox_devtype.Items.Clear(); curindex = comboBox_devtype.Items.Add("DEV_USBCAN"); m_arrdevtype[curindex] = DEV_USBCAN; //comboBox_devtype.Items[2] = "VCI_USBCAN1"; //m_arrdevtype[2]= VCI_USBCAN1 ; curindex = comboBox_devtype.Items.Add("DEV_USBCAN2"); m_arrdevtype[curindex] = DEV_USBCAN2; //comboBox_devtype.Items[3] = "VCI_USBCAN2"; //m_arrdevtype[3]= VCI_USBCAN2 ; comboBox_BoardIndex.SelectedIndex = 0; comboBox_CANIndex.SelectedIndex = 0; comboBox_DeviceIndex.SelectedIndex = 0; comboBox_CANIndex.SelectedIndex = 0; comboBox_MsgType.SelectedIndex = 0; comboBox_VCU_BMSHVOnOffReq.SelectedIndex = 0; comboBox_VCU_AllowChgCtrl.SelectedIndex = 0; comboBox_VCU_BMSCutOffLV.SelectedIndex = 0; comboBox_LockingPinStsFB.SelectedIndex = 0; comboBox_Change_BattConSts.SelectedIndex = 0; comboBox_BTMS_WorkSts.SelectedIndex = 0; comboBox_BTMS_ConnStsFb.SelectedIndex = 0; comboBox_BTMS_FltLevel.SelectedIndex = 0; comboBox_encryptionEnable.SelectedIndex = 0; //comboBox_ControllerChoose.SelectedIndex = 0x00; //comboBox_MsgType.SelectedIndex = 0x01; //canMsgType = (byte)(comboBox_MsgType.SelectedIndex); //controllerChooseFlag = (byte)(comboBox_ControllerChoose.SelectedIndex + 1); // TextBox[] test = new TextBox[10]; for (int i = 0; i < 10; i++) { //test.Size = new System.Drawing.Size(400, 300); test[i] = new TextBox(); test[i].Text = "标题" + i.ToString();//设置文本,i的值转成字符串与标题相加 test[i].Parent = flowLayoutPanel_1; } comboBox_devtype.SelectedIndex = 1; comboBox_devtype.MaxDropDownItems = comboBox_devtype.Items.Count; setBoxAndButtonEnalbe(true); isForm1Colsed = false; } private void setBoxAndButtonEnalbe(bool trueOrfalse) { comboBox_CANIndex.Enabled = trueOrfalse; comboBox_devtype.Enabled = trueOrfalse; comboBox_BoardIndex.Enabled = trueOrfalse; comboBox_DeviceIndex.Enabled = trueOrfalse; } private void Form1_FormClosed(object sender, FormClosedEventArgs e) { if (buttStartCan == true) { //VCI_CloseDevice(m_devtype, m_devind); } //autoSaveFile(); //UpdateStep = 0xFF; isForm1Colsed = true; //setBoxAndButtonEnalbe(false); } private void button_StartCAN_Click(object sender, EventArgs e) { if (buttStartCan == true) { buttStartCan = false; } else { m_devtype = m_arrdevtype[comboBox_devtype.SelectedIndex]; m_devind = 0; m_canind = (UInt32)comboBox_CANIndex.SelectedIndex; m_devind = (UInt32)comboBox_DeviceIndex.SelectedIndex; if (VCI_OpenDevice(m_devtype, m_devind, 0) == 0) { MessageBox.Show("打开设备失败,请检查设备类型和设备索引号是否正确", "错误", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; } buttStartCan = true; VCI_INIT_CONFIG config = new VCI_INIT_CONFIG(); if (comboBox_MsgType.Text == "标准帧") { config.AccCode = 0; config.AccMask = 0xffffffff; //config.AccCode = Convert.ToUInt32(textBox_responseAddr.Text, 16) << 21; //config.AccMask = 0x1FFFFF; config.Filter = 0x02;//只接收符合要求的标准帧 //0或1接收所有帧。2标准帧滤波,3是扩展帧滤波。 } else if (comboBox_MsgType.Text == "扩展帧") { config.AccCode = 0; config.AccMask = 0xffffffff; //config.AccCode = Convert.ToUInt32(textBox_responseAddr.Text, 16) << 3; //config.AccMask = 0x07; config.Filter = 0x03;//只接收符合要求的扩展帧 } //波特率设置为250K switch (comboBox_BoardIndex.Text) { case "250K": config.Timing0 = 0x01; config.Timing1 = 0x1C; break; case "500K": config.Timing0 = 0x00; config.Timing1 = 0x1C; break; default: //250K config.Timing0 = 0x01; config.Timing1 = 0x1C; break; } //config.Filter = 0x00;//接收所有报文 config.Mode = (Byte)0x00; //正常工作模式 VCI_InitCAN(m_devtype, m_devind, m_canind, ref config); } button_StartCAN.Text = buttStartCan == true ? "停止CAN" : "启动CAN"; button_StartCAN.BackColor = buttStartCan == true ? Color.GreenYellow : SystemColors.Control; if (buttStartCan == false) { VCI_ResetCAN(m_devtype, m_devind, m_canind); comboBox_devtype.Enabled = true; comboBox_CANIndex.Enabled = true; comboBox_DeviceIndex.Enabled = true; comboBox_BoardIndex.Enabled = true; comboBox_MsgType.Enabled = true; timer_rec.Enabled = false; timer_send.Enabled = false; //comboBox_ControllerChoose.Enabled = true; return; } VCI_StartCAN(m_devtype, m_devind, m_canind); comboBox_devtype.Enabled = false; comboBox_CANIndex.Enabled = false; comboBox_DeviceIndex.Enabled = false; comboBox_BoardIndex.Enabled = false; comboBox_MsgType.Enabled = false; timer_rec.Interval = 10; timer_send.Interval = 100; timer_rec.Enabled = true; timer_send.Enabled = true; //comboBox_ControllerChoose.Enabled = false; } private void timer_rec_Tick(object sender, EventArgs e) { if (receCount == 0) { uint res = VCI_GetReceiveNum(m_devtype, m_devind, m_canind); if (res > 0) { receobj = new VCI_CAN_OBJ[20]; receCount = 0; receCount = VCI_Receive(m_devtype, m_devind, m_canind, ref receobj[0], 15, 0); if (receCount == 0xFFFFFFFF) { receCount = 0; } for (int i = 0; i < receCount; i++) { //strCanMsg += CANMsgRecord(receobj[i], "rx"); byte[] tmp = new byte[8]; CANRec(receobj[i].ID, receobj[i]); } receCount = 0; } else { } } } private void timer_send_Tick(object sender, EventArgs e) { VCI_CAN_OBJ sendObj = new VCI_CAN_OBJ(); CANTx(0x1802F3D0, sendObj); CANTx(0x18F5C13A, sendObj); CANTx(0x18FF42D8, sendObj); CANTx(0x18FFCBF3, sendObj); CANTx(0x18FFF8A7, sendObj); } void CANTx(UInt32 ID, VCI_CAN_OBJ sendObj) { sendObj.ID = ID; sendObj.ExternFlag = 0X01; sendObj.DataLen = 0x08; unsafe { for (int i = 0; i < 8; i++) { sendObj.Data[i] = 0; } switch (ID) { //vcu case 0x1802F3D0: int VCU_V2B_CMD_Checksum = 0; int VCU_BMSHVOnOffReq = 0; int VCU_VehSpd = 0; int VCU_BMSCutOffLV = 0; int VCU_AllowChgCtrl = 0; if (VCU_V2B_CMD_AliveConter++ > 15) VCU_V2B_CMD_AliveConter = 0; VCU_BMSHVOnOffReq = comboBox_VCU_BMSHVOnOffReq.SelectedIndex; sendObj.Data[1] = (byte)((((VCU_V2B_CMD_AliveConter >> 0) & 0xF) << 0) | (((VCU_BMSHVOnOffReq >> 0) & 0x3) << 4)); VCU_VehSpd = Convert.ToInt32(numericUpDown_VCU_VehSpd.Value); sendObj.Data[2] = (byte)(((VCU_VehSpd >> 0) & 0xFF) << 0); VCU_AllowChgCtrl = comboBox_VCU_AllowChgCtrl.SelectedIndex; VCU_BMSCutOffLV = comboBox_VCU_BMSCutOffLV.SelectedIndex; sendObj.Data[7] = (byte)((((VCU_BMSCutOffLV >> 0) & 0x1) << 0) | ((VCU_AllowChgCtrl >> 0) & 0x3) << 1); for (int i = 1; i < 8; i++) { VCU_V2B_CMD_Checksum ^= sendObj.Data[1]; } sendObj.Data[0] = (byte)(((VCU_V2B_CMD_Checksum >> 0) & 0xFF) << 0); break; //tms case 0x18F5C13A: int BTMS_WorkSts = 0; int BTMS_ConnStsFb = 0; int BTMS_BattPackInCoolTemp = 0; int BTMS_BattPackoutCoolTemp = 0; int BTMS_ActPower = 0; int BTMS_DTC = 0; int BTMS_FltLevel = 0; BTMS_WorkSts = comboBox_BTMS_WorkSts.SelectedIndex; BTMS_ConnStsFb = comboBox_BTMS_ConnStsFb.SelectedIndex; BTMS_BattPackInCoolTemp = Convert.ToByte(numericUpDown_BTMS_BattPackInCoolTemp.Value + 40); BTMS_BattPackoutCoolTemp = Convert.ToByte(numericUpDown_BTMS_BattPackoutCoolTemp.Value + 40); BTMS_ActPower = Convert.ToInt32(numericUpDown_BTMS_ActPower.Value * 10); BTMS_DTC = Convert.ToByte(numericUpDown_BTMS_DTC.Value); BTMS_FltLevel = comboBox_BTMS_FltLevel.SelectedIndex; sendObj.Data[0] = (byte)((((BTMS_WorkSts >> 0) & 0x3) << 0) | (((BTMS_ConnStsFb >> 0) & 0xF) << 2)); sendObj.Data[1] = (byte)(((BTMS_BattPackInCoolTemp >> 0) & 0xFF) << 0); sendObj.Data[2] = (byte)(((BTMS_BattPackoutCoolTemp >> 0) & 0xFF) << 0); sendObj.Data[5] = (byte)(((BTMS_ActPower >> 0) & 0xFF) << 0); sendObj.Data[6] = (byte)(((BTMS_ActPower >> 8) & 0xFF) << 0); sendObj.Data[7] = (byte)((((BTMS_DTC >> 0) & 0x3F) << 0) | (((BTMS_FltLevel >> 0) & 0x3) << 6)); break; case 0x18FF42D8: /* sendObj.Data[0] = (byte)(((TBOX_Second >> 0) & 0xFF) << 0); sendObj.Data[1] = (byte)(((TBOX_Minute >> 0) & 0xFF) << 0); sendObj.Data[2] = (byte)(((TBOX_Hour >> 0) & 0xFF) << 0); sendObj.Data[3] = (byte)(((TBOX_Day >> 0) & 0xFF) << 0); sendObj.Data[4] = (byte)(((TBOX_Month >> 0) & 0xFF) << 0); sendObj.Data[5] = (byte)(((TBOX_Year >> 0) & 0xFF) << 0);*/ break; //rcb case 0x18FFCBF3: int RCB_encryp1 = 0; int RCB_encryp2 = 0; int RCB_encryp3 = 0; int RCB_encryp4 = 0; sendObj.Data[0] = (byte)(((RCB_encryp1 >> 0) & 0xFF) << 0); sendObj.Data[1] = (byte)(((RCB_encryp1 >> 8) & 0xFF) << 0); sendObj.Data[2] = (byte)(((RCB_encryp2 >> 0) & 0xFF) << 0); sendObj.Data[3] = (byte)(((RCB_encryp2 >> 8) & 0xFF) << 0); sendObj.Data[4] = (byte)(((RCB_encryp3 >> 0) & 0xFF) << 0); sendObj.Data[5] = (byte)(((RCB_encryp3 >> 8) & 0xFF) << 0); sendObj.Data[6] = (byte)(((RCB_encryp4 >> 0) & 0xFF) << 0); sendObj.Data[7] = (byte)(((RCB_encryp4 >> 8) & 0xFF) << 0); break; //EBC case 0x18FFF8A7: int LockingPinStsFB = 0; int Change_BattConSts = 0; int Message_Checksum = 0; if (Message_Counter++ > 15) Message_Counter = 0; Message_Checksum = Message_Counter; LockingPinStsFB = comboBox_LockingPinStsFB.SelectedIndex = 0; Change_BattConSts = comboBox_Change_BattConSts.SelectedIndex; sendObj.Data[1] = (byte)((((LockingPinStsFB >> 0) & 0x3) << 0) | (((Change_BattConSts >> 0) & 0x3) << 2)); sendObj.Data[7] = (byte)((((Message_Counter >> 0) & 0xF) << 0) | (((Message_Checksum >> 0) & 0xF) << 4)); break; default: break; } VCI_Transmit(m_devtype, m_devind, m_canind, ref sendObj, 1); } } void CANRec(UInt32 ID, VCI_CAN_OBJ sendObj) { unsafe { switch (ID) { case 0x1801D0F3: string[] strs_BMS_CutOffHVReq = { "0:预留 ","请求下高压","不请求下高压","无效 "}; int BMS_CutOffHVReq = (byte)((((sendObj.Data[0] >> 2) & 0x3) << 0)); //是否请求下高压 BMS_CutOffHVReq = BMS_CutOffHVReq > strs_BMS_CutOffHVReq.Length ? BMS_CutOffHVReq : strs_BMS_CutOffHVReq.Length - 1; textBox_BMS_CutOffHVReq.Text = strs_BMS_CutOffHVReq[BMS_CutOffHVReq]; //int BMS_PmtCutoffLVFb = (byte)((((sendObj.Data[0]>>4)&0x3)<<0)); //BMS允许下低压 //int BMS_EmergCutoffHVReq = (byte)((((sendObj.Data[0]>>6)&0x3)<<0)); //BMS紧急下高压请求 //int BMS_HeatNegRelaySts = (byte)((((sendObj.Data[1]>>0)&0x3)<<0)); //加热负继电器状态 // int BMS_HeatPosRelaySts = (byte)((((sendObj.Data[1]>>2)&0x3)<<0)); //加热正继电器状态 //int BMS_SelfChkSts = (byte)((((sendObj.Data[1]>>4)&0x3)<<0)); //BMS自检状态 break; case 0x1880D0F3: /* int BMS_BattSysNum = (byte)((((sendObj.Data[0]>>0)&0xF)<<0)); //可充电装置系统序号 int BMS_MainPosRelayWeldedFlt = (byte)((((sendObj.Data[0]>>4)&0x1)<<0)); //主正继电器粘连故障 int BMS_MainNegRelayWeldedFlt = (byte)((((sendObj.Data[0]>>5)&0x1)<<0)); //主负继电器粘连故障 int BMS_ChgPosWeldedFlt1 = (byte)((((sendObj.Data[0]>>6)&0x1)<<0)); //充电正1继电器粘连故障 int BMS_ChgNegWeldedFlt1 = (byte)((((sendObj.Data[0]>>7)&0x1)<<0)); //充电负1继电器粘连故障 int BMS_ChgPosWeldedFlt2 = (byte)((((sendObj.Data[1]>>0)&0x1)<<0)); //充电正2继电器粘连故障 int BMS_ChgNegWeldedFlt2 = (byte)((((sendObj.Data[1]>>1)&0x1)<<0)); //充电负2继电器粘连故障 int BMS_HeatNegWeldedFlt = (byte)((((sendObj.Data[1]>>2)&0x1)<<0)); //加热负继电器粘连故障 int BMS_HeatPosWeldedFlt1 = (byte)((((sendObj.Data[1]>>3)&0x1)<<0)); //加热正继电器粘连故障 */ string[] BMS_ConnSts = { "预留" , "开启" ,"闭合" , "无效" }; int BMS_MainPosConnSts = (byte)((((sendObj.Data[1] >> 4) & 0x3) << 0)); //主正继电器状态反馈 int BMS_MainNegConnSts = (byte)((((sendObj.Data[1] >> 6) & 0x3) << 0)); //主ds负继电器状态反馈 int BMS_PreChgConnSts = (byte)((((sendObj.Data[2] >> 0) & 0x3) << 0)); //预充继电器状态反馈 int BMS_ChgPosConnSts1 = (byte)((((sendObj.Data[2] >> 2) & 0x3) << 0)); //充电正1继电器状态 int BMS_ChgNegConnSts1 = (byte)((((sendObj.Data[2] >> 4) & 0x3) << 0)); //充电负1继电器状态 int BMS_ChgPosConnSts2 = (byte)((((sendObj.Data[2] >> 6) & 0x3) << 0)); //充电正2继电器状态 int BMS_ChgNegConnSts2 = (byte)((((sendObj.Data[3] >> 0) & 0x3) << 0)); //充电负2继电器状态 BMS_MainPosConnSts = BMS_MainPosConnSts > BMS_ConnSts.Length ? BMS_MainPosConnSts : BMS_ConnSts.Length - 1; BMS_MainNegConnSts = BMS_MainNegConnSts > BMS_ConnSts.Length ? BMS_MainNegConnSts : BMS_ConnSts.Length - 1; BMS_ChgPosConnSts1 = BMS_ChgPosConnSts1 > BMS_ConnSts.Length ? BMS_ChgPosConnSts1 : BMS_ConnSts.Length - 1; BMS_PreChgConnSts = BMS_PreChgConnSts > BMS_ConnSts.Length ? BMS_PreChgConnSts : BMS_ConnSts.Length - 1; BMS_ChgNegConnSts1 = BMS_ChgNegConnSts1 > BMS_ConnSts.Length ? BMS_ChgNegConnSts1 : BMS_ConnSts.Length - 1; BMS_ChgPosConnSts2 = BMS_ChgPosConnSts2 > BMS_ConnSts.Length ? BMS_ChgPosConnSts2 : BMS_ConnSts.Length - 1; BMS_ChgNegConnSts2 = BMS_ChgNegConnSts2 > BMS_ConnSts.Length ? BMS_ChgNegConnSts2 : BMS_ConnSts.Length - 1; textBox_BMS_MainPosConnSts.Text = BMS_ConnSts[BMS_MainPosConnSts]; textBox_BMS_MainNegConnSts.Text = BMS_ConnSts[BMS_MainNegConnSts]; textBox_BMS_PreChgConnSts.Text = BMS_ConnSts[BMS_PreChgConnSts]; textBox_BMS_ChgPosConnSts1.Text = BMS_ConnSts[BMS_ChgPosConnSts1]; textBox_BMS_ChgNegConnSts1.Text = BMS_ConnSts[BMS_ChgNegConnSts1]; textBox_BMS_ChgPosConnSts2.Text = BMS_ConnSts[BMS_ChgPosConnSts2]; textBox_BMS_ChgNegConnSts2.Text = BMS_ConnSts[BMS_ChgNegConnSts2]; int BMS_ErrorCode = (byte)((((sendObj.Data[7] >> 0) & 0xFF) << 0)); //电池系统故障码 textBox_BMS_ErrorCode.Text = BMS_ErrorCode.ToString(); /* int BMS_BranchCircuitFlt = (byte)((((sendObj.Data[3]>>3)&0x1)<<0)); //支路断路故障 int BMS_ChgCircuitOverLimtFlt = (byte)((((sendObj.Data[3]>>4)&0x3)<<0)); //回充电流超限故障 int BMS_MainPosNotConnFlt = (byte)((((sendObj.Data[3]>>6)&0x1)<<0)); //主正继电器无法闭合报警 int BMS_MainNegNotConnFlt = (byte)((((sendObj.Data[3]>>7)&0x1)<<0)); //主负继电器无法闭合报警 int BMS_ChgPosNotConnFlt1 = (byte)((((sendObj.Data[4]>>0)&0x1)<<0)); //充电正1继电器无法闭合报警 int BMS_ChgPosNotConnFlt2 = (byte)((((sendObj.Data[4]>>1)&0x1)<<0)); //充电正2继电器无法闭合报警 int BMS_ChgNegNotConnFlt1 = (byte)((((sendObj.Data[4]>>2)&0x1)<<0)); //充电负1继电器无法闭合报警 int BMS_ChgNegNotConnFlt2 = (byte)((((sendObj.Data[4]>>3)&0x1)<<0)); //充电负2继电器无法闭合报警 int BMS_HeatBTMSConnNotOpenFlt = (byte)((((sendObj.Data[4]>>4)&0x1)<<0)); //加热膜或BTMS继电器无法断开故障 int BMS_HeatBTMSNotConnFlt = (byte)((((sendObj.Data[4]>>5)&0x1)<<0)); //加热膜或 BTMS 继电器无法闭合故障 int BMS_HeatMgSysFlt = (byte)((((sendObj.Data[4]>>6)&0x1)<<0)); //热管理系统故障 int BMS_SupBattFlt = (byte)((((sendObj.Data[4]>>7)&0x1)<<0)); //BMS 24V供电异常报警 int BMS_BattSelfProtAlm = (byte)((((sendObj.Data[5]>>0)&0x1)<<0)); //电池包自保护报警 int BMS_PreChgRelayWeldedFlt = (byte)((((sendObj.Data[5]>>3)&0x1)<<0)); //预充继电器粘连故障 int BMS_PreChgNotConnFlt = (byte)((((sendObj.Data[5]>>4)&0x1)<<0)); //预充继电器无法闭合报警 int BMS_HeatPosNotConnFlt1 = (byte)((((sendObj.Data[5]>>5)&0x1)<<0)); //加热正继电器无法闭合故障 int BMS_HeatNegNotConnFlt = (byte)((((sendObj.Data[5]>>6)&0x1)<<0)); //加热负继电器无法闭合故障 int BMS_SysNum = (byte)((((sendObj.Data[6]>>0)&0xF)<<0)); //可充电储能子系统总数 */ break; case 0x1881D0F3: string[] strs_BMS_FaultLevel = { "无故障", "1级故障", "2级故障", "3级故障" }; string[] sts_BMS_BattCurrentSts = { "高压开启", "预先充电", "高压关断", "高压上电故障" }; int BMS_FaultLevel = (byte)((((sendObj.Data[2] >> 5) & 0x3) << 0)); //最高报警等级 int BMS_GBT32960FltNum = (byte)((((sendObj.Data[7] >> 3) & 0x1F) << 0)); //故障数目 int BMS_BattCurrentSts = (byte)((((sendObj.Data[1] >> 4) & 0x3) << 0)); //BMS当前工作状态 BMS_FaultLevel = BMS_FaultLevel > strs_BMS_FaultLevel.Length ? BMS_BattCurrentSts : strs_BMS_FaultLevel.Length - 1; textBox_BMS_FaultLevel.Text = strs_BMS_FaultLevel[BMS_FaultLevel]; textBox_BMS_GBT32960FltNum.Text = textBox_BMS_GBT32960FltNum.ToString(); BMS_BattCurrentSts = BMS_BattCurrentSts > sts_BMS_BattCurrentSts.Length ? BMS_BattCurrentSts : sts_BMS_BattCurrentSts.Length - 1; textBox_BMS_BattCurrentSts.Text = sts_BMS_BattCurrentSts[BMS_BattCurrentSts]; /* int BMS_B2V_ST1Checksum = (byte)((((sendObj.Data[0]>>0)&0xFF)<<0)); //校验 int BMS_B2V_ST2AliveCounter = (byte)((((sendObj.Data[1]>>0)&0xF)<<0)); //计数 int BMS_AssisConnSts = (byte)((((sendObj.Data[1]>>6)&0x1)<<0)); //附件继电器状态 int BMS_BattEqualizationSts = (byte)((((sendObj.Data[1]>>7)&0x1)<<0)); //BMS当前均衡状态 int BMS_CellTempDiffFault = (byte)((((sendObj.Data[3]>>0)&0x3)<<0)); //电芯温差异常报警 int BMS_BattTempHighFault = (byte)((((sendObj.Data[3]>>2)&0x3)<<0)); //电芯温度过高报警 int BMS_BattPackVolHighFault = (byte)((((sendObj.Data[3]>>4)&0x3)<<0)); //PACK过压报警 int BMS_BattPackVolLowFault = (byte)((((sendObj.Data[3]>>6)&0x3)<<0)); //PACK欠压报警 int BMS_BattSOCLowFault = (byte)((((sendObj.Data[4]>>0)&0x3)<<0)); //SOC过低报警 int BMS_BattCellVolHighFault = (byte)((((sendObj.Data[4]>>2)&0x3)<<0)); //单体电压过高报警 int BMS_BattCellVolLowFault = (byte)((((sendObj.Data[4]>>4)&0x3)<<0)); //单体电压欠压报警 int BMS_BattIsolationFault = (byte)((((sendObj.Data[4]>>6)&0x3)<<0)); //绝缘报警 int BMS_CellVolDiffFault = (byte)((((sendObj.Data[5]>>0)&0x3)<<0)); //单体压差过大 int BMS_ChgCurrHighFlt = (byte)((((sendObj.Data[5]>>2)&0x3)<<0)); //充电电流过大报警 int BMS_DisChgCurrHighFlt = (byte)((((sendObj.Data[5]>>4)&0x3)<<0)); //放电电流过大报警 int BMS_BattTempLowFault = (byte)((((sendObj.Data[5]>>6)&0x3)<<0)); //电芯温度过低报警 int BMS_BranchCircuitDiffFault = (byte)((((sendObj.Data[6]>>0)&0x3)<<0)); //支路压差过大报警 int BMS_ST1_Flt_HW = (byte)((((sendObj.Data[6]>>2)&0x3)<<0)); //BMS 硬件故障 int BMS_BattSOCHighFault = (byte)((((sendObj.Data[6]>>4)&0x1)<<0)); //SOC过高报警 int BMS_SOCJumpFault = (byte)((((sendObj.Data[6]>>5)&0x1)<<0)); //SOC跳变报警 int BMS_CANComFault = (byte)((((sendObj.Data[6]>>6)&0x1)<<0)); //BMS内部通讯故障 int BMS_BattPackMatchFault = (byte)((((sendObj.Data[6]>>7)&0x1)<<0)); //BMS系统不匹配报警 int BMS_ST1_Flt_HVIL = (byte)((((sendObj.Data[7]>>0)&0x1)<<0)); //高压互锁报警 int BMS_SmokeAlarm = (byte)((((sendObj.Data[7]>>1)&0x1)<<0)); //烟雾报警 int BMS_FireAlarm = (byte)((((sendObj.Data[7]>>2)&0x1)<<0)); //火灾报警 */ break; case 0x1882D0F3: int BMS_BattSOC = (byte)((((sendObj.Data[0] >> 0) & 0xFF) << 0)); //电池包SOC int BMS_BattSOH = (byte)((((sendObj.Data[1] >> 0) & 0xFF) << 0)); //电池包SOH int BMS_BattCurr = (UInt16)((((sendObj.Data[2] >> 0) & 0xFF) << 0) | (((sendObj.Data[3] >> 0) & 0xFF) << 8)); //动力电池组电流 //int BMS_MaxPmtEnyRecoCurr = (UInt16)((((sendObj.Data[4]>>0)&0xFF)<<0)|(((sendObj.Data[5]>>0)&0xFF)<<8)); //电池包允许最大回充电电流值 (脉冲) int BMS_MaxPmtDischgCurr = (UInt16)((((sendObj.Data[6] >> 0) & 0xFF) << 0) | (((sendObj.Data[7] >> 0) & 0xFF) << 8)); //电池包允许最大放电电流值(脉冲) textBox_BMS_BattSOC.Text = ((BMS_BattSOC + 0.0) * 0.4).ToString("F2"); textBox_BMS_BattSOH.Text = ((BMS_BattSOH + 0.0) * 0.4).ToString("F2"); textBox_BMS_BattCurr.Text = ((BMS_BattCurr + 0.0) * 0.1 - 2000.0).ToString("F2"); textBox_BMS_MaxPmtDischgCurr.Text = ((BMS_BattCurr + 0.0) * 0.1).ToString(); break; case 0x1883D0F3: int BMS_PosIsolationRes = (UInt16)((((sendObj.Data[0] >> 0) & 0xFF) << 0) | (((sendObj.Data[1] >> 0) & 0xFF) << 8)); //电池包正极绝缘值 int BMS_NegIsolationRes = (UInt16)((((sendObj.Data[2] >> 0) & 0xFF) << 0) | (((sendObj.Data[3] >> 0) & 0xFF) << 8)); //电池包负极绝缘值 int BMS_BattTermVolINMainPos = (UInt16)((((sendObj.Data[4] >> 0) & 0xFF) << 0) | (((sendObj.Data[5] >> 0) & 0xFF) << 8)); //主正继电器内侧电池端电压 总压 int BMS_BattBusVolOutMainPos = (UInt16)((((sendObj.Data[6] >> 0) & 0xFF) << 0) | (((sendObj.Data[7] >> 0) & 0xFF) << 8)); //主正继电器外侧母线电压 textBox_BMS_PosIsolationRes.Text = ((BMS_PosIsolationRes)).ToString(); textBox_BMS_NegIsolationRes.Text = ((BMS_NegIsolationRes)).ToString(); textBox_BMS_BattTermVolINMainPos.Text = ((BMS_BattTermVolINMainPos + 0.0) * 0.1).ToString("F2"); textBox_BMS_BattBusVolOutMainPos.Text = ((BMS_BattBusVolOutMainPos + 0.0) * 0.1).ToString("F2"); break; case 0x1884D0F3: int BMS_BattMaxTemp = (byte)((((sendObj.Data[0] >> 0) & 0xFF) << 0)); //电芯温度最大值 int BMS_BattMinTemp = (byte)((((sendObj.Data[1] >> 0) & 0xFF) << 0)); //电芯温度最小值 textBox_BMS_BattMaxTemp.Text = BMS_BattMaxTemp.ToString(); textBox_BMS_BattMinTemp.Text = BMS_BattMinTemp.ToString(); /*int BMS_Cell_Avg_Temp = (byte)((((sendObj.Data[2]>>0)&0xFF)<<0)); //电芯温度平均值 int BMS_MaxTemp1PackNum = (byte)((((sendObj.Data[3]>>0)&0xFF)<<0)); //电芯温度最大值所在CSC编号 int BMS_MaxTemp1SnsNum = (byte)((((sendObj.Data[4]>>0)&0xFF)<<0)); //电芯温度最大值所在CSC内温度探针编号 int BMS_MinTemp1PackNum = (byte)((((sendObj.Data[5]>>0)&0xFF)<<0)); //电芯温度最小值所在CSC内温度探针编号 int BMS_MinTemp1SnsNum = (byte)((((sendObj.Data[6]>>0)&0xFF)<<0)); //电芯温度最小值所在CSC内温度探针编号*/ break; case 0x1885D0F3: int BMS_MaxCellVolt = (UInt16)((((sendObj.Data[0] >> 0) & 0xFF) << 0) | (((sendObj.Data[1] >> 0) & 0xFF) << 8)); //电芯电压值最大值 /*int BMS_MaxCellVoltPackNum = (byte)((((sendObj.Data[2]>>0)&0xFF)<<0)); //电芯电压最大值所在CSC编号 int BMS_MaxCellVoltSnsNum = (byte)((((sendObj.Data[3]>>0)&0xFF)<<0)); //电芯电压最大值所在CSC内单体编号 int BMS_Cell_Avg_Volt = (UInt16)((((sendObj.Data[4]>>0)&0xFF)<<0)|(((sendObj.Data[5]>>0)&0xFF)<<8)); //电芯电压值平均值*/ textBox_BMS_MaxCellVolt.Text = ((BMS_MaxCellVolt + 0.0) * 0.001).ToString("F3"); break; case 0x1886D0F3: int BMS_MinCellVolt = (UInt16)((((sendObj.Data[0] >> 0) & 0xFF) << 0) | (((sendObj.Data[1] >> 0) & 0xFF) << 8)); //电芯电压值最小值 //int BMS_MinCellVoltSnsNum = (byte)((((sendObj.Data[2]>>0)&0xFF)<<0)); //电芯电压最小值所在CSC内单体编号 //int BMS_MinCellVoltPackNum = (byte)((((sendObj.Data[3]>>0)&0xFF)<<0)); //电芯电压最小值所在CSC编号 textBox_BMS_MinCellVolt.Text = ((BMS_MinCellVolt + 0.0) * 0.001).ToString("F3"); break; case 0x1888D0F3: //int BMS_BattTermVolOutMainPos = (UInt16)((((sendObj.Data[0]>>0)&0xFF)<<0)|(((sendObj.Data[1]>>0)&0xFF)<<8)); //主正继电器外侧电池端电压 //int BMS_BattTermVolOutMainNeg = (UInt16)((((sendObj.Data[2]>>0)&0xFF)<<0)|(((sendObj.Data[3]>>0)&0xFF)<<8)); //主负继电器外侧电池端电压 string[] strs_BMS_DCChgPlugSts = { "未连接", "仅充电口A口连接", "仅充电口B口连接", "充电口A口和B充都连接"}; string[] strs_BMS_ChgSts = { "可以充电", "正在充电", "充电结束", "充电故障" }; string[] strs_BMS_CnctSt = { "车", "站" }; string[] strs_BMS_chrgIReq = { "30s", "60s" }; int BMS_DCChgPlugSts = (byte)((((sendObj.Data[4] >> 0) & 0x7) << 0)); //充电枪连接状态 int BMS_ChgSts = (byte)((((sendObj.Data[4] >> 5) & 0x7) << 0)); //充电状态 //int BMS_ChgMode = (byte)((((sendObj.Data[4]>>3)&0x3)<<0)); //充电模式 int BMS_CnctSt = (byte)((((sendObj.Data[5] >> 4) & 0x1) << 0)); //BMS连接状态 //int BMS_BattPulseTime = (byte)((((sendObj.Data[5]>>5)&0x7)<<0)); //脉冲时间 int BMS_chrgIReq = (UInt16)((((sendObj.Data[6] >> 0) & 0xFF) << 0) | (((sendObj.Data[7] >> 0) & 0xFF) << 8)); //充电需求电流 BMS_DCChgPlugSts = BMS_DCChgPlugSts > strs_BMS_DCChgPlugSts.Length ? BMS_DCChgPlugSts : strs_BMS_DCChgPlugSts.Length - 1; textBox_BMS_DCChgPlugSts.Text = strs_BMS_DCChgPlugSts[BMS_DCChgPlugSts]; BMS_ChgSts = BMS_ChgSts > strs_BMS_ChgSts.Length ? BMS_ChgSts : strs_BMS_ChgSts.Length - 1; textBox_BMS_DCChgPlugSts.Text = strs_BMS_ChgSts[BMS_ChgSts]; BMS_CnctSt = BMS_CnctSt > strs_BMS_CnctSt.Length ? BMS_CnctSt : strs_BMS_CnctSt.Length - 1; textBox_BMS_DCChgPlugSts.Text = strs_BMS_CnctSt[BMS_CnctSt]; BMS_chrgIReq = BMS_chrgIReq > strs_BMS_chrgIReq.Length ? BMS_chrgIReq : strs_BMS_chrgIReq.Length - 1; textBox_BMS_chrgIReq.Text = strs_BMS_chrgIReq[BMS_chrgIReq]; break; case 0x18C1D0F3: int BMS_CellVolMsgCode = (byte)((((sendObj.Data[0] >> 0) & 0xFF) << 0)); //帧序号 int BMS_CellVolCSCNum = (byte)((((sendObj.Data[1] >> 0) & 0xFF) << 0)); //CSC 编号 int BMS_CellVolt1 = (UInt16)((((sendObj.Data[2] >> 0) & 0xFF) << 0) | (((sendObj.Data[3] >> 0) & 0xFF) << 8)); //单体电池电压(V1) int BMS_CellVolt2 = (UInt16)((((sendObj.Data[4] >> 0) & 0xFF) << 0) | (((sendObj.Data[5] >> 0) & 0xFF) << 8)); //单体电池电压(V2) int BMS_CellVolt3 = (UInt16)((((sendObj.Data[6] >> 0) & 0xFF) << 0) | (((sendObj.Data[7] >> 0) & 0xFF) << 8)); //单体电池电压(V3) //int BCUCellU[BMS_CellVolMsgCode * 3 - 3]=BMS_CellVolt1*0.001; //int BCUCellU[BMS_CellVolMsgCode * 3 - 2]=BMS_CellVolt2*0.001; //int BCUCellU[BMS_CellVolMsgCode * 3 - 1]=BMS_CellVolt3*0.001; break; case 0x18C2D0F3: int BMS_TempMsgCode = (byte)((((sendObj.Data[0] >> 0) & 0xFF) << 0)); //帧序号 int BMS_CSCNum = (byte)((((sendObj.Data[1] >> 0) & 0xFF) << 0)); //CSC 编号 int BMS_BattTemp1 = (byte)((((sendObj.Data[2] >> 0) & 0xFF) << 0)); //温度探针1对应的温度值 int BMS_BattTemp2 = (byte)((((sendObj.Data[3] >> 0) & 0xFF) << 0)); //温度探针2对应的温度值 int BMS_BattTemp3 = (byte)((((sendObj.Data[4] >> 0) & 0xFF) << 0)); //温度探针3对应的温度值 int BMS_BattTemp4 = (byte)((((sendObj.Data[5] >> 0) & 0xFF) << 0)); //温度探针4对应的温度值 int BMS_BattTemp5 = (byte)((((sendObj.Data[6] >> 0) & 0xFF) << 0)); //温度探针5对应的温度值 int BMS_BattTemp6 = (byte)((((sendObj.Data[7] >> 0) & 0xFF) << 0)); //温度探针6对应的温度值 // int BCUModT[BMS_TempMsgCode * 6 - 6]=BMS_BattTemp1-40; // int BCUModT[BMS_TempMsgCode * 6 - 5]=BMS_BattTemp1-40; // int BCUModT[BMS_TempMsgCode * 6 - 4]=BMS_BattTemp1-40; // int BCUModT[BMS_TempMsgCode * 6 - 3]=BMS_BattTemp1-40; // int BCUModT[BMS_TempMsgCode * 6 - 2]=BMS_BattTemp1-40; // int BCUModT[BMS_TempMsgCode * 6 - 1]=BMS_BattTemp1-40; break; case 0x18F4D0F3: /*int BMS_SingleChgEnergy = (UInt16)((((sendObj.Data[0]>>0)&0xFF)<<0)|(((sendObj.Data[1]>>0)&0xFF)<<8)); //单次充电电量(充电枪插入) int BMS_SingleDisChgEny = (UInt16)((((sendObj.Data[2]>>0)&0xFF)<<0)|(((sendObj.Data[3]>>0)&0xFF)<<8)); //单次放电电量 int BMS_SingleEnergy = (UInt16)((((sendObj.Data[4]>>0)&0xFF)<<0)|(((sendObj.Data[5]>>0)&0xFF)<<8)); //单次充电电量(制动能量回收)*/ break; case 0x18FEF8F3: /*int BMS_ConTempDC1Pos = (byte)((((sendObj.Data[0]>>0)&0xFF)<<0)); //行车换电连接器功率端子DC1+的温度 int BMS_ConTempDC1Neg = (byte)((((sendObj.Data[1]>>0)&0xFF)<<0)); //行车换电连接器功率端子DC1-的温度 int BMS_ConTempDC2Pos = (byte)((((sendObj.Data[2]>>0)&0xFF)<<0)); //行车换电连接器功率端子DC2+的温度 int BMS_ConTempDC2Neg = (byte)((((sendObj.Data[3]>>0)&0xFF)<<0)); //行车换电连接器功率端子DC2-的温度 int BMS_ChgConTempDC1Pos = (byte)((((sendObj.Data[4]>>0)&0xFF)<<0)); //充电换电连接器功率端子DC1+的温度 int BMS_ChgConTempDC1Neg = (byte)((((sendObj.Data[5]>>0)&0xFF)<<0)); //充电换电连接器功率端子DC1-的温度 int BMS_ChgConTempDC2Pos = (byte)((((sendObj.Data[6]>>0)&0xFF)<<0)); //充电换电连接器功率端子DC2+的温度 int BMS_ChgConTempDC2Neg = (byte)((((sendObj.Data[7]>>0)&0xFF)<<0)); //充电换电连接器功率端子DC2-的温度*/ break; case 0x18FFF3CB: int BMS_encryp1 = (byte)((((sendObj.Data[0] >> 0) & 0xFF) << 0)); //BMS认证数据1 int BMS_encryp2 = (byte)((((sendObj.Data[1] >> 0) & 0xFF) << 0)); //BMS认证数据2 int BMS_encryp3 = (byte)((((sendObj.Data[2] >> 0) & 0xFF) << 0)); //BMS认证数据3 int BMS_encryp4 = (byte)((((sendObj.Data[3] >> 0) & 0xFF) << 0)); //BMS认证数据4 break; default: break; } } } int VCU_V2B_CMD_AliveConter = 0; UInt16 encryptionAlgorithm(UInt16 plainText) { UInt16 cipherText = 1; UInt32 privateKeyE = 207521; UInt16 privateKeyN = 54127; plainText = (UInt16)(plainText % privateKeyN); while (privateKeyE > 0) { if (privateKeyE % 2 == 1) { cipherText = (UInt16)((cipherText * plainText) % privateKeyN); } privateKeyE = privateKeyE / 2; plainText = (UInt16)((plainText * plainText) % privateKeyN); } return cipherText; } int Message_Counter = 0; void textChecker(object sender, KeyPressEventArgs e) { //判断输入是否符合规范 if ((!char.IsDigit(e.KeyChar)) && e.KeyChar != 8 && e.KeyChar != (char)('.') && e.KeyChar != (char)('-')) {//允许输入数字、退格符、小数点、删除键和负号 MessageBox.Show("请输入正确的数字"); e.Handled = true; } if (e.KeyChar == (char)('-')) { if (Form.ActiveForm.ActiveControl.Text != "") {//这里的txt1需要改成应用处的TextBox的名称,或者可以给这个函数多传递一个参数,再在此处添加一个switch来判断 MessageBox.Show("负号位置错误"); e.Handled = true; } } if (e.KeyChar == (char)('.') && ((TextBox)sender).Text == "") { MessageBox.Show("第一位不能为小数点"); e.Handled = true; } if (e.KeyChar == (char)('.') && ((TextBox)sender).Text.IndexOf('.') != -1) { MessageBox.Show("小数点只能输入一次"); e.Handled = true; } if (e.KeyChar != (char)('.') && ((TextBox)sender).Text == "0" && (e.KeyChar != 8)) {//这里要注意退格符是可以输入的 MessageBox.Show("第一位是0,第二位必须为小数点"); e.Handled = true; } if (((TextBox)sender).Text == "-" && e.KeyChar == (char)('.')) { MessageBox.Show("第一位是负号,第二位不能为小数点 "); e.Handled = true; } } } }