Parcourir la source

2.3.0.32 1.新增加热和继电器强制控制指令,2.新增模组平均温度计算,3.新增永久故障存储,4.新增can设置出厂模式,5.修改数据发送频率,静置时为1min1次,6.新增SOC大于90以上不睡眠

CHENJIE-PC\QiXiang_CHENJIE il y a 3 ans
Parent
commit
02ae9f06c5
8 fichiers modifiés avec 140 ajouts et 71 suppressions
  1. 2 0
      inc/Signal.h
  2. 2 1
      inc/app.h
  3. 25 0
      src/CANTask.c
  4. 25 2
      src/MainTask.c
  5. 2 0
      src/Signal.c
  6. 5 5
      src/TcpTask.c
  7. 5 0
      src/UDSService.c
  8. 74 63
      src/UartTask.c

+ 2 - 0
inc/Signal.h

@@ -28,6 +28,8 @@ extern  UINT8	VibrationStatus;
 extern  UINT8   RxInterprut;
 extern  UINT8   chargerConnectState;
 extern  UINT8   BattWorkStateDelay;
+extern  UINT8   HeatForceControl;
+extern  UINT8   AvgBattTemp;
 //declear the UINT16 vars
 extern	UINT16	battCellU[28];
 extern	UINT16	minCellVol;

+ 2 - 1
inc/app.h

@@ -51,7 +51,7 @@ extern "C" {
 #define	BLSWVERSION		0x01020000    //BootLoader版本号V1.2.0.0
 #define	DRVSWVERSION		0x01050000     //驱动层版本号V1.4.0.0  驱动层1.5.0.0,增加了三轴
 //#define	APPSWVERSION		0x01020209     
-#define	APPSWVERSION		0x0203001F
+#define	APPSWVERSION		0x02030020
 //#define	APPSWVERSION		0x0201000E
 //--------------------------------------------------------------------------------
 
@@ -116,6 +116,7 @@ typedef struct AppDataType
     UINT32 AccMileage;
     UINT16 SysReStart;
     UINT8  RelayControl;
+    UINT8  ErrorMsg;
 }AppDataBody;
 typedef struct _AppDataHeader
 {

+ 25 - 0
src/CANTask.c

@@ -119,6 +119,31 @@ static void Can_Receive()
 								msgFlag = 0;
 							}
 						}
+						else if(CanRxMsg[i].Id == 0x7A2)
+						{
+							if(CanRxMsg[i].Data[0] == 0x01)
+							{
+								AppDataInfo.appDataModify = TRUE;	
+								AppDataInfo.RelayControl = TRUE;
+							}
+							else
+							{
+								AppDataInfo.appDataModify = TRUE;	
+								AppDataInfo.RelayControl = FALSE;
+							}
+							if(CanRxMsg[i].Data[1] == 0x01)
+							{
+								HeatForceControl = 0x01;
+							}
+							else if(CanRxMsg[i].Data[1] == 0x02)
+							{
+								HeatForceControl = 0x02;
+							}
+							else
+							{
+								HeatForceControl = 0x00;
+							}
+						}
 					}	
 					if(udsFlag==1)
 					{	

+ 25 - 2
src/MainTask.c

@@ -78,6 +78,7 @@ void appLoadConfig(void);
 void appSaveConfig(void);
 static void appGetNVMSavedData(void);
 void appSaveNVMData(void);
+void RecoveyTheData(void);
 static void setDefaultAppDataInfo(void);
 static void LoadAppDataInfo(void);
 static void appSaveDataInfo(void);
@@ -211,6 +212,23 @@ static void MainTask(void* arg)
                 if(Timer_count%10==0)
                 {
                     BattWorkStateDelayFunc(battWorkState);
+                    if( BattWorkStateDelay ==0x02)
+                    {
+                        BattChrgEndFlag=TRUE;
+                    }
+                    else
+                    {
+                        BattChrgEndFlag=FALSE;
+                    }
+                    if(AppDataInfo.ErrorMsg != 0)
+                    {
+                        if(osOK==osMutexAcquire(Error_Mutex, 100))
+                        {
+                            UINT8 ErrorNumTemp = AppDataInfo.ErrorMsg;
+                            PutErrorNum((UINT16 *)ErrorNum,sizeof(ErrorNum),ErrorNumTemp);
+                        }
+                        osMutexRelease(Error_Mutex);
+                    }
                 }
                 if(Work_timer_end)
                 {
@@ -251,7 +269,7 @@ static void MainTask(void* arg)
                 #ifdef USING_PRINTF1
                     printf("TcpService:%d,UDSSwitch:%d,BMS_Fota_update_flag:%d,battWorkState:%d,Can_Msg_Enble:%d\r\n",TcpService,UDSSwitch,BMS_Fota_update_flag,battWorkState,Can_Msg_Enble);
                 #endif	
-                if(TcpService!=0x00||UDSSwitch==1||BMS_Fota_update_flag||battWorkState!=0||CanMsgFlag==0x01)
+                if(TcpService!=0x00||UDSSwitch==1||BMS_Fota_update_flag||battWorkState!=0||CanMsgFlag==0x01||battSOC>=90)
                 {
                     xTimerReset(work_timer,0);
                 }
@@ -813,7 +831,11 @@ static void LoadAppDataInfo(void)
     OsaFclose(fp);
     return;
 }
-
+void RecoveyTheData(void)
+{
+    setDefaultAppDataInfo();
+    appSaveDataInfo();
+}
 //无法找到文件时的第一次启动,后续不会启动此函数
 static void setDefaultAppDataInfo(void)
 {
@@ -828,6 +850,7 @@ static void setDefaultAppDataInfo(void)
     AppDataInfo.AccMileage = 0;
     AppDataInfo.SysReStart = 0;
     AppDataInfo.RelayControl = 0;
+    AppDataInfo.ErrorMsg = 0;
     return;
 }
 void BattWorkStateDelayFunc(UINT8 battWorkCurrentState)

+ 2 - 0
src/Signal.c

@@ -58,6 +58,8 @@ UINT8	VibrationStatus = 0x00;
 UINT8   RxInterprut = 0x00;
 UINT8   chargerConnectState = 0x00;
 UINT8   BattWorkStateDelay  = 0x00;
+UINT8   HeatForceControl = 0x00;
+UINT8   AvgBattTemp = 0x00;
 //declear the UINT16 vars
 UINT16	battCellU[28] = {0xFFFF};
 UINT16	minCellVol = 0xFFFF;

+ 5 - 5
src/TcpTask.c

@@ -272,8 +272,8 @@ static void TcpDataInfoAssembleSend()
     switch(BattWorkStateDelay)
     {
         case BATT_IDLE_SYM:
-            BattSendFreq = 30/5;
-            GpsSendFreq = 30/5;
+            BattSendFreq = 60/5;
+            GpsSendFreq = 60/5;
             break;
         case BATT_DISCHARGE_SYM:
             GpsSendFreq = 10/5;
@@ -284,8 +284,8 @@ static void TcpDataInfoAssembleSend()
             GpsSendFreq = 30/5;
             break;
         default:
-            BattSendFreq = 30/5;
-            GpsSendFreq = 30/5;
+            BattSendFreq = 60/5;
+            GpsSendFreq = 60/5;
             break;
     }
     if(VibrationStatus)
@@ -579,7 +579,7 @@ static void TcpDataInfoAssembleSend()
             }
         }
     }
-    if(send_counter%12==0 && send_counter!=0)//发送调试信息,此处发送参数信息/60s一次
+    if(send_counter%BattSendFreq==0 && send_counter!=0)//发送调试信息,此处发送参数信息/60s一次
     {
         DebugMsgtoTcpType DebugMsgInfo;
         UINT8 *SendBuffer = NULL;

+ 5 - 0
src/UDSService.c

@@ -279,6 +279,11 @@ void UDS_Service()
 											ret = HAL_Can_Transmit(UDSAnswer);
 										}										
 									}
+									else if(UDSSubService[i] == 0xFF)
+									{
+										RecoveyTheData();
+										UDSPositiveAnswer(0x04,i,00);
+									}
 									else if(UDSSubService[i] == 0x0F) //write the update config:updateDifferDataByteLen
 									{										
 										updateDifferDataByteLen = (CanRxMsg[i].Data[2]<<16)|(CanRxMsg[i].Data[3]<<8)|CanRxMsg[i].Data[4];										

+ 74 - 63
src/UartTask.c

@@ -72,7 +72,7 @@ void battWarningStateDisplay(void);
 void battLockStateDisplay(UINT8 lockState);
 void relayControlFunc(float DutyRatio,UINT8  BuzzerPeriod);
 void SP_BMS_Update_Service(void);
-BOOL BattHeaterSwitch(UINT8* heaterSwitch);
+BOOL BattHeaterSwitch(UINT8* heaterSwitch,UINT8 HeatForceControl);
 UINT16  encryptionAlgorithm (UINT16 plainText);
 UINT8  decryptionAlgorithm (UINT16 cipherText);
 UINT8 Uart_Encrypt_Send(void);
@@ -103,9 +103,7 @@ static void UartTask(void* arg)
     PROC_UART_STATE_SWITCH(PROCESS_UART_STATE_ENCRYPT);
     UINT16  Reg_Num = 0;
     UINT16  Uart_Uds_LEN;
-    UINT16  Uart_Recv_LEN;
 	UINT32  currentTimerCount=0;
-	BOOL uartReadSuccessFlag = false;
     Uart_Read_Msg_Type Uart_Read_Msg;
 	memset(&(Uart_Read_Msg),0x00,sizeof(Uart_Read_Msg_Type));
     Uart_Write_Data_Type UartWriteData; //Uart控制命令
@@ -147,15 +145,11 @@ static void UartTask(void* arg)
                 }
                 else if(Timer_count%10==0)
                 {
-                    #ifdef USING_PRINTF1
-                        printf("[%d]Uart Timer 1s:%d,uartReadSuccessFlag:%d\n",__LINE__,Timer_count,uartReadSuccessFlag);
-                    #endif
-                    if(osMessageQueueGet(UartWriteCmdHandle,&UartWriteData,0,0)==osOK && uartReadSuccessFlag==TRUE)
-                    {
-                        #ifdef USING_PRINTF
-                            printf("[%d]UartWriteCmdHandle :%x-%X%X\n",__LINE__,UartWriteData.WriteCmd,UartWriteData.Data[0],UartWriteData.Data[1]);
+					#ifdef USING_PRINTF
+                            printf("[%d]AvgBattTemp :%d,UartBattInfoRecvFlag:%d,battHeatEnableState:%d \n",__LINE__,AvgBattTemp,UartBattInfoRecvFlag,battHeatEnableState);
                         #endif
-						Ringtimes = 0;
+                    if(osMessageQueueGet(UartWriteCmdHandle,&UartWriteData,0,0)==osOK && UartBattInfoRecvFlag==TRUE)
+                    {
                         PROC_UART_STATE_SWITCH(PROCESS_UART_STATE_WRITE);
 						break;
                     }
@@ -169,39 +163,26 @@ static void UartTask(void* arg)
 				{
 					AppDataInfo.RelayControl=TRUE;
 				}
-				if((maxCellTemp>=45+40)&&(minCellTemp>=45+40)&&(battHeatEnableState==0x00)&&(MOSTemp>=70+40))//温度的判定需要加40摄氏度,如果模组最高>=45度,模组最低>=45度,mos温度>=70度,并且加热关闭,持续超过10s,则断开继电器,锁定放电mos
+				if((AvgBattTemp>=45+40)&&(battHeatEnableState==0x00)&&(MOSTemp>=70+40))//温度的判定需要加40摄氏度,如果模组最高>=45度,模组最低>=45度,mos温度>=70度,并且加热关闭,持续超过10s,则断开继电器,锁定放电mos
 				{
 					heatErrorCounter++;
 					if(heatErrorCounter>100)
 					{
+						AppDataInfo.ErrorMsg = 20;
 						heatErrorCounter = 0;
 						AppDataInfo.appDataModify = TRUE;
 						AppNVMData.appDataModify = TRUE;
 						AppDataInfo.RelayControl=TRUE;
 						AppNVMData.isBattLocked = TRUE;
-						if(osOK==osMutexAcquire(Error_Mutex, 100))
-						{
-							UINT8 ErrorNumTemp = 20;
-							PutErrorNum((UINT16 *)ErrorNum,sizeof(ErrorNum),ErrorNumTemp);
-						}
-						osMutexRelease(Error_Mutex);
 					}
 				}
-				if(UartReadMsg.Header[2]>0)
-				{
-					uartReadSuccessFlag = true;
-				}
-				else
-				{
-					uartReadSuccessFlag = false;
-				}
 				if(Timer_count-currentTimerCount >= 1)
 				{
 					if(AppNVMData.isBattLocked != 0)
 					{
 						battLockStateDisplay(TRUE);
 					}
-					else if(uartReadSuccessFlag)
+					else if(UartBattInfoRecvFlag)
 					{
 						battSOCDisplay();
 						battErrorStateDisplay();
@@ -232,19 +213,20 @@ static void UartTask(void* arg)
 							Ringtimes = 0;
 						}
 					}
-					else if(UDSSwitch==1 && Ringtimes<=50)
+					else if(CanMsgFlag==1 && Ringtimes<=50)
 					{
 						relayControlFunc(0.6,5);//表示1s响2次,占比80%
 						Ringtimes++;
+						if(Ringtimes>=50)
+						{
+							Ringtimes = 51;
+							relayControl(FALSE);
+						}
 					}
 					else if(BuzzerControl==TRUE)
 					{
 						relayControlFunc(0.6,5);//表示1s响2次,占比80%
 					}
-					if(Ringtimes>=50)
-					{
-						relayControl(FALSE);
-					}
 				}
 				currentTimerCount = Timer_count;
 				if(BMS_Fota_update_flag)
@@ -256,56 +238,71 @@ static void UartTask(void* arg)
 					}
 				}
 				//限制充电测试
-				if((battSOC>=95)&&(BattWorkStateDelay ==0x02)&&(((UartReadMsg.data[(0x1B+BATT_CELL_VOL_NUM+BATT_TEMP_NUM+BATT_OTHER_TEMP_NUM)*2+1])&0x02)!=0x00))//try to lock lock the charge 
+				if((battSOC>=95)&&(BattWorkStateDelay ==0x02)&&(((UartReadMsg.data[(0x1B+BATT_CELL_VOL_NUM+BATT_TEMP_NUM+BATT_OTHER_TEMP_NUM)*2+1])&0x02)!=0x00)&&(UartBattInfoRecvFlag==TRUE))//try to lock lock the charge 
 				{
+					#ifdef USING_PRINTF
+                        printf("[%d]try to lock charge \n",__LINE__);
+                    #endif
 					UartWriteData.WriteCmd = 0x01;
 					UartWriteData.Data[0] = 0x00|(UartReadMsg.data[(0x1B+BATT_CELL_VOL_NUM+BATT_TEMP_NUM+BATT_OTHER_TEMP_NUM)*2]);
 					UartWriteData.Data[1] = 0x00|((UartReadMsg.data[(0x1B+BATT_CELL_VOL_NUM+BATT_TEMP_NUM+BATT_OTHER_TEMP_NUM)*2+1])&0x01);
 					osMessageQueuePut(UartWriteCmdHandle,&UartWriteData,0,0);
 				}
-				else if((battSOC<=90)&&(((UartReadMsg.data[(0x1B+BATT_CELL_VOL_NUM+BATT_TEMP_NUM+BATT_OTHER_TEMP_NUM)*2+1])&0x02)!=0x02))//try to unlock lock the charge 
+				else if((battSOC<=90)&&(((UartReadMsg.data[(0x1B+BATT_CELL_VOL_NUM+BATT_TEMP_NUM+BATT_OTHER_TEMP_NUM)*2+1])&0x02)!=0x02)&&(UartBattInfoRecvFlag==TRUE))//try to unlock lock the charge 
 				{
+					#ifdef USING_PRINTF
+                        printf("[%d]try to unlock charge \n",__LINE__);
+                    #endif
 					UartWriteData.WriteCmd = 0x01;
 					UartWriteData.Data[0] = 0x00|(UartReadMsg.data[(0x1B+BATT_CELL_VOL_NUM+BATT_TEMP_NUM+BATT_OTHER_TEMP_NUM)*2]);
 					UartWriteData.Data[1] = 0x02|((UartReadMsg.data[(0x1B+BATT_CELL_VOL_NUM+BATT_TEMP_NUM+BATT_OTHER_TEMP_NUM)*2+1])&0x01);
 					osMessageQueuePut(UartWriteCmdHandle,&UartWriteData,0,0);
 				}
-				if((battWorkState ==0x00) && (AppNVMData.isBattLocked==TRUE) && (((UartReadMsg.data[(0x1B+BATT_CELL_VOL_NUM+BATT_TEMP_NUM+BATT_OTHER_TEMP_NUM)*2+1])&0x01)!=0x00))//try to lock lock the discharge 
+				if((battWorkState ==0x00) && (AppNVMData.isBattLocked==TRUE) && (((UartReadMsg.data[(0x1B+BATT_CELL_VOL_NUM+BATT_TEMP_NUM+BATT_OTHER_TEMP_NUM)*2+1])&0x01)!=0x00)&&(UartBattInfoRecvFlag==TRUE))//try to lock lock the discharge 
 				{
 					#ifdef USING_PRINTF
-                        printf("[%d]try to lock:%X-%X\n",__LINE__,AppNVMData.isBattLocked,(UartReadMsg.data[(0x1B+BATT_CELL_VOL_NUM+BATT_TEMP_NUM+BATT_OTHER_TEMP_NUM)*2+1])&0x03);
+                        printf("[%d]try to lock discharge \n",__LINE__);
                     #endif
 					UartWriteData.WriteCmd = 0x01;
 					UartWriteData.Data[0] = 0x00|(UartReadMsg.data[(0x1B+BATT_CELL_VOL_NUM+BATT_TEMP_NUM+BATT_OTHER_TEMP_NUM)*2]);
 					UartWriteData.Data[1] = 0x00|((UartReadMsg.data[(0x1B+BATT_CELL_VOL_NUM+BATT_TEMP_NUM+BATT_OTHER_TEMP_NUM)*2+1])&0x02);
 					osMessageQueuePut(UartWriteCmdHandle,&UartWriteData,0,0);
 				}
-				else if (battWorkState ==0x00 && AppNVMData.isBattLocked==FALSE && (((UartReadMsg.data[(0x1B+BATT_CELL_VOL_NUM+BATT_TEMP_NUM+BATT_OTHER_TEMP_NUM)*2+1])&0x01)!=0x01)&&(uartReadSuccessFlag==TRUE)) // try to unlock
+				else if (battWorkState ==0x00 && AppNVMData.isBattLocked==FALSE && (((UartReadMsg.data[(0x1B+BATT_CELL_VOL_NUM+BATT_TEMP_NUM+BATT_OTHER_TEMP_NUM)*2+1])&0x01)!=0x01)&&(UartBattInfoRecvFlag==TRUE)) // try to unlock
 				{
 					#ifdef USING_PRINTF
-                        printf("[%d]try to unlock:%X-%X\n",__LINE__,AppNVMData.isBattLocked,(UartReadMsg.data[(0x1B+BATT_CELL_VOL_NUM+BATT_TEMP_NUM+BATT_OTHER_TEMP_NUM)*2+1])&0x03);
+                        printf("[%d]try to unlock discharge \n",__LINE__);
                     #endif
 					UartWriteData.WriteCmd = 0x01;
 					UartWriteData.Data[0] = 0x00|(UartReadMsg.data[(0x1B+BATT_CELL_VOL_NUM+BATT_TEMP_NUM+BATT_OTHER_TEMP_NUM)*2]);
 					UartWriteData.Data[1] = 0x01|((UartReadMsg.data[(0x1B+BATT_CELL_VOL_NUM+BATT_TEMP_NUM+BATT_OTHER_TEMP_NUM)*2+1])&0x02);
 					osMessageQueuePut(UartWriteCmdHandle,&UartWriteData,0,0);
 				}
-				if((AppDataInfo.RelayControl==TRUE) && (((UartReadMsg.data[(0x1B+BATT_CELL_VOL_NUM+BATT_TEMP_NUM+BATT_OTHER_TEMP_NUM)*2])&0x80)==0x00)&&(uartReadSuccessFlag==TRUE))//继电器断开
+				if((AppDataInfo.RelayControl==TRUE) && (((UartReadMsg.data[(0x1B+BATT_CELL_VOL_NUM+BATT_TEMP_NUM+BATT_OTHER_TEMP_NUM)*2])&0x80)==0x00)&&(UartBattInfoRecvFlag==TRUE))//继电器断开
 				{
+					#ifdef USING_PRINTF
+                        printf("[%d]try to cut relay \n",__LINE__);
+                    #endif
 					UartWriteData.WriteCmd = 0x03;
 					UartWriteData.Data[0] = 0x80;
 					UartWriteData.Data[1] = 0x00|(UartReadMsg.data[(0x1B+BATT_CELL_VOL_NUM+BATT_TEMP_NUM+BATT_OTHER_TEMP_NUM)*2+1]);
 					osMessageQueuePut(UartWriteCmdHandle,&UartWriteData,0,0);
 				}
-				else if((AppDataInfo.RelayControl==FALSE) && (((UartReadMsg.data[(0x1B+BATT_CELL_VOL_NUM+BATT_TEMP_NUM+BATT_OTHER_TEMP_NUM)*2])&0x80)==0x80)&&(uartReadSuccessFlag==TRUE))//继电器闭合
+				else if((AppDataInfo.RelayControl==FALSE) && (((UartReadMsg.data[(0x1B+BATT_CELL_VOL_NUM+BATT_TEMP_NUM+BATT_OTHER_TEMP_NUM)*2])&0x80)==0x80)&&(UartBattInfoRecvFlag==TRUE))//继电器闭合
 				{
+					#ifdef USING_PRINTF
+                        printf("[%d]try to recover relay \n",__LINE__);
+                    #endif
 					UartWriteData.WriteCmd = 0x03;
 					UartWriteData.Data[0] = 0x00;
 					UartWriteData.Data[1] = 0x00|(UartReadMsg.data[(0x1B+BATT_CELL_VOL_NUM+BATT_TEMP_NUM+BATT_OTHER_TEMP_NUM)*2+1]);
 					osMessageQueuePut(UartWriteCmdHandle,&UartWriteData,0,0);
 				}
-				if(BattHeaterSwitch(&HeatSwitch)==TRUE)
+				if(BattHeaterSwitch(&HeatSwitch,HeatForceControl)==TRUE&&(UartBattInfoRecvFlag==TRUE))
 				{
+					#ifdef USING_PRINTF
+                        printf("[%d]try to change heatstate \n",__LINE__);
+                    #endif
 					UartWriteData.WriteCmd = 0x02;
 					UartWriteData.Data[0] = 0x00;
 					UartWriteData.Data[1] = HeatSwitch&0xFF;
@@ -316,6 +313,7 @@ static void UartTask(void* arg)
             case PROCESS_UART_STATE_READ:
             {
                 UINT16 CRC_chk_buffer;
+				UINT16  Uart_Recv_LEN = 0;
                 Reg_Num = 0x21+BATT_CELL_VOL_NUM+BATT_TEMP_NUM + BATT_OTHER_TEMP_NUM;//按照协议里面的0x21+X+N的结束地址
                 Uart_Read_Msg.Bms_Address = BMS_ADDRESS_CODE;
                 Uart_Read_Msg.Bms_Funcode = UART_READ_CODE;
@@ -341,14 +339,6 @@ static void UartTask(void* arg)
 				}
                 UartReadMsg.len = Uart_Recv_LEN;
                 PROC_UART_STATE_SWITCH(PROCESS_UART_STATE_IDLE);
-                if( battWorkState ==0x02)
-                {
-                    BattChrgEndFlag=TRUE;
-                }
-                else
-                {
-                    BattChrgEndFlag=FALSE;
-                }
 				#ifdef USING_PRINTF1
                     printf("[%d]lock:%X,permit:%X,Mos:%x\n",__LINE__,AppNVMData.isBattLocked,(UartReadMsg.data[(0x1B+BATT_CELL_VOL_NUM+BATT_TEMP_NUM+BATT_OTHER_TEMP_NUM)*2+1])&0x03,((UartReadMsg.data[(0x09+BATT_CELL_VOL_NUM+BATT_OTHER_TEMP_NUM)*2+1])>>1)&0x03);
                 #endif
@@ -533,11 +523,14 @@ static BOOL uartBattInfoDecode(UINT8* dataPtr)
     //SOC紧急修复
 	maxCellTemp = 0x00;
 	minCellTemp = 0xFF;
+	UINT16 TempBuffer = 0;
 	for(i=0;i<BATT_TEMP_NUM;i++)
 	{
+		TempBuffer = battCellTemp[i] + TempBuffer;
 		maxCellTemp = max(maxCellTemp,battCellTemp[i]);
 		minCellTemp = min(minCellTemp,battCellTemp[i]);		
 	}
+	AvgBattTemp = (TempBuffer-maxCellTemp-minCellTemp)/(BATT_TEMP_NUM - 2);
 	nbSwVersion = APPSWVERSION;
 	nbHwVersion = HWVERSION;
 	BmsErrorDecode(battWarningState);
@@ -859,33 +852,51 @@ UINT8 Uart_DataRecv_func(Uart_Read_Msg_Type Uart_Read_Msg_Fun,UINT8* Uart_Recv_B
   \return   (BOOL) isNeedtoSwitch: true: need to send cmd to turn on/off the switch
   								 false: do not need to do anything
 */
-BOOL BattHeaterSwitch(UINT8* heaterSwitch)
+BOOL BattHeaterSwitch(UINT8* heaterSwitch,UINT8 HeatForceControl)
 {
- BOOL isNeedtoSwitch = FALSE;
- 
- UINT8 i =0; 
- UINT8 currentSwitchState = 0;
-
- //get the current switch state and the cell temp
- currentSwitchState = battHeatEnableState & 0x01;
+	BOOL isNeedtoSwitch = FALSE;
+	
+	UINT8 i =0; 
+	UINT8 currentSwitchState = 0;
 
-	if(currentSwitchState==0)  //当前状态为关闭,判断是否应该开启
+	//get the current switch state and the cell temp
+	currentSwitchState = battHeatEnableState & 0x01;
+	if(HeatForceControl==1)//强制开启
 	{
-		if((chargerConnectState == 1 && minCellTemp<5+40 && minCellTemp>=-29+40 && maxCellTemp<25+40)||(chargerConnectState==0 && minCellTemp<5+40 && minCellTemp>=-29+40 && battSOC>=10 && (((battProtectState>> 21)&0x01) == 0)))//温度偏移为40 
+		if(currentSwitchState==0) 
 		{
 			*heaterSwitch = 1;
 			isNeedtoSwitch = true;
 		}
 	}
-	else        //当前状态为开启,判断是否应该关闭
+	else if(HeatForceControl==2)//强制关闭
 	{
-		if((minCellTemp>=10+40 || maxCellTemp>=30+40)||(chargerConnectState == 0 && minCellTemp<5+40 && minCellTemp>=-29+40 && battSOC<5))
+		if(currentSwitchState==1) 
 		{
 			*heaterSwitch = 0;
-			isNeedtoSwitch= true;
+			isNeedtoSwitch = true;
+		}
+	}
+	else//不强制控制
+	{
+		if(currentSwitchState==0)  //当前状态为关闭,判断是否应该开启
+		{
+			if((chargerConnectState == 1 && minCellTemp<5+40 && minCellTemp>=-29+40 && maxCellTemp<25+40)||(chargerConnectState==0 && minCellTemp<5+40 && minCellTemp>=-29+40 && battSOC>=10 && (((battProtectState>> 21)&0x01) == 0)))//温度偏移为40 
+			{
+				*heaterSwitch = 1;
+				isNeedtoSwitch = true;
+			}
+		}
+		else        //当前状态为开启,判断是否应该关闭
+		{
+			if((minCellTemp>=10+40 || maxCellTemp>=30+40)||(chargerConnectState == 0 && minCellTemp<5+40 && minCellTemp>=-29+40 && battSOC<5))
+			{
+				*heaterSwitch = 0;
+				isNeedtoSwitch= true;
+			}
 		}
 	}
- return isNeedtoSwitch;
+	return isNeedtoSwitch;
 }
 
 void battSOCDisplay()