CHENJIE-PC\QiXiang_CHENJIE před 3 roky
rodič
revize
4e814b9fde
22 změnil soubory, kde provedl 4964 přidání a 366 odebrání
  1. 8 2
      ARMCC/Makefile
  2. 39 72
      inc/AppConfig.h
  3. 44 0
      inc/AppFunc.h
  4. 8 11
      inc/AppSignal.h
  5. 0 0
      inc/AppTaskCan.h
  6. 0 0
      inc/AppTaskGps.h
  7. 39 0
      inc/AppTaskLed.h
  8. 2 0
      inc/AppTaskMain.h
  9. 23 19
      inc/AppTaskTcp.h
  10. 0 0
      inc/AppTaskUart.h
  11. 0 26
      inc/Fota.h
  12. 7 1
      inc/app.h
  13. 1252 0
      src/AppFunc.c
  14. 20 46
      src/AppSignal.c
  15. 273 0
      src/AppTaskCan.c
  16. 209 0
      src/AppTaskGps.c
  17. 48 0
      src/AppTaskLed.c
  18. 10 63
      src/AppTaskMain.c
  19. 54 0
      src/AppTaskTcp.c
  20. 2919 0
      src/AppTaskUart.c
  21. 9 12
      src/app.c
  22. 0 114
      src/hal_module_adapter.c

+ 8 - 2
ARMCC/Makefile

@@ -18,6 +18,12 @@ obj-y             += PLAT/project/$(TARGET)/apps/qx_app/src/app.o \
 		     		PLAT/project/$(TARGET)/apps/qx_app/src/bsp_custom.o \
 					PLAT/project/$(TARGET)/apps/qx_app/src/hal_module_adapter.o \
 					PLAT/project/$(TARGET)/apps/qx_app/src/sensor.o \
-					PLAT/project/$(TARGET)/apps/qx_app/src/MainTask.o \
-					PLAT/project/$(TARGET)/apps/qx_app/src/Signal.o
+					PLAT/project/$(TARGET)/apps/qx_app/src/AppSignal.o \
+					PLAT/project/$(TARGET)/apps/qx_app/src/AppFunc.o \
+					PLAT/project/$(TARGET)/apps/qx_app/src/AppMainTask.o \
+					PLAT/project/$(TARGET)/apps/qx_app/src/AppTcpTask.o \
+					PLAT/project/$(TARGET)/apps/qx_app/src/AppLedTask.o \
+					PLAT/project/$(TARGET)/apps/qx_app/src/AppUartTask.o \
+					PLAT/project/$(TARGET)/apps/qx_app/src/AppCanTask.o \
+					PLAT/project/$(TARGET)/apps/qx_app/src/AppGpsTask.o 
 include $(TOP)/PLAT/tools/scripts/Makefile.rules

+ 39 - 72
inc/AppConfig.h

@@ -1,89 +1,59 @@
 /****************************************************************************
  *
- * Copy right:   2021-, Copyrigths of RLWL Ltd.
- * File name:    app.h
- * Description:  App Config H file
+ * Copy right:   2021-, Copyrigths of RLWL Ltd.Chen J
+ * File name:    AppConfig.h
+ * Description:  App Config H file 配置文件,可以针对不同参数进行更改
  * History:      Rev3.0   2021-07-06
  *
  ****************************************************************************/
 
-#define BMS_MANUFACTURE (2)         //BMS制造商表示1-超力源,2-美顺
-#define DATA_MODULE_TYPE (1)        //1表示NB模块,2表示4G cat1
-#define BMS_INFO  (1)               //1-1表示超力源4830,1-2表示超力源6060,2-1表示美顺6455
-#define EOLSTATE (0)                //1标识下线检测跳过,使用默认值
-#define DEFAULT_SN                "RLTEST00000000001"
-#if  BMS_MANUFACTURE==1
-    #if BMS_INFO==1
-        #define BATT_CELL_VOL_NUM  (14)
-        #define BATT_TEMP_NUM  (3)
-        #define BATT_OTHER_TEMP_NUM  (2)
-    #elif BMS_INFO==2
-        #define BATT_CELL_VOL_NUM  (17)
-        #define BATT_TEMP_NUM  (4)
-        #define BATT_OTHER_TEMP_NUM  (2)
-    #endif
-#elif  BMS_MANUFACTURE==2
-    #if BMS_INFO==1
-        #define BATT_CELL_VOL_NUM  (20)
-        #define BATT_TEMP_NUM  (3)
-        #define BATT_OTHER_TEMP_NUM  (2)
-    #elif BMS_INFO==2
-        #define BATT_CELL_VOL_NUM  (17)
-        #define BATT_TEMP_NUM  (4)
-        #define BATT_OTHER_TEMP_NUM  (2)
-    #elif BMS_INFO==3
-        #define BATT_CELL_VOL_NUM  (20)
-        #define BATT_TEMP_NUM  (4)
-        #define BATT_OTHER_TEMP_NUM  (2)
-    #endif
-#endif
+#define BMS_MANUFACTURE             (2)                 //BMS制造商表示1-超力源,2-美顺
+#define BMS_INFO                    (1)                 //1-1表示超力源4830,1-2表示超力源6060,2-1表示美顺6455
+#define DATA_MODULE_TYPE            (1)                 //1表示NB模块,2表示4G cat1
+#define EOLSTATE                    (0)                 //1表示下线检测跳过,使用默认值,0表示使用下线检测
+#define DEFAULT_SN                  "RLTEST00000000001" //默认上传的SN编码
+#define	APPSWVERSION		        0x03000000          //数据模块软件版本号
 
-#define NB_OTHER_TEMP_NUM  (4)                      //NB采集的温度个数
-#define BATT_CELL_VOL_NUM_2 (BATT_CELL_VOL_NUM*2)
+#define TCP_ADD                     "iotp.fast-fun.cn"  //数据上传的地址
+#define TCP_PORT					8712                //数据上传的端口
 
-#define HWVERSION		    0x0102              //硬件主版本,现为V1.2板
-#define	BLSWVERSION		0x01020000              //BootLoader版本号V1.2.0.0
-#define	DRVSWVERSION		0x01050000          //驱动层版本号V1.4.0.0  驱动层1.5.0.0,增加了三轴
-#define	APPSWVERSION		0x03000000          //数据模块软件版本号
-#define APP_CONFIG_FILE_LATEST_VERSION 0
-#define APP_CONFIG_FILE_NAME  "qxappconfig.nvm"
-#define APP_DATAINFO_FILE_NAME  "qxappDataInfo.nvm"
-#define BATT_SN_LEN           17
+#define NB_OTHER_TEMP_NUM           (4)                 //NB采集的温度个数
+#define HWVERSION		            0x0102              //硬件主版本,现为V1.2板
+#define	BLSWVERSION		            0x01020000          //BootLoader版本号V1.2.0.0
+#define	DRVSWVERSION		        0x01050000          //驱动层版本号V1.4.0.0  驱动层1.5.0.0,增加了三轴
+
+#define APP_CONFIG_FILE_NAME                "qxappconfig.nvm"
+#define APP_DATAINFO_FILE_NAME              "qxappDataInfo.nvm"
+#define BATT_SN_LEN                          17
 
 //declear struct vars   结构体变量定义
-typedef struct AppNVMDataType
+typedef struct AppConfigDataType
 {	
     BOOL   appDataModify;		//数据更改标志位
 	UINT8  battSN[BATT_SN_LEN]; //电池SN号码
-   	BOOL   isBattLocked;		//电池锁定状态0:not locked;	1:locked
-    UINT8  chargEndWorkTime;   //the unit is min 充电结束持续发送时间
-    UINT8  wakeupWorkTime;     //the unit is min 唤醒工作时间
-    UINT8  sleepTime;           //睡眠时间
-    UINT16 HwVersion;
-    UINT32 BLSwVersion;
-    UINT32 DrvSwVersion;
-    UINT32 AppSwVersion;
 	UINT8  EOLState;            //下线检测状态
-}AppNVMDataType;
+    UINT32 AppSwVersion;        //软件版本
+    UINT8  BattCellCount;       //电池电压串数
+    UINT8  BattTempCount;       //电池温度个数
+}AppConfigDataType;
 
-typedef struct AppConfigHeader
+typedef struct AppConfigDataHeader
 {
     UINT16 fileBodySize; //file body size, not include size of header;
-    UINT8  version;
     UINT8  checkSum;
-}AppConfigHeader;
+}AppConfigDataHeader;
 
 typedef struct AppDataType
 {	
-    BOOL   appDataModify;		//数据更改标志位
-    UINT8  BmsChrgInfoSendFreq;
-    UINT8  BmsDisChrgInfoSendFreq;
-    UINT8  GpsChrgInfoSendFreq;
-    UINT8  GpsDisChrgInfoSendFreq;
-    INT8  BattCurrentNegFlag;
-    UINT32 CumulativeCapacity;
-    UINT32 AccMileage;
-    UINT16 SysReStart;
+    BOOL   appDataModify;		        //数据更改标志位
+    UINT8  BattInfoSendFreqHigh;        //电池信息发送间隔高频,单位s
+    UINT8  BattInfoSendFreqNomal;       //电池信息发送间隔正常,单位s     
+    UINT8  BattInfoSendFreqLow;         //电池信息发送间隔低频,单位s
+    UINT8  PosInfoSendFreqHigh;         //定位信息发送间隔高频,单位s
+    UINT8  PosInfoSendFreqNormal;       //定位信息发送间隔正常,单位s
+    UINT8  PosInfoSendFreqLow;          //定位信息发送间隔低频,单位s
+    UINT32 AccMileage;                  //累计里程,单位m
+    UINT16 SysReStartCount;             //系统重启次数
 }AppDataBody;
 typedef struct _AppDataHeader
 {
@@ -91,11 +61,8 @@ typedef struct _AppDataHeader
     UINT8  checkSum;
 }AppDataHeader;
 
-
-typedef struct _UartAnswerMsg
+typedef struct AppSocketConnectionContext_Tag
 {
-	BOOL UartFlag;
-    UINT8 dataPtr[8];
-    UINT16 len;
-}UartAnswerMsgType;
-
+    INT32 id;
+    INT32 status;
+}AppSocketConnectionContext;

+ 44 - 0
inc/AppFunc.h

@@ -0,0 +1,44 @@
+/****************************************************************************
+ *
+ * Copy right:   RL.Chen J and Zhen C
+ * File name:    AppFunc.h
+ * Description:  应用层函数调用文件
+ * History:      2021-07-15
+ *
+ ****************************************************************************/
+#include "flash_ec616_rt.h"
+#include "commontypedef.h"
+#include "flash_ec616_rt.h"
+#include "mem_map.h"
+#include "AppTaskTcp.h"
+#include "AppConfig.h"
+#include "ec_tcpip_api.h"
+
+#define FLASH_BMS_FOTA_START_ADDR         0x2E6000          //BMS升级文件存储起始地址
+#define FLASH_BMS_FOTA_LEN                0x32000           //BMS升级文件存储长度 = =200k
+#define FLASH_BMS_FOTA_END_ADDR           0x318000          //BMS升级文件存储结束地址
+typedef struct _Fota_Type
+{
+    BOOL    Fota_update_error ;
+    UINT32  Fota_All_Data_Len ;
+    UINT32  Fota_Current_Addres ;
+    UINT8   Fota_Recv_Data_Len ;
+    UINT8   Fota_Recv_Data[100] ;
+    UINT32  Fota_Flash_Addres;
+    UINT8   Fota_CRC ;
+
+}Fota_Type;
+
+UINT8 Fota_Func(UINT8 *DataPtr,INT32 connectId);
+void CANEncodeFunction(UINT32 ID,UINT8* rawData);
+void UDS_Service();
+UINT16 GetErrorNum(UINT16 *ErrorArray,UINT8 Errorlen);
+UINT8 PutErrorNum(UINT16 *ErrorArray,UINT8 Errorlen,UINT16 ErrorNum);
+UINT8 LookUpRTtable(UINT32 R_value);
+
+static BOOL UDSClearFotaDownloadRegion(void);
+static BOOL UDSAskforDownLoadData(void);
+static UINT8 UDSPositiveAnswer(UINT8 answerLen,UINT8 messageIndex,UINT32 posCode);
+static UINT8 UDSNegtiveAnswer(UINT8 answerLen,UINT8 messageIndex, UINT32 negCode);
+static UINT8 bcc_chk_fota(UINT8* data, UINT8 length);
+static UINT8 Fota_crc_chk(UINT8* data,UINT8 length);

+ 8 - 11
inc/Signal.h → inc/AppSignal.h

@@ -42,11 +42,13 @@ extern UINT8	reservedSignal6;
 extern UINT8	reservedSignal7;
 extern UINT8	reservedSignal8;
 
-extern UINT8   Lockstatus;
-extern UINT8   TcpErrorcount;
-extern UINT8   TcpSendLen;
-extern UINT8   CanMsgEnble;
+extern UINT8    Lockstatus;
+extern UINT8    TcpErrorcount;
+extern UINT8    TcpSendLen;
+extern UINT8    CanMsgEnble;
 extern UINT8 	UDSSwitch;
+extern UINT8 	UDSSwitch ;
+extern UINT8 	PosFlag ;      
 //declear the UINT16 vars
 extern UINT16	battCellU[28];
 extern UINT16	minCellVol;
@@ -68,11 +70,6 @@ extern UINT32  TimeCounter;
 
 //declear other vars
 extern osMutexId_t Error_Mutex;
-
-
-extern UINT16	COMOutTable[28];
- 
-extern AppNVMDataType AppNVMData;
+extern AppConfigDataType AppNVMData;
 extern AppDataBody AppDataInfo;
-
-
+extern AppSocketConnectionContext socContext;  //网络连接状态

+ 0 - 0
inc/CANTask.h → inc/AppTaskCan.h


+ 0 - 0
inc/GpsTask.h → inc/AppTaskGps.h


+ 39 - 0
inc/AppTaskLed.h

@@ -0,0 +1,39 @@
+/****************************************************************************
+ *
+ * Copy right:   Qx.Chen Jie
+ * File name:    LedTask.h
+ * Description:  Led闪烁逻辑
+ * History:      2021-07-05
+ * Version:      V3.0
+ ****************************************************************************/
+#include "commontypedef.h"
+#include "bsp.h"
+#include "bsp_custom.h"
+#include "osasys.h"
+#include "ostask.h"
+#include "queue.h"
+#include "ps_event_callback.h"
+#include "cmisim.h"
+#include "cmimm.h"
+#include "cmips.h"
+#include "sockets.h"
+#include "psifevent.h"
+#include "ps_lib_api.h"
+#include "lwip/netdb.h"
+#include "debug_log.h"
+#include "slpman_ec616.h"
+#include "plat_config.h"
+#include "ec_tcpip_api.h"
+#include "hal_module_adapter.h"
+#include "timers.h"
+#include "Signal.h"
+
+#define PROC_LED_TASK_STACK_SIZE           (256)
+typedef enum
+{
+    PROCESS_LED_STATE_IDLE = 0,
+    PROCESS_LED_STATE_WORK,
+    PROCESS_LED_STATE_SLEEP
+}process_LED;
+void LedTaskInit(void *arg);
+void LedTaskDeInit(void *arg);

+ 2 - 0
inc/MainTask.h → inc/AppTaskMain.h

@@ -29,12 +29,14 @@
 #include "Signal.h"
 
 #define PROC_MAIN_TASK_STACK_SIZE           (1024+512)
+
 typedef enum
 {
     PROCESS_STATE_IDLE = 0,
     PROCESS_STATE_WORK,
     PROCESS_STATE_SLEEP
 }process_Main;
+
 void MainTaskInit(void* arg);
 void MainTaskDeInit(void* arg);
 extern void GsensorInit(void);

+ 23 - 19
inc/TcpTask.h → inc/AppTaskTcp.h

@@ -6,8 +6,28 @@
  * History:      2021-03-07
  *
  ****************************************************************************/
-#include "app.h"
-extern UINT32 TcpService;
+#include "commontypedef.h"
+#include "bsp.h"
+#include "bsp_custom.h"
+#include "osasys.h"
+#include "ostask.h"
+#include "queue.h"
+#include "ps_event_callback.h"
+#include "cmisim.h"
+#include "cmimm.h"
+#include "cmips.h"
+#include "sockets.h"
+#include "psifevent.h"
+#include "ps_lib_api.h"
+#include "lwip/netdb.h"
+#include "debug_log.h"
+#include "slpman_ec616.h"
+#include "plat_config.h"
+#include "ec_tcpip_api.h"
+#include "hal_module_adapter.h"
+#include "timers.h"
+#include "Signal.h"
+
 #define PROC_TCP_TASK_STACK_SIZE           (2048)
 #define QMSG_ID_BASE               (0x160) 
 #define QMSG_ID_NW_IP_READY        (QMSG_ID_BASE)
@@ -18,21 +38,11 @@ extern UINT32 TcpService;
 #define QMSG_ID_SOCK_EXIT       	(QMSG_ID_BASE + 6)
 #define APP_EVENT_QUEUE_SIZE    (10)
 
-#define CHRG_END_DELAY    (300)
-#define RUN_END_DELAY    (100)
-
-
-#define QX_TCP_ADD              "iotp.fast-fun.cn"
-#define QX_TCP_PORT					8712
-// #define QX_TCP_IPADRRES				"47.97.127.222"
-// #define QX_TCP_PORT					8712
 /*---------------测试IP地址-----------------------------------*/
-// #define QX_TCP_IPADRRES				"39.103.177.126"
-// #define QX_TCP_PORT					8712
 // #define QX_TCP_ADD 				"rpi.it5000.com"
 // #define QX_TCP_PORT					8812
 /*---------------测试IP地址END-----------------------------------*/
-#define BATT_SN_LEN             17
+
 #define TCP_START_SYM1			0x23
 #define TCP_START_SYM2			0x23
 #define TCP_CMD_SYM				0x02	//实时信息上报是0x02
@@ -171,12 +181,6 @@ typedef enum
     APP_SOCKET_CONNECTION_CONNECTED,    
 }AppSocketConnectionStatus;
 
-typedef struct AppSocketConnectionContext_Tag
-{
-    INT32 id;
-    INT32 status;
-}AppSocketConnectionContext;
-
 typedef enum
 {
     PROCESS_TCP_STATE_IDLE = 0,

+ 0 - 0
inc/UartTask.h → inc/AppTaskUart.h


+ 0 - 26
inc/Fota.h

@@ -1,26 +0,0 @@
-/****************************************************************************
- *
- * Copy right:   Qx.ChenJie
- * File name:    Fota.h
- * Description:  Fota函数
- * History:      2021-03-15
- * 
- ****************************************************************************/
-#include "bsp_custom.h"
-#define FLASH_BMS_FOTA_START_ADDR         0x2E6000
-#define FLASH_BMS_FOTA_LEN               0x32000  //200k
-#define FLASH_BMS_FOTA_END_ADDR         0x318000
-typedef struct _Fota_Type
-{
-    bool Fota_update_error ;
-    UINT32 Fota_All_Data_Len ;
-    UINT32 Fota_Current_Addres ;
-    UINT8 Fota_Recv_Data_Len ;
-    UINT8 Fota_Recv_Data[100] ;
-    UINT32 Fota_Flash_Addres;
-    UINT8 Fota_CRC ;
-
-}Fota_Type;
-extern volatile bool NB_Fota_update_flag;
-extern volatile bool BMS_Fota_update_flag;
-void Fota_Func(UINT8 *DataPtr,INT32 connectId);

+ 7 - 1
inc/app.h

@@ -1,6 +1,6 @@
 /****************************************************************************
  *
- * Copy right:   2021-, Copyrigths of RLWL Ltd.
+ * Copy right:   2021-, Copyrigths of RLWL Ltd. Chen J
  * File name:    app.h
  * Description:  App definition H file
  * History:      Rev3.0   2021-07-06
@@ -30,6 +30,12 @@
 #ifdef __cplusplus
 extern "C" {
 #endif
+extern void AppTaskMainInit(void* arg);
+extern void AppTaskTcpInit(void *arg);
+extern void AppTaskLedInit(void *arg);
+extern void AppTaskGpsInit(void *arg);
+extern void AppTaskUartInit(void *arg);
+extern void AppTaskCanInit(void *arg);
 #ifdef __cplusplus
 }
 #endif

+ 1252 - 0
src/AppFunc.c

@@ -0,0 +1,1252 @@
+/****************************************************************************
+ *
+ * Copy right:   RL.Chen J and Zhen C
+ * File name:    AppFunc.c
+ * Description:  应用层函数调用文件
+ * History:      2021-03-15
+ *
+ ****************************************************************************/
+#include "AppFunc.h"
+#include "AppSignal.h"
+/*******
+ * Fota升级处理函数
+ * 输入:网络接收的数据,网络链接ID
+ * 输出:0x00表示数据未准备完成,0x01表示数据模块OTA数据准备完成,0x88表示BMS的OTA数据准备完成
+ * 处理:将接收的数据进行校验,搬运至升级区域,并进行应答
+*******/
+UINT8 Fota_Func(UINT8 *DataPtr,INT32 connectId)
+{
+    UINT8 		Fota_Answer[43]={0};
+	Fota_Type 	Fota_S;
+    UINT8 		Fota_Cmd = 0;
+    INT8 		ret = 0;
+    UINT8* 		Data_Read_Buffer = NULL;
+    UINT8 		Data_Read_Crc = 0;
+    if(*(DataPtr+30)==0x01)
+    {
+        Fota_S.Fota_Flash_Addres = FLASH_FOTA_REGION_START;
+        Fota_Cmd = *(DataPtr+31);
+        Fota_Answer[0] = TCP_START_SYM1;
+        Fota_Answer[1] = TCP_START_SYM2;
+        Fota_Answer[2] = TCP_CONCMD_SYM;
+        switch (Fota_Cmd)
+        {
+            case 0x01:
+            {
+                Fota_S.Fota_All_Data_Len = *(DataPtr+33)<<24|*(DataPtr+34)<<16|*(DataPtr+35)<<8|*(DataPtr+36);
+                Fota_S.Fota_Current_Addres = *(DataPtr+37)<<24|*(DataPtr+38)<<16|*(DataPtr+39)<<8|*(DataPtr+40);
+                if(Fota_S.Fota_All_Data_Len>=(FLASH_BMS_FOTA_START_ADDR - FLASH_FOTA_REGION_START))
+                {
+                    Fota_Answer[3] = 0x02;
+                }
+                else
+                {
+                    Fota_Answer[3] = 0x01;
+                    BSP_QSPI_Erase_Safe(Fota_S.Fota_Flash_Addres,Fota_S.Fota_All_Data_Len + 4 - (Fota_S.Fota_All_Data_Len%4)); //对齐擦除
+                }
+                memcpy(&Fota_Answer[4],(DataPtr+4),BATT_SN_LEN);
+                Fota_Answer[21] = TCP_ENCPT_DISABLE;
+                Fota_Answer[22] = 0x00;
+                Fota_Answer[23] = 0x12;
+                memcpy(&Fota_Answer[24],(DataPtr+24),18);
+                Fota_Answer[42] =  bcc_chk_fota(Fota_Answer,42);
+                tcpipConnectionSend(connectId,Fota_Answer,43,0,0,0);
+                break;
+            }
+            case 0x02:
+            {
+                Fota_S.Fota_All_Data_Len = *(DataPtr+33)<<24|*(DataPtr+34)<<16|*(DataPtr+35)<<8|*(DataPtr+36);
+                Fota_S.Fota_Current_Addres = *(DataPtr+37)<<24|*(DataPtr+38)<<16|*(DataPtr+39)<<8|*(DataPtr+40);
+                Fota_S.Fota_Recv_Data_Len = *(DataPtr+41);
+                memset(Fota_S.Fota_Recv_Data,0x00,100);
+                memcpy(Fota_S.Fota_Recv_Data,(DataPtr+42),*(DataPtr+41));
+                Fota_S.Fota_CRC = Fota_crc_chk(Fota_S.Fota_Recv_Data,Fota_S.Fota_Recv_Data_Len);
+                if(Fota_S.Fota_CRC == *(DataPtr+Fota_S.Fota_Recv_Data_Len+42))
+                {
+                    if(Fota_S.Fota_Recv_Data_Len%4!=0)
+                    {
+                    Fota_S.Fota_Recv_Data_Len = Fota_S.Fota_Recv_Data_Len + 4-(Fota_S.Fota_Recv_Data_Len%4);
+                    }
+                    BSP_QSPI_Write_Safe(Fota_S.Fota_Recv_Data,Fota_S.Fota_Flash_Addres+Fota_S.Fota_Current_Addres,Fota_S.Fota_Recv_Data_Len);
+                    Data_Read_Buffer = malloc(Fota_S.Fota_Recv_Data_Len);
+                    BSP_QSPI_Read_Safe(Data_Read_Buffer,Fota_S.Fota_Flash_Addres+Fota_S.Fota_Current_Addres,Fota_S.Fota_Recv_Data_Len);
+                    Data_Read_Crc = Fota_crc_chk(Data_Read_Buffer,Fota_S.Fota_Recv_Data_Len);
+                    #ifdef USING_PRINTF
+                        printf("\n\n\n");
+                        for(int i=0;i<Fota_S.Fota_Recv_Data_Len;i++)
+                        {
+                            printf("%x  ",*(Data_Read_Buffer+i));
+                        }    
+                        printf("\n\n\n");
+                    #endif
+					if(Data_Read_Buffer!=NULL)
+                    	free(Data_Read_Buffer);
+					Data_Read_Buffer = NULL;
+                    if(Data_Read_Crc==Fota_S.Fota_CRC )
+                    {
+                        Fota_Answer[3] = 0x01;
+                    }
+                    else
+                    {
+                        Fota_Answer[3] = 0x02;
+                        BSP_QSPI_Erase_Safe(Fota_S.Fota_Flash_Addres+Fota_S.Fota_Current_Addres,Fota_S.Fota_Recv_Data_Len);
+                    }
+                }
+                else//数据校验失败
+                {
+                    Fota_Answer[3] = 0x02;
+                }
+                memcpy(&Fota_Answer[4],(DataPtr+4),BATT_SN_LEN);
+                Fota_Answer[21] = TCP_ENCPT_DISABLE;
+                Fota_Answer[22] = 0x00;
+                Fota_Answer[23] = 0x12;
+                memcpy(&Fota_Answer[24],(DataPtr+24),18);
+                Fota_Answer[42] =  bcc_chk_fota(Fota_Answer,42);
+                tcpipConnectionSend(connectId,Fota_Answer,43,0,0,0);
+                break;
+            }
+            case 0x03:
+            {
+                Fota_S.Fota_All_Data_Len = *(DataPtr+33)<<24|*(DataPtr+34)<<16|*(DataPtr+35)<<8|*(DataPtr+36);
+                Fota_S.Fota_Current_Addres = *(DataPtr+37)<<24|*(DataPtr+38)<<16|*(DataPtr+39)<<8|*(DataPtr+40);
+                Fota_Answer[3] = 0x01;
+                memcpy(&Fota_Answer[4],(DataPtr+4),BATT_SN_LEN);
+                Fota_Answer[21] = TCP_ENCPT_DISABLE;
+                Fota_Answer[22] = 0x00;
+                Fota_Answer[23] = 0x12;
+                memcpy(&Fota_Answer[24],(DataPtr+24),18);
+                Fota_Answer[42] =  bcc_chk_fota(Fota_Answer,42);
+                tcpipConnectionSend(connectId,Fota_Answer,43,0,0,0);
+                if(Fota_S.Fota_All_Data_Len==Fota_S.Fota_Current_Addres)
+                {
+                    return 0x01;
+                }
+                else
+                {
+                    return 0x00;
+                }
+                break;
+            }
+            default:
+            {
+                Fota_Answer[3] = 0x02;
+                memcpy(&Fota_Answer[4],(DataPtr+4),BATT_SN_LEN);
+                Fota_Answer[21] = TCP_ENCPT_DISABLE;
+                Fota_Answer[22] = 0x00;
+                Fota_Answer[23] = 0x12;
+                memcpy(&Fota_Answer[24],(DataPtr+24),18);
+                Fota_Answer[42] =  bcc_chk_fota(Fota_Answer,42);
+                tcpipConnectionSend(connectId,Fota_Answer,43,0,0,0);
+                break;
+            }
+                
+        }
+		return 0x00;
+    }
+    else if(*(DataPtr+30)==0x88)//BMS升级文件存放
+    {
+        Fota_S.Fota_Flash_Addres = FLASH_BMS_FOTA_START_ADDR;
+        Fota_Cmd = *(DataPtr+31);
+        Fota_Answer[0] = TCP_START_SYM1;
+        Fota_Answer[1] = TCP_START_SYM2;
+        Fota_Answer[2] = TCP_CONCMD_SYM;
+        switch (Fota_Cmd)
+        {
+            case 0x01:
+            {
+                Fota_S.Fota_All_Data_Len = *(DataPtr+33)<<24|*(DataPtr+34)<<16|*(DataPtr+35)<<8|*(DataPtr+36);
+                Fota_S.Fota_Current_Addres = *(DataPtr+37)<<24|*(DataPtr+38)<<16|*(DataPtr+39)<<8|*(DataPtr+40);
+                if(Fota_S.Fota_All_Data_Len>=(FLASH_BMS_FOTA_END_ADDR - FLASH_BMS_FOTA_START_ADDR))
+                {
+                    Fota_Answer[3] = 0x02;
+                }
+                else
+                {
+                    Fota_Answer[3] = 0x01;
+                }
+                memcpy(&Fota_Answer[4],(DataPtr+4),BATT_SN_LEN);
+                Fota_Answer[21] = TCP_ENCPT_DISABLE;
+                Fota_Answer[22] = 0x00;
+                Fota_Answer[23] = 0x12;
+                memcpy(&Fota_Answer[24],(DataPtr+24),18);
+                Fota_Answer[42] =  bcc_chk_fota(Fota_Answer,42);
+                tcpipConnectionSend(connectId,Fota_Answer,43,0,0,0);
+                if(Fota_Answer[3] == 0x01)
+                {
+                    BSP_QSPI_Erase_Safe(Fota_S.Fota_Flash_Addres,Fota_S.Fota_All_Data_Len + 4 - (Fota_S.Fota_All_Data_Len%4)); //512k-32k = 480k -> 0x75300  0x78000
+                }
+                break;
+            }
+            case 0x02:
+            {
+                Fota_S.Fota_All_Data_Len = *(DataPtr+33)<<24|*(DataPtr+34)<<16|*(DataPtr+35)<<8|*(DataPtr+36);
+                Fota_S.Fota_Current_Addres = *(DataPtr+37)<<24|*(DataPtr+38)<<16|*(DataPtr+39)<<8|*(DataPtr+40);
+                Fota_S.Fota_Recv_Data_Len = *(DataPtr+41);
+                memset(Fota_S.Fota_Recv_Data,0x00,100);
+                memcpy(Fota_S.Fota_Recv_Data,(DataPtr+42),*(DataPtr+41));
+                Fota_S.Fota_CRC = Fota_crc_chk(Fota_S.Fota_Recv_Data,Fota_S.Fota_Recv_Data_Len);
+                if(Fota_S.Fota_CRC == *(DataPtr+Fota_S.Fota_Recv_Data_Len+42))
+                {
+                    if(Fota_S.Fota_Recv_Data_Len%4!=0)
+                    {
+                    Fota_S.Fota_Recv_Data_Len = Fota_S.Fota_Recv_Data_Len + 4-(Fota_S.Fota_Recv_Data_Len%4);
+                    }
+                    BSP_QSPI_Write_Safe(Fota_S.Fota_Recv_Data,Fota_S.Fota_Flash_Addres+Fota_S.Fota_Current_Addres,Fota_S.Fota_Recv_Data_Len);
+                    Data_Read_Buffer = malloc(Fota_S.Fota_Recv_Data_Len);
+                    BSP_QSPI_Read_Safe(Data_Read_Buffer,Fota_S.Fota_Flash_Addres+Fota_S.Fota_Current_Addres,Fota_S.Fota_Recv_Data_Len);
+                    Data_Read_Crc = Fota_crc_chk(Data_Read_Buffer,Fota_S.Fota_Recv_Data_Len);
+                    #ifdef USING_PRINTF1
+                        printf("\n\n\n");
+                        UINT8 temp[1];
+                        for(int i=0;i<Fota_S.Fota_Recv_Data_Len;i++)
+                        {
+                            printf("%x  ",*(Data_Read_Buffer+i));
+                        }    
+                        printf("\n\n\n");
+                    #endif
+                    if(Data_Read_Buffer!=NULL)
+                    	free(Data_Read_Buffer);
+					Data_Read_Buffer = NULL;
+                    if(Data_Read_Crc==Fota_S.Fota_CRC )
+                    {
+                        Fota_Answer[3] = 0x01;
+                    }
+                    else
+                    {
+                        Fota_Answer[3] = 0x02;
+                        BSP_QSPI_Erase_Safe(Fota_S.Fota_Flash_Addres+Fota_S.Fota_Current_Addres,Fota_S.Fota_Recv_Data_Len);
+                    }
+                }
+                else//数据校验失败
+                {
+                    Fota_Answer[3] = 0x02;
+                }
+                memcpy(&Fota_Answer[4],(DataPtr+4),BATT_SN_LEN);
+                Fota_Answer[21] = TCP_ENCPT_DISABLE;
+                Fota_Answer[22] = 0x00;
+                Fota_Answer[23] = 0x12;
+                memcpy(&Fota_Answer[24],(DataPtr+24),18);
+                Fota_Answer[42] =  bcc_chk_fota(Fota_Answer,42);
+                tcpipConnectionSend(connectId,Fota_Answer,43,0,0,0);
+                break;
+            }
+            case 0x03:
+            {
+                Fota_S.Fota_All_Data_Len = *(DataPtr+33)<<24|*(DataPtr+34)<<16|*(DataPtr+35)<<8|*(DataPtr+36);
+                Fota_S.Fota_Current_Addres = *(DataPtr+37)<<24|*(DataPtr+38)<<16|*(DataPtr+39)<<8|*(DataPtr+40);
+                Fota_Answer[3] = 0x01;
+                memcpy(&Fota_Answer[4],(DataPtr+4),BATT_SN_LEN);
+                Fota_Answer[21] = TCP_ENCPT_DISABLE;
+                Fota_Answer[22] = 0x00;
+                Fota_Answer[23] = 0x12;
+                memcpy(&Fota_Answer[24],(DataPtr+24),18);
+                Fota_Answer[42] =  bcc_chk_fota(Fota_Answer,42);
+                tcpipConnectionSend(connectId,Fota_Answer,43,0,0,0);
+                if(Fota_S.Fota_All_Data_Len==Fota_S.Fota_Current_Addres)
+                {
+                    return 0x88;
+                }
+                else
+                {
+                    return 0x00;
+                }
+                break;
+            }
+            default:
+            {
+                Fota_Answer[3] = 0x02;
+                memcpy(&Fota_Answer[4],(DataPtr+4),BATT_SN_LEN);
+                Fota_Answer[21] = TCP_ENCPT_DISABLE;
+                Fota_Answer[22] = 0x00;
+                Fota_Answer[23] = 0x12;
+                memcpy(&Fota_Answer[24],(DataPtr+24),18);
+                Fota_Answer[42] =  bcc_chk_fota(Fota_Answer,42);
+                tcpipConnectionSend(connectId,Fota_Answer,43,0,0,0);
+                break;
+            }
+        }
+		return 0x00;
+    }
+}
+static UINT8 bcc_chk_fota(UINT8* data, UINT8 length)
+{
+    UINT8 bcc_chk_return = 0x00;
+    UINT8 count = 0;
+    while (count<length)
+    {
+        bcc_chk_return^=data[count];
+        count++;
+    }
+    return  bcc_chk_return;
+}
+static UINT8 Fota_crc_chk(UINT8* data,UINT8 length)
+{  
+    UINT8 reg_crc=0x00;
+    while(length--)
+    { 
+        reg_crc ^= *data++;
+    }
+    return reg_crc;
+}
+/*******
+ * Can解码组包函数
+ * 输入:全局变量和缓存地址
+ * 输出:空
+ * 处理:将全局变量进行组包后存放
+*******/
+void CANEncodeFunction(UINT32 ID,UINT8* rawData)
+{
+	memset(rawData, 0xFF, 8);	
+	switch (ID)
+	{
+		case	0x6A0:
+			*(UINT16*)(rawData +0) = ((battCellU[0]>>8) & 0xFF) | (((battCellU[0]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +2) = ((battCellU[1]>>8) & 0xFF) | (((battCellU[1]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +4) = ((battCellU[2]>>8) & 0xFF) | (((battCellU[2]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +6) = ((battCellU[3]>>8) & 0xFF) | (((battCellU[3]&0xFF)<<8)&0xFF00);
+			break;
+		case	0x6A1:
+			*(UINT16*)(rawData +0) = ((battCellU[4]>>8) & 0xFF) | (((battCellU[4]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +2) = ((battCellU[5]>>8) & 0xFF) | (((battCellU[5]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +4) = ((battCellU[6]>>8) & 0xFF) | (((battCellU[6]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +6) = ((battCellU[7]>>8) & 0xFF) | (((battCellU[7]&0xFF)<<8)&0xFF00);
+			break;
+		case	0x6A2:
+			*(UINT16*)(rawData +0) = ((battCellU[8]>>8) & 0xFF) | (((battCellU[8]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +2) = ((battCellU[9]>>8) & 0xFF) | (((battCellU[9]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +4) = ((battCellU[10]>>8) & 0xFF) | (((battCellU[10]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +6) = ((battCellU[11]>>8) & 0xFF) | (((battCellU[11]&0xFF)<<8)&0xFF00);
+			break;
+		case	0x6A3:
+			*(UINT16*)(rawData +0) = ((battCellU[12]>>8) & 0xFF) | (((battCellU[12]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +2) = ((battCellU[13]>>8) & 0xFF) | (((battCellU[13]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +4) = ((battCellU[14]>>8) & 0xFF) | (((battCellU[14]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +6) = ((battCellU[15]>>8) & 0xFF) | (((battCellU[15]&0xFF)<<8)&0xFF00);
+			break;
+		case	0x6A4:
+			*(UINT16*)(rawData +0) = ((battCellU[16]>>8) & 0xFF) | (((battCellU[16]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +2) = ((battCellU[17]>>8) & 0xFF) | (((battCellU[17]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +4) = ((battCellU[18]>>8) & 0xFF) | (((battCellU[18]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +6) = ((battCellU[19]>>8) & 0xFF) | (((battCellU[19]&0xFF)<<8)&0xFF00);
+			break;
+		case	0x6A5:
+			*(UINT16*)(rawData +0) = ((battCellU[20]>>8) & 0xFF) | (((battCellU[20]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +2) = ((battCellU[21]>>8) & 0xFF) | (((battCellU[21]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +4) = ((battCellU[22]>>8) & 0xFF) | (((battCellU[22]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +6) = ((battCellU[23]>>8) & 0xFF) | (((battCellU[23]&0xFF)<<8)&0xFF00);
+			break;
+		case	0x6A6:
+			*(UINT16*)(rawData +0) = ((battCellU[24]>>8) & 0xFF) | (((battCellU[24]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +2) = ((battCellU[25]>>8) & 0xFF) | (((battCellU[25]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +4) = ((battCellU[26]>>8) & 0xFF) | (((battCellU[26]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +6) = ((battCellU[27]>>8) & 0xFF) | (((battCellU[27]&0xFF)<<8)&0xFF00);
+			break;
+		case	0x6B0:
+			*(UINT8*)(rawData +0) =battCellTemp[0]&0xFF;
+			*(UINT8*)(rawData +1) =battCellTemp[1]&0xFF;
+			*(UINT8*)(rawData +2) =battCellTemp[2]&0xFF;
+			*(UINT8*)(rawData +3) =battCellTemp[3]&0xFF;
+			*(UINT8*)(rawData +4) =battCellTemp[4]&0xFF;
+			*(UINT8*)(rawData +5) =battCellTemp[5]&0xFF;
+			*(UINT8*)(rawData +6) =battCellTemp[6]&0xFF;
+			*(UINT8*)(rawData +7) =battCellTemp[7]&0xFF;
+			break;
+		case	0x6BA:
+			*(UINT8*)(rawData +0) =MOSTemp&0xFF;
+			*(UINT8*)(rawData +1) =packTemp&0xFF;
+			*(UINT8*)(rawData +2) =fastChargeTemp&0xFF;
+			*(UINT8*)(rawData +3) =normalChargeTemp&0xFF;
+			*(UINT8*)(rawData +4) =heatTemp1&0xFF;
+			*(UINT8*)(rawData +5) =heatTemp2&0xFF;
+			*(UINT8*)(rawData +6) =nbReservedTemp1&0xFF;
+			*(UINT8*)(rawData +7) =nbReservedTemp2&0xFF;
+			break;
+		case	0x6C0:
+			*(UINT16*)(rawData +0) = ((minCellVol>>8) & 0xFF) | (((minCellVol&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +2) = ((maxCellVol>>8) & 0xFF) | (((maxCellVol&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +4) = ((battPackVol>>8) & 0xFF) | (((battPackVol&0xFF)<<8)&0xFF00);
+			*(UINT8*)(rawData +6) =maxCellTemp&0xFF;
+			*(UINT8*)(rawData +7) =minCellTemp&0xFF;
+			break;
+		case	0x6C1:
+			*(UINT8*)(rawData +0) =battSOC&0xFF;
+			*(UINT8*)(rawData +1) =battSOH&0xFF;
+			*(UINT16*)(rawData +2) = ((battI>>8) & 0xFF) | (((battI&0xFF)<<8)&0xFF00);
+			*(UINT8*)(rawData +4) =battWorkState&0xFF;
+			*(UINT32*)(rawData +5) = ((battWarningState>>16) & 0xFF)|((battWarningState)&0xFF00)|(((battWarningState&0xFF)<<16)&0xFF0000);
+			break;
+		case	0x6C2:
+			*(UINT32*)(rawData +0) = ((nbSwVersion>>24) & 0xFF)|((nbSwVersion>>8)&0xFF00)|((nbSwVersion<<8)&0xFF0000)|(((nbSwVersion&0xFF)<<24)&0xFF000000);
+			*(UINT16*)(rawData +4) = ((nbHwVersion>>8) & 0xFF) | (((nbHwVersion&0xFF)<<8)&0xFF00);
+			*(UINT8*)(rawData +6) =bmsSwVersion&0xFF;
+			*(UINT8*)(rawData +7) =bmsHwVersion&0xFF;
+			break;
+		case	0x6C3:
+			*(UINT32*)(rawData +0) = ((battBalanceoInfo>>24) & 0xFF)|((battBalanceoInfo>>8)&0xFF00)|((battBalanceoInfo<<8)&0xFF0000)|(((battBalanceoInfo&0xFF)<<24)&0xFF000000);
+			*(UINT8*)(rawData +4) =battMOSSwitchState&0xFF;
+			*(UINT8*)(rawData +5) =battHeatEnableState&0xFF;
+			break;
+		case	0x6C4:
+			*(UINT8*)(rawData +0) =reservedSignal1&0xFF;
+			*(UINT8*)(rawData +1) =reservedSignal2&0xFF;
+			*(UINT8*)(rawData +2) =reservedSignal3&0xFF;
+			*(UINT8*)(rawData +3) =reservedSignal4&0xFF;
+			*(UINT8*)(rawData +4) =reservedSignal5&0xFF;
+			*(UINT8*)(rawData +5) =reservedSignal6&0xFF;
+			*(UINT8*)(rawData +6) =reservedSignal7&0xFF;
+			*(UINT8*)(rawData +7) =reservedSignal8&0xFF;
+			break;
+		case	0x7C0:
+			*(UINT16*)(rawData +0) = ((battCellU[0]>>8) & 0xFF) | (((battCellU[0]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +2) = ((battCellU[1]>>8) & 0xFF) | (((battCellU[1]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +4) = ((battCellU[2]>>8) & 0xFF) | (((battCellU[2]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +6) = ((battCellU[3]>>8) & 0xFF) | (((battCellU[3]&0xFF)<<8)&0xFF00);
+			break;
+		case	0x7C1:
+			*(UINT16*)(rawData +0) = ((battCellU[4]>>8) & 0xFF) | (((battCellU[4]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +2) = ((battCellU[5]>>8) & 0xFF) | (((battCellU[5]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +4) = ((battCellU[6]>>8) & 0xFF) | (((battCellU[6]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +6) = ((battCellU[7]>>8) & 0xFF) | (((battCellU[7]&0xFF)<<8)&0xFF00);
+			break;
+		case	0x7C2:
+			*(UINT16*)(rawData +0) = ((battCellU[8]>>8) & 0xFF) | (((battCellU[8]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +2) = ((battCellU[9]>>8) & 0xFF) | (((battCellU[9]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +4) = ((battCellU[10]>>8) & 0xFF) | (((battCellU[10]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +6) = ((battCellU[11]>>8) & 0xFF) | (((battCellU[11]&0xFF)<<8)&0xFF00);
+			break;
+		case	0x7C3:
+			*(UINT16*)(rawData +0) = ((battCellU[12]>>8) & 0xFF) | (((battCellU[12]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +2) = ((battCellU[13]>>8) & 0xFF) | (((battCellU[13]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +4) = ((battCellU[14]>>8) & 0xFF) | (((battCellU[14]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +6) = ((battCellU[15]>>8) & 0xFF) | (((battCellU[15]&0xFF)<<8)&0xFF00);
+			break;
+		case	0x7C4:
+			*(UINT16*)(rawData +0) = ((battCellU[16]>>8) & 0xFF) | (((battCellU[16]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +2) = ((battCellU[17]>>8) & 0xFF) | (((battCellU[17]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +4) = ((battCellU[18]>>8) & 0xFF) | (((battCellU[18]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +6) = ((battCellU[19]>>8) & 0xFF) | (((battCellU[19]&0xFF)<<8)&0xFF00);
+			break;
+		case	0x7C5:
+			*(UINT16*)(rawData +0) = ((battCellU[20]>>8) & 0xFF) | (((battCellU[20]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +2) = ((battCellU[21]>>8) & 0xFF) | (((battCellU[21]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +4) = ((battCellU[22]>>8) & 0xFF) | (((battCellU[22]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +6) = ((battCellU[23]>>8) & 0xFF) | (((battCellU[23]&0xFF)<<8)&0xFF00);
+			break;
+		case	0x7C6:
+			*(UINT16*)(rawData +0) = ((battCellU[24]>>8) & 0xFF) | (((battCellU[24]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +2) = ((battCellU[25]>>8) & 0xFF) | (((battCellU[25]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +4) = ((battCellU[26]>>8) & 0xFF) | (((battCellU[26]&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +6) = ((battCellU[27]>>8) & 0xFF) | (((battCellU[27]&0xFF)<<8)&0xFF00);
+			break;
+		case	0x7C7:
+			*(UINT8*)(rawData +0) =battCellTemp[0]&0xFF;
+			*(UINT8*)(rawData +1) =battCellTemp[1]&0xFF;
+			*(UINT8*)(rawData +2) =battCellTemp[2]&0xFF;
+			*(UINT8*)(rawData +3) =battCellTemp[3]&0xFF;
+			*(UINT8*)(rawData +4) =battCellTemp[4]&0xFF;
+			*(UINT8*)(rawData +5) =battCellTemp[5]&0xFF;
+			*(UINT8*)(rawData +6) =battCellTemp[6]&0xFF;
+			*(UINT8*)(rawData +7) =battCellTemp[7]&0xFF;
+			break;
+		case	0x7C8:
+			*(UINT8*)(rawData +0) =MOSTemp&0xFF;
+			*(UINT8*)(rawData +1) =packTemp&0xFF;
+			*(UINT8*)(rawData +2) =fastChargeTemp&0xFF;
+			*(UINT8*)(rawData +3) =normalChargeTemp&0xFF;
+			*(UINT8*)(rawData +4) =heatTemp1&0xFF;
+			*(UINT8*)(rawData +5) =heatTemp2&0xFF;
+			*(UINT8*)(rawData +6) =nbReservedTemp1&0xFF;
+			*(UINT8*)(rawData +7) =nbReservedTemp2&0xFF;
+			break;
+		case	0x7C9:
+			*(UINT16*)(rawData +0) = ((minCellVol>>8) & 0xFF) | (((minCellVol&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +2) = ((maxCellVol>>8) & 0xFF) | (((maxCellVol&0xFF)<<8)&0xFF00);
+			*(UINT16*)(rawData +4) = ((battPackVol>>8) & 0xFF) | (((battPackVol&0xFF)<<8)&0xFF00);
+			*(UINT8*)(rawData +6) =maxCellTemp&0xFF;
+			*(UINT8*)(rawData +7) =minCellTemp&0xFF;
+			break;
+		case	0x7CA:
+			*(UINT8*)(rawData +0) =battSOC&0xFF;
+			*(UINT8*)(rawData +1) =battSOH&0xFF;
+			*(UINT16*)(rawData +2) = ((battI>>8) & 0xFF) | (((battI&0xFF)<<8)&0xFF00);
+			*(UINT8*)(rawData +4) =battWorkState&0xFF;
+			*(UINT32*)(rawData +5) = ((battWarningState>>16) & 0xFF)|((battWarningState)&0xFF00)|(((battWarningState&0xFF)<<16)&0xFF0000);
+			break;
+		case	0x7CB:
+			*(UINT32*)(rawData +0) = ((nbSwVersion>>24) & 0xFF)|((nbSwVersion>>8)&0xFF00)|((nbSwVersion<<8)&0xFF0000)|(((nbSwVersion&0xFF)<<24)&0xFF000000);
+			*(UINT16*)(rawData +4) = ((nbHwVersion>>8) & 0xFF) | (((nbHwVersion&0xFF)<<8)&0xFF00);
+			*(UINT8*)(rawData +6) =bmsSwVersion&0xFF;
+			*(UINT8*)(rawData +7) =bmsHwVersion&0xFF;
+			break;
+		case	0x7CC:
+			*(UINT32*)(rawData +0) = ((battBalanceoInfo>>24) & 0xFF)|((battBalanceoInfo>>8)&0xFF00)|((battBalanceoInfo<<8)&0xFF0000)|(((battBalanceoInfo&0xFF)<<24)&0xFF000000);
+			*(UINT8*)(rawData +4) =battMOSSwitchState&0xFF;
+			*(UINT8*)(rawData +5) =battHeatEnableState&0xFF;
+			break;
+		case	0x7CD:
+			*(UINT8*)(rawData +0) =reservedSignal1&0xFF;
+			*(UINT8*)(rawData +1) =reservedSignal2&0xFF;
+			*(UINT8*)(rawData +2) =reservedSignal3&0xFF;
+			*(UINT8*)(rawData +3) =reservedSignal4&0xFF;
+			*(UINT8*)(rawData +4) =reservedSignal5&0xFF;
+			*(UINT8*)(rawData +5) =reservedSignal6&0xFF;
+			*(UINT8*)(rawData +6) =reservedSignal7&0xFF;
+			*(UINT8*)(rawData +7) =reservedSignal8&0xFF;
+			break;
+		case	0x7B0:
+			*(UINT8*)(rawData +0) = (AppNVMData.battSN[0])&0xFF;
+			*(UINT8*)(rawData +1) = (AppNVMData.battSN[1])&0xFF;
+			*(UINT8*)(rawData +2) = (AppNVMData.battSN[2])&0xFF;
+			*(UINT8*)(rawData +3) = (AppNVMData.battSN[3])&0xFF;
+			*(UINT8*)(rawData +4) = (AppNVMData.battSN[4])&0xFF;
+			*(UINT8*)(rawData +5) = (AppNVMData.battSN[5])&0xFF;
+			*(UINT8*)(rawData +6) = (AppNVMData.battSN[6])&0xFF;
+			*(UINT8*)(rawData +7) = (AppNVMData.battSN[7])&0xFF;
+			break;
+		case	0x7B1:
+			*(UINT8*)(rawData +0) = (AppNVMData.battSN[8])&0xFF;
+			*(UINT8*)(rawData +1) = (AppNVMData.battSN[9])&0xFF;
+			*(UINT8*)(rawData +2) = (AppNVMData.battSN[10])&0xFF;
+			*(UINT8*)(rawData +3) = (AppNVMData.battSN[11])&0xFF;
+			*(UINT8*)(rawData +4) = (AppNVMData.battSN[12])&0xFF;
+			*(UINT8*)(rawData +5) = (AppNVMData.battSN[13])&0xFF;
+			*(UINT8*)(rawData +6) = (AppNVMData.battSN[14])&0xFF;
+			*(UINT8*)(rawData +7) = (AppNVMData.battSN[15])&0xFF;
+			break;
+		case	0x7B2:
+			*(UINT8*)(rawData +0) = (AppNVMData.battSN[16])&0xFF;
+			
+			break;
+		
+		default:
+			break;
+	}
+}
+/*******
+ * 下线检测诊断函数
+ * 输入:空
+ * 输出:空
+ * 处理:下线检测诊断
+*******/
+
+void UDS_Service()
+{
+	static UINT8	UDSService[2];
+	static UINT8	UDSSubService[2];
+	static UINT8	UDSSubServiceActionCode[2];
+	static UINT8 	UDSSwitch = 0;
+	static UINT8   UDSDialogMode = 01;
+	static UINT32  updateDifferDataByteLen = 0;
+	//each package means 100 bytes, max PackageCounter = updateDifferDataByteLen%100 + 1
+	static UINT16  updateDifferDataPackageCounter = 0;  
+	//each slice means 4 bytes, max SliceCounter = 25;
+	static UINT32  updateDifferDataSliceCounter = 0;
+	static UINT8   UDSBattSN[BATT_SN_LEN];
+	static BOOL downloadReady = FALSE;
+	UINT8 i,j= 0;
+	UINT32 k=0;
+	INT8 ret,errorCount = 0;
+	BOOL boolRet = false;
+	static UINT8 snFlag = 0;
+	static UINT32 sliceCounterFlag = 0;
+	UINT32 tempSliceCounter=0;	
+	static UINT8 counter=0;  
+	CAN_Msg_Type UDSAnswer ={0};
+	UINT8   updateDataBuffer[100];
+	UINT32 	posCode,negCode;
+	
+	
+	//UINT8 temp00[94] ={0x00,0x0E,0x00,0x05,0x0D,0xDE,0x0D,0xDE,0x0D,0xDE,0x0D,0xDE,0x0D,0x7A,0x0D,0xDE,0x0D,0xDE,0x0D,0xDE,0x0D,0xDE,0x0D,0xDE,0x0E,0x42,0x0D,0xDE,0x0D,0xDE,0x0D,0xDE,0x13,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x00,0x24,0x00,0x26,0x00,0x22,0x00,0x24,0x00,0x00,0x00,0x00,0x6e,0x78,0x00,0x00,0x00,0x00,0x00,0x5F,0x00,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x74,0x0E,0x42,0x0D,0x7A,0x00,0x00};
+	//MEMCPY(battInfo, temp00, 94);
+	
+	//while(true)
+	//{
+		//if(UDSSwitch == 1)
+		{
+			
+			
+			for(i=0; i<2; i++)
+			{
+				UDSAnswer.DLC = 8;
+				memset(UDSAnswer.Data, 0, UDSAnswer.DLC);
+				
+				if(CanRxMsg[i].Id == 0x7A0)
+					{
+					switch (UDSService[i])
+						{
+							case 0x10:
+								if(UDSSubService[i] == 0x01)
+								{
+									if((UDSDialogMode == 0x01 || UDSDialogMode==0x02)||UDSSwitch == 0)
+									{									
+										UDSPositiveAnswer(0x04,i,0x00);
+										UDSSwitch = 0;
+										UDSDialogMode = 1;
+									}
+									else
+									{
+										UDSNegtiveAnswer(0x05,i,0xFF);
+									}
+								}
+								else if(UDSSubService[i] == 0x02)
+								{
+									UDSPositiveAnswer(0x04,i,0x00);
+									UDSSwitch = 1;
+									UDSDialogMode = 2;									
+								}
+								else if(UDSSubService[i] == 0x03)
+								{
+									if(UDSSwitch == 1)
+									{
+										UDSPositiveAnswer(0x04,i,0x00);
+										UDSSwitch = 1;
+										UDSDialogMode = 3;
+			                		}
+			                		else
+			                		{
+										UDSNegtiveAnswer(0x05,i,0xFF);
+			                		}
+
+								}
+								else if(UDSSubService[i] == 0x11)   //make NB software reset
+								{
+									if(UDSDialogMode == 2)
+									{
+										UDSPositiveAnswer(0x04,i,0x00);										
+										osDelay(100);
+										appSaveNVMData();
+										appSetCFUN(0);
+										osDelay(1000);
+			                			EC_SystemReset();
+			                		}
+			                		else
+			                		{
+										UDSNegtiveAnswer(0x05,i,0xFF);  
+			                		}
+								}								
+								else
+								{
+									UDSNegtiveAnswer(0x05,i,0xEE);
+								}
+								break;
+							case 0x22:
+								if(UDSDialogMode == 2)
+								{
+									if(UDSSubService[i] == 0x01)		//check the sw of NB
+									{
+										UDSPositiveAnswer(0x08,i,APPSWVERSION);
+									}
+									else if(UDSSubService[i] == 0x02)  //check the hw of NB
+									{
+										UDSPositiveAnswer(0x06,i,HWVERSION);										
+									}
+									else if(UDSSubService[i] == 0x03)  //check the SN number
+									{											
+										switch(UDSSubServiceActionCode[i])
+										{
+											case 00:
+												UDSAnswer.Id = 0x7B0;
+												
+												CANEncodeFunction(UDSAnswer.Id, UDSAnswer.Data);
+												ret = HAL_Can_Transmit(UDSAnswer);
+												
+												break;
+												
+											case 01:
+												UDSAnswer.Id = 0x7B1;
+												CANEncodeFunction(UDSAnswer.Id, UDSAnswer.Data);
+												ret = HAL_Can_Transmit(UDSAnswer);
+
+												break;
+
+											case 02:
+												UDSAnswer.Id = 0x7B2;
+												CANEncodeFunction(UDSAnswer.Id, UDSAnswer.Data);
+												ret = HAL_Can_Transmit(UDSAnswer);
+												
+												break;
+											default:
+											break;											
+										}									
+									}
+									else if(UDSSubService[i] == 0x04)  //check the batt message
+									{
+										UDSAnswer.Id = 0x7C0+UDSSubServiceActionCode[i];
+										CANEncodeFunction(UDSAnswer.Id, UDSAnswer.Data);										
+										ret = HAL_Can_Transmit(UDSAnswer);										
+									}
+									else if(UDSSubService[i] == 0x05)  //check the enviroment temp of NB
+									{				
+										UINT32 temp = ((fastChargeTemp<<24)&0xFF000000) | ((normalChargeTemp<<16)&0xFF0000) | ((heatTemp1<<8)&0xFF00) | (heatTemp2&0xFF);				
+										UDSPositiveAnswer(0x08,i,temp);  //ntcvalue										
+									}									
+									else if(UDSSubService[i] == 0x06)	//check the tcp link of NB
+									{
+										UDSPositiveAnswer(0x06,i,TcpSendLen);  //TcpconnectStatus
+									}
+									else if(UDSSubService[i] == 0x07)  //check the GPS link of NB
+									{
+										posCode =(UINT32) PosFlag;
+										UDSPositiveAnswer(0x05,i,posCode);  //gps satellite num(uint8), should be modified
+									}	
+									else
+									{
+										UDSNegtiveAnswer(0x05,i,0xEE);
+									}
+								}
+								else	//the service is not surpported in current dialog mode
+								{
+									UDSNegtiveAnswer(0x05,i,0xFF);
+								}
+								break;
+							case 0x2E:   //write service
+								if(UDSDialogMode == 2)
+								{
+									if(UDSSubService[i] == 0x03)  // write the battSN
+									{
+										if(UDSSubServiceActionCode[i] == 0x00 && snFlag == 0x00)
+										{
+											for(j=0; j<5; j++)
+											{
+												UDSBattSN[j+5*0] = CanRxMsg[i].Data[j+3];
+											}	
+											snFlag = snFlag|0x01;
+										}
+										else if(UDSSubServiceActionCode[i] == 0x01 && snFlag == 0x01)
+										{
+											for(j=0; j<5; j++)
+											{
+												UDSBattSN[j+5*1] = CanRxMsg[i].Data[j+3];
+											}
+											snFlag = snFlag|0x02;
+										}
+										else if(UDSSubServiceActionCode[i] == 0x02 && snFlag == 0x03)
+										{
+											for(j=0; j<5; j++)
+											{
+												UDSBattSN[j+5*2] = CanRxMsg[i].Data[j+3];
+											}
+											snFlag = snFlag|0x04;
+										}
+										else if(UDSSubServiceActionCode[i] == 0x03 && snFlag == 0x07)
+										{
+											for(j=0; j<2; j++)
+											{
+												UDSBattSN[j+5*3] = CanRxMsg[i].Data[j+3];
+											}
+											snFlag = snFlag|0x08;
+										}
+
+										if(snFlag == 0x0F)
+										{
+											snFlag = 0;
+											UDSPositiveAnswer(0x04,i,00);
+											MEMCPY(AppConfigData.battSN, UDSBattSN, BATT_SN_LEN);
+											AppConfigData.EOLState = 1; //SN号写入完成,表明已经进行过下线配置
+											appSaveNVMData();
+										}
+										else
+										{
+											UDSAnswer.Id = 0x7A8;											
+											UDSAnswer.Data[0] = 0x05;
+											UDSAnswer.Data[1] = 0x3E;
+											UDSAnswer.Data[2] = UDSService[i];
+											UDSAnswer.Data[3] = UDSSubService[i];
+											UDSAnswer.Data[4] = snFlag;	
+											
+											ret = HAL_Can_Transmit(UDSAnswer);
+										}										
+									}
+									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];										
+										UDSPositiveAnswer(0x04,i,00);
+									}
+									else
+									{
+										UDSNegtiveAnswer(0x05,i,0xEE);
+										
+									}
+									break;
+								}								
+								else
+								{
+									UDSNegtiveAnswer(0x05,i,0xFF);
+								}
+								break;
+							case 0x31:  //clear the flash service
+								if(UDSDialogMode == 3)  
+								{
+									if(UDSSubService[i] == 0x0F)  //clear the fota flash
+									{
+										if(UDSSubServiceActionCode[i] == 0x01)
+										{
+											//Clear the Flash
+											boolRet = UDSClearFotaDownloadRegion();
+											//if ok											
+											UDSPositiveAnswer(0x05,i,(UINT32)boolRet);
+										}
+										else
+										{
+											UDSNegtiveAnswer(0x06,i,UDSSubServiceActionCode[i]<<8|0xFF);  //重点测试
+										}										
+									}
+									else
+									{
+										UDSNegtiveAnswer(0x05,i,0xEE);  //the subservice is not surpported
+									}
+								}
+								else
+								{
+									UDSNegtiveAnswer(0x05,i,0xFF);  //the survie is not surpported in current dialog mode
+								}
+								break;
+							case 0x34:  //prepare for some one process
+								if(UDSDialogMode == 3)
+								{
+									if(UDSSubService[i] == 0x0F)  //ask for download update data
+									{									
+										boolRet = UDSAskforDownLoadData();
+										//if ok											
+										UDSPositiveAnswer(0x05,i,(UINT32)boolRet);
+									}
+									else
+									{
+										UDSNegtiveAnswer(0x05,i,0xEE);
+									}
+								}
+								else
+								{
+									UDSNegtiveAnswer(0x05,i,0xFF);
+								}
+								break;
+							case 0x36:  //download the update data
+								if(UDSDialogMode == 3)
+								{
+									if(downloadReady == TRUE)
+									{
+										counter++;  //记录报文数量									
+										tempSliceCounter =  (CanRxMsg[i].Data[1]<<16)|(CanRxMsg[i].Data[2]<<8)|(CanRxMsg[i].Data[3]);
+									/*
+									#ifdef USING_PRINTF
+										printf("tempSliceCounter = %x\n",tempSliceCounter);
+									#endif
+									*/										
+										if(tempSliceCounter < (updateDifferDataPackageCounter+1)*25 && tempSliceCounter>=updateDifferDataPackageCounter*25)
+										{
+											updateDifferDataSliceCounter = tempSliceCounter % 25;
+											for(j=0;j<4;j++)
+											{
+												updateDataBuffer[updateDifferDataSliceCounter*4+j] = CanRxMsg[i].Data[4+j];
+											}								
+											
+											if(updateDifferDataSliceCounter>0)
+											{
+												sliceCounterFlag = sliceCounterFlag |(0x01<<updateDifferDataSliceCounter);
+											}
+											else
+											{
+												sliceCounterFlag = sliceCounterFlag |0x01;
+											}
+											/*
+										#ifdef USING_PRINTF
+											printf("sliceCounterFlag = %x  counter=%d\n",sliceCounterFlag,counter);
+										#endif
+										*/											
+										}
+										else
+										{
+											counter--;
+										}
+										
+										if(counter == 25)
+										{
+											counter = 0;											
+											if(sliceCounterFlag == 0x1FFFFFF)  //received all the 25 message of current package
+											{															
+												//write the buffer(100 byte) to flash
+												ret = (uint8_t)BSP_QSPI_Write_Safe(updateDataBuffer,FLASH_FOTA_REGION_START+(updateDifferDataPackageCounter)*100,100);
+												errorCount = 0;
+												while(ret != QSPI_OK && errorCount<3)  //try to write most 3 times
+												{
+													errorCount++;
+													BSP_QSPI_Erase_Safe(FLASH_FOTA_REGION_START+(updateDifferDataPackageCounter)*100,100);
+													ret = (uint8_t)BSP_QSPI_Write_Safe(updateDataBuffer,FLASH_FOTA_REGION_START+(updateDifferDataPackageCounter)*100,100);
+												}
+												if(ret == QSPI_OK)  // write successed
+												{
+													UDSPositiveAnswer(0x08,i,tempSliceCounter);	
+				/*									
+													#if 0
+													#ifdef USING_PRINTF
+														UINT8 checksum0,checksum1=0;
+														printf("updateDifferDataPackageCounter = %d\n",updateDifferDataPackageCounter);
+														printf("updateDataBuffer write:\n");
+														for(k=0;k<100;k++)
+														{
+															printf("%x  ",updateDataBuffer[k]);
+															checksum0+=updateDataBuffer[k];
+														}
+														printf("\n");	
+														
+														UINT8 readFlash=0;
+														printf("updateDataBuffer read:\n");
+														
+														for(k=0;k<100;k++)
+														{
+															BSP_QSPI_Read_Safe(&readFlash,FLASH_FOTA_REGION_START+updateDifferDataPackageCounter*100+k, 1);
+															printf("%2x ",readFlash);
+															checksum1+=readFlash;
+														}
+														printf("\n");
+														if(checksum0 == checksum1)
+														{
+															printf("write succeed!\nchecksum0 = %2x,checksum1 = %2x\n",checksum0,checksum1);
+														}
+														else
+														{
+															printf("write fail!\nchecksum0 = %2x,checksum1 = %2x\n",checksum0,checksum1);
+														}
+														//printf("write succeed, next updateDifferDataPackageCounter = %x\n",updateDifferDataPackageCounter+1);
+													#endif
+													#endif
+*/
+													memset(updateDataBuffer,0, 100);
+													sliceCounterFlag = 0x0;
+													updateDifferDataPackageCounter++;
+												}
+												else  //write fail
+												{
+													UDSNegtiveAnswer(0x08,i,0xFFFFFFFF);  //failed to write this package to flash
+													/*
+													#if 0
+													#ifdef USING_PRINTF
+														printf("write flash fail!! updateDifferDataPackageCounter = %d\n",updateDifferDataPackageCounter);
+														printf("ERROR: sliceCounterFlag=%x\n",sliceCounterFlag);
+													#endif
+													#endif
+													*/
+												}
+											}
+											else
+											{
+												//received 25 messages, but lose one or more messages
+												//in this case, updater will try to send the package again(most 4 times)
+												UDSNegtiveAnswer(0x08,i,sliceCounterFlag);
+												#ifdef USING_PRINTF
+														printf("ERROR: package lose one or mo message!! sliceCounterFlag = %x\n",sliceCounterFlag);
+												#endif
+												//sliceCounterFlag = 0x0;
+												/*
+											#ifdef USING_PRINTF
+												printf("updateDifferDataPackageCounter = %d\n",updateDifferDataPackageCounter+1);
+												printf("updateDataBuffer:\n");
+												for(k=0;k<100;k++)
+												{
+													printf("%x  ",updateDataBuffer[k]);
+												}
+												printf("\n");
+											#endif
+											*/
+												//memset(updateDataBuffer,0, 100);
+											}
+										}
+									}
+									else
+									{
+										UDSNegtiveAnswer(0x05,i,0xEF); //the download process is not ready
+										counter = 0;
+									}
+								}
+								else
+								{
+									UDSNegtiveAnswer(0x05,i,0xFF);  //the service is not surpported in current dialog mode
+								}
+								break;
+							case 0x37:  //exit some one process
+								if(UDSDialogMode == 3)
+								{
+									if(UDSSubService[i] == 0x0F)  // exit the download 
+									 {
+										UDSPositiveAnswer(0x04,i,0x00);
+									/*
+									#if 0
+									#ifdef USING_PRINTF
+										printf("CAN update data:\n");
+										UINT8 ts=0;
+										for(UINT32 jjj =0;jjj<updateDifferDataByteLen;jjj++)
+										{											
+											BSP_QSPI_Read_Safe(&ts,FLASH_FOTA_REGION_START+jjj,1);
+											printf("%x ",ts);
+										}
+										printf("\n");
+									#endif
+									#endif
+									*/
+										downloadReady = FALSE;
+									 }
+									 else
+									 {
+										UDSNegtiveAnswer(0x05,i,0xEE);
+									}
+								}
+								else
+								{
+									UDSNegtiveAnswer(0x05,i,0xFF);
+								}
+								break;
+							default:								
+								UDSNegtiveAnswer(0x04,i,0xFF);  //the service is not surpported
+								break;
+								
+						}
+					}
+				}
+			}
+	//}
+	for(i=0; i<2; i++)
+	{
+		UDSService[i] = 0;
+		UDSSubService[i] = 0;
+	}
+}
+
+UINT8 UDSPositiveAnswer(UINT8 answerLen,UINT8 messageIndex,UINT32 posCode)
+{
+	CAN_Msg_Type UDSAnswer;
+	UINT8 ret;
+	UDSAnswer.Id = 0x7A8;
+	UDSAnswer.DLC = 8;
+	UDSAnswer.Data[0] = answerLen;
+	UDSAnswer.Data[1] = 0x78;
+	UDSAnswer.Data[2] = UDSService[messageIndex];
+	UDSAnswer.Data[3] = UDSSubService[messageIndex];
+	if(answerLen == 4)
+	{
+		UDSAnswer.Data[4] = 0x00;
+		UDSAnswer.Data[5] = 0x00;
+		UDSAnswer.Data[6] = 0x00;
+		UDSAnswer.Data[7] = 0x00;
+	}
+	else if(answerLen==5)
+	{	UDSAnswer.Data[4] = posCode;
+		UDSAnswer.Data[5] = 0x00;
+		UDSAnswer.Data[6] = 0x00;
+		UDSAnswer.Data[7] = 0x00;
+	}
+	else if(answerLen==6)
+	{
+		UDSAnswer.Data[4] = posCode>>8;
+		UDSAnswer.Data[5] = posCode;
+		UDSAnswer.Data[6] = 0x00;
+		UDSAnswer.Data[7] = 0x00;
+	}
+	else if(answerLen==7)
+	{
+		UDSAnswer.Data[4] = posCode>>16;
+		UDSAnswer.Data[5] = posCode>>8;
+		UDSAnswer.Data[6] = posCode;
+		UDSAnswer.Data[7] = 0x00;
+	}
+	else if(answerLen==8)
+	{
+		UDSAnswer.Data[4] = posCode>>24;
+		UDSAnswer.Data[5] = posCode>>16;
+		UDSAnswer.Data[6] = posCode>>8;
+		UDSAnswer.Data[7] = posCode;
+	}
+	ret = HAL_Can_Transmit(UDSAnswer);
+	return ret;
+}
+
+UINT8 UDSNegtiveAnswer(UINT8 answerLen,UINT8 messageIndex, UINT32 negCode)
+{
+	CAN_Msg_Type UDSAnswer;
+	UINT8 ret;
+	UDSAnswer.Id = 0x7A8;
+	UDSAnswer.DLC = 8;
+	UDSAnswer.Data[0] = answerLen;
+	UDSAnswer.Data[1] = 0x7F;
+	UDSAnswer.Data[2] = UDSService[messageIndex];
+	UDSAnswer.Data[3] = UDSSubService[messageIndex];
+	if(answerLen==4)
+	{
+		UDSAnswer.Data[3] = negCode;
+		UDSAnswer.Data[4] = 0x00;
+		UDSAnswer.Data[5] = 0x00;
+		UDSAnswer.Data[6] = 0x00;
+		UDSAnswer.Data[7] = 0x00;
+	}
+	if(answerLen==5)
+	{	UDSAnswer.Data[4] = negCode;
+		UDSAnswer.Data[5] = 0x00;
+		UDSAnswer.Data[6] = 0x00;
+		UDSAnswer.Data[7] = 0x00;
+	}
+	else if(answerLen==6)
+	{
+		UDSAnswer.Data[4] = negCode>>8;
+		UDSAnswer.Data[5] = negCode;
+		UDSAnswer.Data[6] = 0x00;
+		UDSAnswer.Data[7] = 0x00;
+	}
+	else if(answerLen==7)
+	{
+		UDSAnswer.Data[4] = negCode>>16;
+		UDSAnswer.Data[5] = negCode>>8;
+		UDSAnswer.Data[6] = negCode;
+		UDSAnswer.Data[7] = 0x00;
+	}
+	else if(answerLen==8)
+	{
+		UDSAnswer.Data[4] = negCode>>24;
+		UDSAnswer.Data[5] = negCode>>16;
+		UDSAnswer.Data[6] = negCode>>8;
+		UDSAnswer.Data[7] = negCode;
+	}
+	ret = HAL_Can_Transmit(UDSAnswer);
+	return ret;
+}
+
+BOOL UDSAskforDownLoadData()
+{
+	updateDifferDataPackageCounter = 0;
+	downloadReady = true;
+	
+	return TRUE;
+}
+
+BOOL UDSClearFotaDownloadRegion()
+{
+	UINT8 ret = FALSE;
+	ret = BSP_QSPI_Erase_Safe(FLASH_FOTA_REGION_START, 0x46000); //512k-32k -200k = 280k -> 0x46000
+	
+	if(ret == QSPI_OK)
+	{
+		return TRUE;
+	}
+	else
+	{
+		return FALSE;
+	}
+}
+/*******
+ * RT查询函数
+ * 输入:R
+ * 输出:T
+ * 处理:利用R反查T
+*******/
+UINT8 LookUpRTtable(UINT32 R_value)
+{
+	UINT8 Temp_Table1[23] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22};
+	UINT8 Temp_Table2[217] = {23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,
+	49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,
+	84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,
+	115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,
+	142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,
+	169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,
+	196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,
+	223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239};
+	UINT32 R_Table1[23] = {202269,191063,180554,170694,161438,152746,144580,136905,129687,122898,116508,
+						110493,104827,99488,94455,89710,85233,81008,77019,73252,69693,66329,63148};
+	UINT16 R_Table2[217] = {
+	60140,57293,54599,52049,49633,47343,45174,43117,41166,39315,37558,35891,34307,32802,31373,
+	30014,28722,27493,26324,25211,24152,23144,22183,21268,20395,19564,18771,18015,17293,16604,
+	15947,15319,14720,14147,13600,13077,12577,12098,11641,11203,10784,10383,10000,9632,9280,8942,
+	8619,8309,8012,7727,7454,7191,6940,6698,6466,6244,6030,5825,5627,5438,5255,5080,4911,4749,4593,
+	4443,4299,4160,4026,3898,3773,3654,3539,3428,3321,3218,3119,3023,2931,2841,2755,2672,2592,2515,
+	2441,2369,2299,2232,2167,2104,2044,1985,1928,1874,1821,1769,1720,1672,1626,1581,1537,1495,1455,
+	1415,1377,1340,1305,1270,1236,1204,1172,1142,1112,1083,1056,1029,1002,977,952,928,905,883,861,
+	839,819,799,779,760,742,724,707,690,674,658,642,627,613,599,585,571,558,546,533,521,509,498,487,
+	476,466,455,445,436,426,417,408,399,391,382,374,366,359,351,344,337,330,323,316,310,304,298,292,
+	286,280,274,269,264,259,254,249,244,239,234,230,226,221,217,213,209,205,201,198,194,190,187,183,
+	180,177,174,171,168,165,162,159,156,153,151,148,145,143,141,138,136,133,131,129,127,125};
+	if(R_value>R_Table2[0])
+	{
+		if(R_value<=R_Table1[22])//判断是否超出表尾
+		{
+			return Temp_Table1[22];
+		}
+		else if(R_value>=R_Table1[0])//判断是否超出表头
+		{
+			return Temp_Table1[0];
+		}
+		else 
+		{
+			for(int i=0;i<23-1;i++)
+			{
+				if ((R_value<=R_Table1[i])&&(R_value>R_Table1[i+1]))//中间判断
+				{
+					return Temp_Table1[i];
+				}
+				else
+				{
+					continue;
+				} 
+				
+			}
+		}
+	}//R-1
+	else
+	{
+		if(R_value<=R_Table2[216])//判断是否超出表尾
+		{
+			return Temp_Table2[216];
+		}
+		else if(R_value>=R_Table2[0])//判断是否超出表头
+		{
+			return Temp_Table2[0];
+		}
+		else 
+		{
+			for(int i=0;i<217-1;i++)
+			{
+				if ((R_value<R_Table2[i])&&(R_value>=R_Table2[i+1]))//中间判断
+				{
+					return Temp_Table2[i+1];
+				}
+				else
+				{
+					continue;
+				} 
+				
+			}
+		}
+	}//R-2
+}
+
+UINT16 GetErrorNum(UINT16 *ErrorArray,UINT8 Errorlen)
+{
+	UINT16 OutNum;
+	OutNum = *(ErrorArray);
+	for(int i=0;i<Errorlen-1;i++)
+	{
+		*(ErrorArray+i) = *(ErrorArray+i+1);
+		if(*(ErrorArray+i+1)==0)
+			break;
+	}
+	return OutNum;
+}
+UINT8 PutErrorNum(UINT16 *ErrorArray,UINT8 Errorlen,UINT16 ErrorNum)
+{
+	for(int i=0;i<Errorlen;i++)
+	{
+		if(*(ErrorArray+i)==0)
+		{
+			*(ErrorArray+i) = ErrorNum;
+			return 0;
+		}
+		else
+		{
+			if(*(ErrorArray+i)==ErrorNum)
+			{
+				return 1;
+			}
+			else
+			{
+				continue;
+			}
+		}
+	}
+	return 2;
+}

+ 20 - 46
src/Signal.c → src/AppSignal.c

@@ -1,18 +1,19 @@
 /****************************************************************************
  *
  * Copy right:   2021-, Copyrigths of RLWL Ltd.
- * File name:    Signal.c
- * Description:  Global variable definition c file
+ * File name:    AppSignal.c
+ * Description:  Global variable definition c file,此文件存放App使用到的全局变量
  * History:      Rev3.0   2021-07-06
  *
  ****************************************************************************/
 
-#include "Signal.h"
-//declear the bool vars
+#include "AppSignal.h"
+//
+/**declear the bool vars**/
 volatile BOOL NB_Fota_update_flag = FALSE;
 volatile BOOL BMS_Fota_update_flag = FALSE;
 
-//declear the UINT8 vars
+/**declear the uint8 vars**/
 UINT8	battCellTemp[8] = {0xFF};       //Battery temperature 电池温度数值
 UINT8	MOSTemp = 0xFF;                 //mos temprature mos温度
 UINT8	packTemp = 0xFF;                //battery pack temprature   电池箱体温度
@@ -41,11 +42,12 @@ UINT8	reservedSignal7 = 0xFF;         //can信息保留信号7
 UINT8	reservedSignal8 = 0xFF;         //can信息保留信号8
 
 UINT8   Lockstatus = 0;             //Interlock status 高压互锁状态
-UINT8   TcpErrorcount=0;              //Error count TCP联网错误计数
+UINT8   TcpErrorcount=0;            //Error count TCP联网错误计数
 UINT8 	TcpSendLen = 0;             //Tcp send status Tcp发送状态
 UINT8   CanMsgEnble = 0;            //Can send status Can中断状态
-UINT8 	UDSSwitch = 0;
-//declear the UINT16 vars
+UINT8 	UDSSwitch = 0;              //下线检测标志位
+UINT8 	PosFlag = 0;                //定位信息是否有效标志位
+/**declear the uint16 vars**/
 UINT16	battCellU[28] = {0xFFFF};    //电池包单体电压
 UINT16	minCellVol = 0xFFFF;    //最小单体电压
 UINT16	maxCellVol = 0xFFFF;    //最大单体电压
@@ -56,7 +58,7 @@ UINT16  ErrorNum[5]={0};        //Error array,故障数组
 
 
 
-//declear the UINT32 vars
+/**declear the uint32 vars**/
 UINT32	battWarningState = 0xFFFFFFFF;  //电池告警状态
 UINT32	nbSwVersion = 0xFFFFFFFF;       // 数据模块软件状态
 UINT32	battBalanceoInfo = 0xFFFFFFFF;  //电池均衡状态
@@ -64,45 +66,17 @@ UINT32  Battdesigncap =0xFFFFFFFF;      //battery design cap 电池包设计容
 UINT32  TimeCounter = 0x00;             //主任务定时器计数
 
 
-//declear other vars
+/**declear the Handle vars**/
 osMutexId_t Error_Mutex = NULL;         //故障互锁句柄
 
 
 
-//declear struct vars   结构体变量定义
-
-AppNVMDataType      AppNVMData;
-
-AppDataBody         AppDataInfo;
-
-UINT16	COMOutTable[28]	=	{
-0x6A0,
-0x6A1,
-0x6A2,
-0x6A3,
-0x6A4,
-0x6A5,
-0x6A6,
-0x6B0,
-0x6BA,
-0x6C0,
-0x6C1,
-0x6C2,
-0x6C3,
-0x6C4,
-0x7C0,
-0x7C1,
-0x7C2,
-0x7C3,
-0x7C4,
-0x7C5,
-0x7C6,
-0x7C7,
-0x7C8,
-0x7C9,
-0x7CA,
-0x7CB,
-0x7CC,
-0x7CD
-};
+/**declear other vars**/   
+
+AppConfigDataType      AppNVMData;
+
+AppDataBody             AppDataInfo;
+
+AppSocketConnectionContext socContext;  //网络连接状态
+
 

+ 273 - 0
src/AppTaskCan.c

@@ -0,0 +1,273 @@
+#include "bsp.h"
+#include "bsp_custom.h"
+#include "osasys.h"
+#include "ostask.h"
+#include "queue.h"
+#include "ps_event_callback.h"
+#include "cmisim.h"
+#include "cmimm.h"
+#include "cmips.h"
+#include "sockets.h"
+#include "psifevent.h"
+#include "ps_lib_api.h"
+#include "lwip/netdb.h"
+#include <cis_def.h>
+#include "debug_log.h"
+#include "slpman_ec616.h"
+#include "plat_config.h"
+#include "ec_tcpip_api.h"
+#include "hal_module_adapter.h"
+#include "UartTask.h"
+#include "MainTask.h"
+#include "app.h"
+#include "CANTask.h"
+#include "UDSService.h"
+#include "signal.h"
+
+extern UINT32 Timer_count;
+extern volatile BOOL Sleep_flag;
+
+CAN_Msg_Type CanRxMsg[2];
+/*线程声明*/
+#define 			PROC_CAN_RX_TASK_STACK_SIZE			(1024)
+static StaticTask_t gProcess_Can_Rx_Task_t;
+static UINT8 		gProcess_Can_Rx_TaskStack[PROC_CAN_RX_TASK_STACK_SIZE];
+
+
+static process_CAN	gProcess_CAN_Task = PROCESS_CAN_STATE_IDLE;
+#define 			PROC_CAN_STATE_SWITCH(a)  (gProcess_CAN_Task = a)
+volatile bool 		CAN_Sleep_State = false;
+UINT8 				CanSendSlpHandler	= 0xfd;
+
+extern updateBMSStatus MS_BMS_Update_Service();
+
+
+void CANTaskInit(void* arg)
+{
+    osThreadAttr_t task_rx_attr,task_tx_attr;
+    Can_InitType param;
+    param.baudrate = CAN_250Kbps;
+	param.mode = REQOP_NORMAL;	
+	param.packType = STD_PACK;
+	
+    memset(&task_rx_attr,0,sizeof(task_rx_attr));
+    memset(gProcess_Can_Rx_TaskStack, 0, PROC_CAN_RX_TASK_STACK_SIZE);
+    task_rx_attr.name = "Can_Task";
+    task_rx_attr.stack_mem = gProcess_Can_Rx_TaskStack;
+    task_rx_attr.stack_size = PROC_CAN_RX_TASK_STACK_SIZE;
+    task_rx_attr.priority = osPriorityBelowNormal7;
+    task_rx_attr.cb_mem = &gProcess_Can_Rx_Task_t;
+    task_rx_attr.cb_size = sizeof(StaticTask_t);
+	
+    HAL_Can_Init(param);
+    osDelay(1000);
+    osThreadNew(Can_Receive, NULL, &task_rx_attr);
+}
+
+
+static void Can_Receive()
+{    
+	slpManSlpState_t State;
+    uint8_t udsFlag,msgFlag=0;
+	UINT8 i = 0;
+	UINT16 delayconuter = 0;
+	CAN_Sleep_State = false;
+    while(true)
+    {
+		memset(CanRxMsg, 0, sizeof(CanRxMsg));    		
+		switch(gProcess_CAN_Task)
+		{
+			case PROCESS_CAN_STATE_IDLE:
+				osDelay(2000);
+				PROC_CAN_STATE_SWITCH(PROCESS_CAN_STATE_WORK);
+				break;				
+			
+			case PROCESS_CAN_STATE_WORK:
+				
+				if(Sleep_flag)
+				{
+					PROC_CAN_STATE_SWITCH(PROCESS_CAN_STATE_SLEEP);
+				}
+				if(HAL_Can_Receive(CanRxMsg)>0)					
+				{
+					delayconuter=0;						
+					for(i=0; i<2; i++)
+					{								
+						if(CanRxMsg[i].Id == 0x7A0)
+						{	
+							udsFlag = 1;
+							UDSService[i] =  CanRxMsg[i].Data[0];
+							UDSSubService[i] = CanRxMsg[i].Data[1];
+							UDSSubServiceActionCode[i] = CanRxMsg[i].Data[2];
+							if(UDSService[i] == 0x10)
+							{
+								if(UDSSubService[i] == 0x02)
+								{
+									UDSSwitch = 1;
+								}								
+							}
+						}
+						else if(CanRxMsg[i].Id == 0x7A1)
+						{
+							if(CanRxMsg[i].Data[0] != 0x00)
+							{
+								msgFlag = 1;	
+							}
+							else
+							{
+								msgFlag = 0;
+							}
+						}
+					}	
+					if(udsFlag==1)
+					{	
+						UDS_Service();
+						udsFlag = 0;
+					}
+					else if(msgFlag == 1)
+					{
+						CanMsgTx1000ms();							
+					}				
+				}
+				else
+				{
+					delayconuter++;
+					osDelay(10);
+					if(delayconuter>=0xfffe)
+					{
+						delayconuter=0;
+					}
+				}
+				if(delayconuter>100)
+				{
+					delayconuter=0;
+					PROC_CAN_STATE_SWITCH(PROCESS_CAN_STATE_IDLE);
+				}
+				break;
+				
+	        case PROCESS_CAN_STATE_SLEEP:
+	        {	            
+	            HAL_Can_Sleep();	 
+	            
+	            CAN_Sleep_State = true;
+	            while(true)
+	            {
+	                osDelay(60000/portTICK_PERIOD_MS);
+	            }
+				osThreadExit();	            
+	            break;
+	       }
+	   }
+	   //osDelay(50);
+	}      
+}
+
+
+void CanMsgTx1000ms()
+{
+	UINT16	COMOutTable[28]	=	{0x6A0,0x6A1,0x6A2,0x6A3,0x6A4,0x6A5,0x6A6,0x6B0,0x6BA,0x6C0,0x6C1,0x6C2,0x6C3,0x6C4,0x7C0,0x7C1,0x7C2,0x7C3,0x7C4,0x7C5,0x7C6,0x7C7,0x7C8,0x7C9,0x7CA,0x7CB,0x7CC,0x7CD};
+	static UINT32 timerRecord = 0;
+	UINT8 count = 0;
+	CAN_Msg_Type canMsg;
+	
+	if(Timer_count - timerRecord > 0)
+	{
+		timerRecord = Timer_count;
+		count = Timer_count%10;
+		switch (count)
+		{
+			case 0:  //send cell batt info 0x6A0、0x6A1	
+				canMsg.DLC = 8;
+				canMsg.Id = COMOutTable[count*2];
+				CANEncodeFunction( COMOutTable[count*2],  canMsg.Data);
+				HAL_Can_Transmit(canMsg);
+
+				canMsg.DLC = 8;
+				canMsg.Id = COMOutTable[count*2+1];
+				CANEncodeFunction( COMOutTable[count*2+1], canMsg.Data);
+				HAL_Can_Transmit(canMsg);
+				
+				break;
+
+			case 1:  //send cell batt info 0x6A2、0x6A3
+				canMsg.DLC = 8;
+				canMsg.Id = COMOutTable[count*2];
+				CANEncodeFunction( COMOutTable[count*2], canMsg.Data);
+				HAL_Can_Transmit(canMsg);
+
+				canMsg.DLC = 8;
+				canMsg.Id = COMOutTable[count*2+1];
+				CANEncodeFunction( COMOutTable[count*2+1], canMsg.Data);
+				HAL_Can_Transmit(canMsg);
+				break;
+
+			case 2: //send cell batt info 0x6A4、 0x6A5
+				canMsg.DLC = 8;
+				canMsg.Id = COMOutTable[count*2];
+				CANEncodeFunction( COMOutTable[count*2], canMsg.Data);
+				HAL_Can_Transmit(canMsg);
+
+				canMsg.DLC = 8;
+				canMsg.Id = COMOutTable[count*2+1];
+				CANEncodeFunction( COMOutTable[count*2+1], canMsg.Data);
+				HAL_Can_Transmit(canMsg);
+				break;
+			
+			case 3:	//send cell batt info 0x6A6、0x6B0
+				canMsg.DLC = 8;
+				canMsg.Id = COMOutTable[count*2];
+				CANEncodeFunction( COMOutTable[count*2], canMsg.Data);
+				HAL_Can_Transmit(canMsg);
+
+				canMsg.DLC = 8;
+				canMsg.Id = COMOutTable[count*2+1];
+				CANEncodeFunction( COMOutTable[count*2+1], canMsg.Data);
+				HAL_Can_Transmit(canMsg);
+				
+				break;
+			
+			case 4: //send batt temp info 0x6BA、0x6C0
+				canMsg.DLC = 8;
+				canMsg.Id = COMOutTable[count*2];
+				CANEncodeFunction( COMOutTable[count*2], canMsg.Data);
+				HAL_Can_Transmit(canMsg);
+
+				canMsg.DLC = 8;
+				canMsg.Id = COMOutTable[count*2+1];
+				CANEncodeFunction( COMOutTable[count*2+1], canMsg.Data);
+				HAL_Can_Transmit(canMsg);
+			break;
+			
+			case 5: //send batt other info 0x6C1、0x6C2
+				canMsg.DLC = 8;
+				canMsg.Id = COMOutTable[count*2];
+				CANEncodeFunction( COMOutTable[count*2],  canMsg.Data);
+				HAL_Can_Transmit(canMsg);
+
+				canMsg.DLC = 8;
+				canMsg.Id = COMOutTable[count*2+1];
+				CANEncodeFunction( COMOutTable[count*2+1], canMsg.Data);
+				HAL_Can_Transmit(canMsg);
+			break;
+
+			case 6:	//send batt other info 0x6C3、0x6C4
+				canMsg.DLC = 8;
+				canMsg.Id = COMOutTable[count*2];
+				CANEncodeFunction( COMOutTable[count*2],  canMsg.Data);
+				HAL_Can_Transmit(canMsg);
+
+				canMsg.DLC = 8;
+				canMsg.Id = COMOutTable[count*2+1];
+				CANEncodeFunction( COMOutTable[count*2+1], canMsg.Data);
+				HAL_Can_Transmit(canMsg);
+			break;
+			
+			default:
+			break;
+			
+		}
+	}
+}
+
+
+

+ 209 - 0
src/AppTaskGps.c

@@ -0,0 +1,209 @@
+/****************************************************************************
+ *
+ * Copy right:   Qx.Chen jie
+ * File name:    GpsTask.c
+ * Description:  Gps处理任务
+ * History:      2021-03-07
+ *
+ ****************************************************************************/
+#include "bsp.h"
+#include "bsp_custom.h"
+#include "osasys.h"
+#include "ostask.h"
+#include "queue.h"
+#include "ps_event_callback.h"
+#include "app.h"
+#include "cmisim.h"
+#include "cmimm.h"
+#include "cmips.h"
+#include "sockets.h"
+#include "psifevent.h"
+#include "ps_lib_api.h"
+#include "lwip/netdb.h"
+#include "debug_log.h"
+#include "slpman_ec616.h"
+#include "plat_config.h"
+#include "ec_tcpip_api.h"
+#include "app.h"
+#include "MainTask.h"
+#include "GpsTask.h"
+#include "TcpTask.h"
+//全局变量区输入
+extern volatile BOOL Sleep_flag; 
+extern AppDataBody AppDataInfo;
+extern UINT8 WorkFlag;
+//全局变量区输出
+UINT8 GpsData[20];
+osMutexId_t GpsMutex = NULL;
+//线程定义区
+#define GPS_TASK_STACK_SIZE   								 (512)
+static QueueHandle_t norGpsHandle = NULL;
+static osThreadId_t gpsTaskHandle = NULL;
+static StaticTask_t gpsTask = NULL;
+static UINT8 gpsTaskStack[GPS_TASK_STACK_SIZE];
+
+//函数声明区
+void strdel(char * str,char c);
+UINT32 location_handle(char *in1);
+
+static void GpsTask(void* arg)
+{
+    gpsReqMsg msg;
+	char *p=NULL;
+	const char *delim = "\n";
+	char *databuffer[14];
+    UINT32 speedtemp;
+    UINT32 latitude;
+	UINT32 longitude;
+    UINT16 direction;
+    posGGAServiceStart(norGpsHandle);
+    posGGAReset();
+    if(GpsMutex == NULL)
+    {
+        GpsMutex = osMutexNew(NULL);
+    }
+    while(1)
+    {
+        //char temp[] = "$GNRMC,082626.000,A,2939.91801,N,10637.09500,E,0.543,30.254,261120,,,A,V*17";
+        osStatus_t ret = osMessageQueueGet(norGpsHandle, &msg, 0, osWaitForever);
+        if(ret==0)
+        {
+            if (msg.dataPtr)
+            {	
+                osStatus_t result = osMutexAcquire(GpsMutex, osWaitForever);//Gps数据锁	
+                p = strtok(msg.dataPtr,delim);//将信息进行分割
+                #ifdef USING_PRINTF1
+                    printf("\nP msgptr data:%s\r\n",p);
+                #endif
+                p = strtok(p,",");//只取第1行的信息RMC
+                //p = strtok(temp,",");//模拟测试
+                if (strcmp(p,"$GNRMC")==0)
+                {
+                    UINT8 i=0;			
+                    while (p)
+                    {	
+                        databuffer[i]=p;
+                        p = strtok(NULL,",");
+                        i++;;
+                    }
+                    if (strcmp(databuffer[1],"V")==0|strcmp(databuffer[2],"V")==0)
+                    {
+                        memset(GpsData,0x00,sizeof(GpsData));
+                    }
+                    else if (strcmp(databuffer[2],"A")==0)
+                    {
+                        GpsData[0] = 0x01;//有效,东经,北纬写定
+                        GpsData[1] = 03;//卫星数目写入1
+                        strdel(databuffer[3],'.');
+                        strdel(databuffer[5],'.');
+                        strdel(databuffer[7],'.');
+                        speedtemp = atol(databuffer[7])*1852/1e5;//节换算单位,1节=1.852km每小时
+                        GpsData[4] = (speedtemp>>8)&0xFF;
+                        GpsData[5] = speedtemp&0xFF; 
+                        latitude =location_handle(databuffer[3]);
+                        GpsData[8] = latitude>> 24;
+                        GpsData[9] = latitude>> 16;
+                        GpsData[10] = latitude>> 8;
+                        GpsData[11] = latitude;
+                        longitude = location_handle(databuffer[5]);
+                        GpsData[12] = longitude>>24;
+                        GpsData[13] = longitude>>16;
+                        GpsData[14] = longitude>>8;
+                        GpsData[15] = longitude;
+
+                        GpsData[6] = 0x03;
+                        GpsData[7] = 0xE8;
+                        if(speedtemp>=50)//大于5km/h才输出方位
+                        {
+                            direction = atol(databuffer[8]);
+                            GpsData[2] = direction>>8;
+                            GpsData[3] = direction;
+                        }
+                        else
+                        {
+                            GpsData[2] = 0xff;
+                            GpsData[3] = 0xfe;
+                        }
+                        if(speedtemp>=30 && speedtemp<=1500 && WorkFlag==0x01)
+                        {
+                            AppDataInfo.appDataModify = true;
+                            AppDataInfo.AccMileage = speedtemp/36 + AppDataInfo.AccMileage;
+                            if(AppDataInfo.AccMileage>=0xfffffffe)
+                            {
+                                AppDataInfo.AccMileage = 0;
+                            }
+
+                        }
+                        GpsData[16] = AppDataInfo.AccMileage>>24;
+                        GpsData[17] = AppDataInfo.AccMileage>>16;
+                        GpsData[18] = AppDataInfo.AccMileage>>8;
+                        GpsData[19] = AppDataInfo.AccMileage;
+                    }
+                }
+                osMutexRelease(GpsMutex);
+            }
+            if(msg.dataPtr)
+                free(msg.dataPtr);
+            msg.dataPtr=NULL;
+        }
+        if (Sleep_flag)
+		{
+            posGGAServiceStop();
+			osThreadExit();
+			break;
+		}
+    }
+}
+INT32 GpsTaskInit(void)
+{
+
+	if(norGpsHandle == NULL)
+	{
+		norGpsHandle = osMessageQueueNew(1,sizeof(gpsReqMsg), NULL);
+		if(norGpsHandle == NULL)
+			return 1;
+	}
+	if(gpsTaskHandle == NULL)
+	{
+		osThreadAttr_t task_attr;
+		memset(&task_attr , 0 , sizeof(task_attr));
+		task_attr.name = "GPS";
+		task_attr.priority = osPriorityBelowNormal6;
+		task_attr.cb_mem = &gpsTask;
+		task_attr.cb_size = sizeof(StaticTask_t);
+		task_attr.stack_mem = gpsTaskStack;
+		task_attr.stack_size =GPS_TASK_STACK_SIZE;
+		memset(& gpsTaskStack, 0xa5, GPS_TASK_STACK_SIZE);
+		gpsTaskHandle = osThreadNew(GpsTask , NULL,&task_attr);
+		if(gpsTaskHandle == NULL)
+			return 1;
+	}
+	
+	return 0;
+}
+/*----------------------------------------*/
+// 字符串删除函数
+void strdel(char * str,char c)
+{
+	char *p = str;
+	while(*str)
+	{
+		if(*str!=c)
+			*p++ = *str;
+		str++;
+	}
+	*p = '\0';
+}
+UINT32 location_handle(char *in1)
+{
+	UINT32 location_temp;
+	UINT32 location_degree;
+	UINT32 location_min;
+	location_temp = atol(in1);
+	location_degree = location_temp/(1e7);
+	location_degree = location_degree*(1e6);
+	location_min = location_temp-location_degree*10;
+	location_min = location_min/6;
+	location_temp = location_degree+location_min;
+	return location_temp;
+}

+ 48 - 0
src/AppTaskLed.c

@@ -0,0 +1,48 @@
+/****************************************************************************
+ *
+ * Copy right:   Qx.Chen jie
+ * File name:    LedTask.c
+ * Description:  主要负责:Led闪烁逻辑
+ * History:      2021-07-05
+ * Version:      V3.0
+ ****************************************************************************/
+#include "LedTask.h"
+
+//局部变量申请
+static StaticTask_t                 gProcess_Led_Task_t;
+static UINT8                        gProcess_Led_TaskStack[PROC_LED_TASK_STACK_SIZE];
+static osThreadId_t                 LedTaskId = NULL;
+static process_LED 		            gProcess_Led_Task = PROCESS_LED_STATE_IDLE;
+#define PROC_LED_STATE_SWITCH(a)    (gProcess_Led_Task = a)
+
+//函数声明区
+
+//线程任务区
+static void LedTask(void* arg)
+{
+    osDelay(5000);//等待驻网延时5s
+    while (true)
+    {
+        osDelay(100);
+    }//while 循环
+}
+//Tcp线程初始化
+void LedTaskInit(void *arg)
+{
+    osThreadAttr_t task_attr;
+    //registerPSEventCallback(NB_GROUP_ALL_MASK, socketRegisterPSUrcCallback);
+    memset(&task_attr,0,sizeof(task_attr));
+    memset(gProcess_Led_TaskStack, 0xA5, PROC_LED_TASK_STACK_SIZE);
+    task_attr.name = "Led_Task";
+    task_attr.stack_mem = gProcess_Led_TaskStack;
+    task_attr.stack_size = PROC_LED_TASK_STACK_SIZE;
+    task_attr.priority = osPriorityBelowNormal;
+    task_attr.cb_mem = &gProcess_Led_Task_t;
+    task_attr.cb_size = sizeof(StaticTask_t);
+    LedTaskId = osThreadNew(LedTask, NULL, &task_attr);
+}
+void LedTaskDeInit(void *arg)
+{
+    osThreadTerminate(LedTaskId);
+    LedTaskId = NULL;
+}

+ 10 - 63
src/MainTask.c → src/AppTaskMain.c

@@ -1,8 +1,8 @@
 /****************************************************************************
  *
- * Copy right:   Qx.
+ * Copy right:   Qx.CJ
  * File name:    MainTask.c
- * Description:  APP任务调取和异常处理
+ * Description:  主要负责:1.工作模式转换2.定时器定时3.定时保存运行数据4.异常状态重启
  * History:      2021-07-05
  * Version:      V3.0
  ****************************************************************************/
@@ -66,53 +66,9 @@ static void MainTask(void* arg)
     #ifdef DEBUGLOG
     Debug_printf("Wkp-%d \n",Wakeup_source);
     #endif
-	appGetNVMSavedData();
-    LoadAppDataInfo();
-    
-    #ifdef USING_PRINTF1
-    UINT8 *pReadAppConfig;
-    UINT32 readCount;
-    //AppConfigHeader    AppConfigHr;
-    OSAFILE file;
-    file = OsaFopen(APP_CONFIG_FILE_NAME,"rb");
-    OsaFseek(file, 0, SEEK_SET);
-    pReadAppConfig  = OsaAllocZeroMemory(AppConfigHr.fileBodySize+4);    
-    readCount = OsaFread(pReadAppConfig, AppConfigHr.fileBodySize+4, 1, file);
-    printf("AppConfigHr.fileBodySize+4 = %d\n",AppConfigHr.fileBodySize+4);
-    printf("readCount = %d\n",readCount);
-    printf("the config data = \n");
-    for (int i ;i<AppConfigHr.fileBodySize+4;i++)
-        printf("%d ",*(pReadAppConfig+i));
-    printf("\n");
-    #endif
-    #ifdef USING_PRINTF1
-    UINT8 *pReadAppData;
-    UINT32 readCount;
-    //AppConfigHeader    AppConfigHr;
-    OSAFILE file;
-    file = OsaFopen(APP_DATAINFO_FILE_NAME,"rb");
-    OsaFseek(file, 0, SEEK_SET);
-    pReadAppData  = OsaAllocZeroMemory(AppDataHr.fileBodySize+3);    
-    readCount = OsaFread(pReadAppData, AppDataHr.fileBodySize+3, 1, file);
-    printf("AppDataHr.fileBodySize+3 = %d\n",AppDataHr.fileBodySize+3);
-    printf("readCount = %d\n",readCount);
-    printf("the data = ");
-    for (int i=0 ;i<AppDataHr.fileBodySize+3;i++)
-        printf("%x(%d) ",*(pReadAppData+i),i);
-    printf("\n");
-    #endif
-    if(AppNVMData.AppSwVersion!=APPSWVERSION)
-    {
-        AppNVMData.HwVersion = HWVERSION;
-        AppNVMData.BLSwVersion = BLSWVERSION;
-        AppNVMData.DrvSwVersion = DRVSWVERSION;
-        AppNVMData.AppSwVersion = APPSWVERSION;
-        AppNVMData.appDataModify = TRUE;
-    }
+
     montior_timer = xTimerCreate("montior_timer", 100 / portTICK_RATE_MS, pdTRUE, NULL, montior_timer_callback);
     work_timer = xTimerCreate("work_timer", AppNVMData.wakeupWorkTime*60*1000 / portTICK_RATE_MS, pdTRUE, NULL, work_timer_callback);
-
-	
 	NetSocDisplay(LED_SOC_0,LED_TURN_OFF);
 	NetSocDisplay(LED_SOC_1,LED_TURN_OFF);
 	NetSocDisplay(LED_SOC_2,LED_TURN_OFF);
@@ -125,6 +81,8 @@ static void MainTask(void* arg)
         {
             case PROCESS_STATE_IDLE:
             {
+                appGetNVMSavedData();
+                LoadAppDataInfo();
                 TimeCounter = 0;
                 xTimerStart(montior_timer, 0);
                 xTimerStart(work_timer, 0);
@@ -133,7 +91,7 @@ static void MainTask(void* arg)
             }
             case PROCESS_STATE_WORK:
             {
-
+                /***if Tcp connect error 5 times then save data and restart sys***/
                 if(TcpErrorcount>=5)
                 {
                     AppDataInfo.appDataModify = true;
@@ -142,33 +100,22 @@ static void MainTask(void* arg)
                     {
                         AppDataInfo.SysReStart = 0;
                     }
-                    if(AppNVMData.appDataModify)
-                    {
-                        appSaveNVMData();
-                    }
-                    if(AppDataInfo.appDataModify)
-                    {
-                        appSaveDataInfo();
-                    }
+                    appSaveNVMData();
+                    appSaveDataInfo();
                     appSetCFUN(0);
                     osDelay(1000);
                     EC_SystemReset();
                 }
+                
                 osDelay(1000);
                 break;
             }
             case PROCESS_STATE_SLEEP:
             {
-                if(AppNVMData.appDataModify)
+                if(NB_Fota_update_flag)
                 {
                     appSaveNVMData();
-                }
-                if(AppDataInfo.appDataModify)
-                {
                     appSaveDataInfo();
-                }
-                if(NB_Fota_update_flag)
-                {
                     appSetCFUN(0);
                     osDelay(1000);
                     EC_SystemReset();

+ 54 - 0
src/AppTaskTcp.c

@@ -0,0 +1,54 @@
+/****************************************************************************
+ *
+ * Copy right:   Qx.Chen jie
+ * File name:    TcpTask.c
+ * Description:  主要负责:1.数据发送、定时心跳上报,2.数据接收、命令接收及处理,3.Fota函数调用,4.驻网及失败状态监测与上报
+ * History:      2021-07-05
+ * Version:      V3.0
+ ****************************************************************************/
+#include "TcpTask.h"
+
+//局部变量申请
+static StaticTask_t                 gProcess_Tcp_Task_t;
+static UINT8                        gProcess_Tcp_TaskStack[PROC_TCP_TASK_STACK_SIZE];
+static QueueHandle_t                psEventQueueHandle;//状态转换队列句柄
+static osThreadId_t                 TcpTaskId = NULL;
+static process_TCP 		            gProcess_Tcp_Task = PROCESS_TCP_STATE_IDLE;
+#define PROC_TCP_STATE_SWITCH(a)    (gProcess_Tcp_Task = a)
+static eventCallbackMessage_t       *queueItem = NULL;
+static UINT8                         gImsi[16] = {0};
+static UINT32                        gCellID = 0;
+static QueueHandle_t                 TcpRecvHandle = NULL;
+static UINT8                         TcpRecvEnd = 0;
+
+//函数声明区
+
+//线程任务区
+static void TcpTask(void* arg)
+{
+    osDelay(5000);//等待驻网延时5s
+    while (true)
+    {
+        osDelay(100);
+    }//while 循环
+}
+//Tcp线程初始化
+void TcpTaskInit(void *arg)
+{
+    osThreadAttr_t task_attr;
+    //registerPSEventCallback(NB_GROUP_ALL_MASK, socketRegisterPSUrcCallback);
+    memset(&task_attr,0,sizeof(task_attr));
+    memset(gProcess_Tcp_TaskStack, 0xA5, PROC_TCP_TASK_STACK_SIZE);
+    task_attr.name = "Tcp_Task";
+    task_attr.stack_mem = gProcess_Tcp_TaskStack;
+    task_attr.stack_size = PROC_TCP_TASK_STACK_SIZE;
+    task_attr.priority = osPriorityBelowNormal7;
+    task_attr.cb_mem = &gProcess_Tcp_Task_t;
+    task_attr.cb_size = sizeof(StaticTask_t);
+    TcpTaskId = osThreadNew(TcpTask, NULL, &task_attr);
+}
+void TcpTaskDeInit(void *arg)
+{
+    osThreadTerminate(TcpTaskId);
+    TcpTaskId = NULL;
+}

+ 2919 - 0
src/AppTaskUart.c

@@ -0,0 +1,2919 @@
+/****************************************************************************
+ *
+ * Copy right:   Qx.
+ * File name:    UartTask.c
+ * Description:  串口任务
+ * History:      2021-03-05
+ *
+ * 2021-04-11:可以通过Ota线路升级Bms保护板
+ ****************************************************************************/
+#include "bsp.h"
+#include "bsp_custom.h"
+#include "osasys.h"
+#include "ostask.h"
+#include "queue.h"
+#include "ps_event_callback.h"
+#include "cmisim.h"
+#include "cmimm.h"
+#include "cmips.h"
+#include "sockets.h"
+#include "psifevent.h"
+#include "ps_lib_api.h"
+#include "lwip/netdb.h"
+//#include <cis_def.h>
+#include "debug_log.h"
+#include "slpman_ec616.h"
+#include "plat_config.h"
+#include "ec_tcpip_api.h"
+#include "hal_module_adapter.h"
+#include "UartTask.h"
+#include "MainTask.h"
+#include <stdlib.h>
+#include "app.h"
+#include "numeric.h"
+#include "Fota.h"
+#include "signal.h"
+//全局变量输入区
+extern UINT32 Timer_count;
+extern volatile BOOL Sleep_flag; 
+extern AppNVMDataType AppNVMData;
+extern AppDataBody AppDataInfo;
+extern UINT8 WorkFlag;
+//全局变量输出区
+BOOL UartBattInfoRecvFlag  = false;
+QueueHandle_t UartWriteCmdHandle = NULL;
+UINT8 BattChrgEndFlag;
+
+
+
+//
+
+extern ARM_DRIVER_USART Driver_USART1;
+static ARM_DRIVER_USART *USARTdrv = &Driver_USART1;
+volatile bool isRecvTimeout = false;
+volatile bool isRecvComplete = false;
+
+//线程声明区
+static StaticTask_t             gProcess_Uart_Task_t;
+static UINT8                  gProcess_Uart_TaskStack[PROC_UART_TASK_STACK_SIZE];
+static osThreadId_t           UartTaskId = NULL;
+static process_Uart             gProcess_Uart_Task = PROCESS_UART_STATE_IDLE;
+#define PROC_UART_STATE_SWITCH(a)  (gProcess_Uart_Task = a)
+
+//函数声明区
+void USART_callback(uint32_t event);
+UINT8 Uart_DataRecv_func(Uart_Read_Msg_Type Uart_Read_Msg_Fun,UINT8* Uart_Recv_Buffer_Fun);
+static BOOL uartBattInfoDecode(UINT8* dataPtr);
+UINT8 Uart_WriteCmd_func(Uart_Write_Data_Type UartWriteData);
+UINT16 crc_chk(UINT8* data, UINT8 length);
+void battSOCDisplay(void);
+void battErrorStateDisplay(void);
+void battWarningStateDisplay(void);
+void battLockStateDisplay(UINT8 lockState);
+void relayPWMControl(void);
+void SP_BMS_Update_Service(void);
+BOOL BattHeaterSwitch(UINT8* heaterSwitch);
+UINT16  encryptionAlgorithm (UINT16 plainText);
+UINT8  decryptionAlgorithm (UINT16 cipherText);
+UINT8 Uart_Encrypt_Send(void);
+UINT8 BmsErrorDecode(UINT32 battWarningState);
+//BMS升级函数声明
+UINT8 SP_BMS_Update_CheckSUM(UINT8* pSendData,UINT8 len);
+void SP_BMS_Update_Service();
+UINT8 SP_BMS_Update_Query(UINT8* pSend,UINT32 sendLen, UINT8* pRead, UINT32 readLen, UINT32 timeout);
+
+updateBMSStatus MS_BMS_Update_Service();
+UINT16 MS_BMS_Update_CRC16(UINT8* pSendData,UINT16 len);
+UINT8 MS_BMS_Update_Query(UINT8* pSend,UINT32 sendLen, UINT8* pRead, UINT32 readLen, UINT32 timeout);
+//Uart线程任务区
+static void UartTask(void* arg)
+{
+    USARTdrv->Initialize(USART_callback);
+    USARTdrv->PowerControl(ARM_POWER_FULL);
+    USARTdrv->Control(ARM_USART_MODE_ASYNCHRONOUS |
+                      ARM_USART_DATA_BITS_8 |
+                      ARM_USART_PARITY_NONE |
+                      ARM_USART_STOP_BITS_1 |
+                      ARM_USART_FLOW_CONTROL_NONE, 9600);
+    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控制命令
+	memset(&(UartWriteData),0x00,sizeof(Uart_Write_Data_Type));
+    UartReadMsgType UartReadMsg;
+    memset(&(UartReadMsg.UartFlag),0x00,sizeof(UartReadMsgType));
+    if(UartWriteCmdHandle == NULL)//Uart控制命令传输指针
+	{
+		UartWriteCmdHandle = osMessageQueueNew(3,sizeof(Uart_Write_Data_Type), NULL);
+	}
+    //上电起始控制区域
+    while (1)
+    {
+        switch (gProcess_Uart_Task)
+        {
+			case PROCESS_UART_STATE_ENCRYPT:
+			{
+				UINT8 EncryptFlag=0x00;
+				UINT8 EncryptCount=0;
+				while(EncryptFlag!=0x01&&EncryptCount<=3)
+				{
+					EncryptFlag = Uart_Encrypt_Send();
+					EncryptCount++;
+				}
+				PROC_UART_STATE_SWITCH(PROCESS_UART_STATE_IDLE);
+				break;
+			}
+            case PROCESS_UART_STATE_IDLE:
+            {
+                osDelay(100);
+                if(Sleep_flag)
+                {
+                    PROC_UART_STATE_SWITCH(PROCESS_UART_STATE_SLEEP);
+                }
+                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)
+                    {
+                        #ifdef USING_PRINTF1
+                            printf("[%d]UartWriteCmdHandle :%x\n",__LINE__,UartWriteData.WriteCmd);
+                        #endif
+                        PROC_UART_STATE_SWITCH(PROCESS_UART_STATE_WRITE);
+                    }
+                    else
+                        PROC_UART_STATE_SWITCH(PROCESS_UART_STATE_READ);
+                }
+				if(UartReadMsg.Header[2]>0)
+				{
+					uartReadSuccessFlag = true;
+				}
+				else
+				{
+					uartReadSuccessFlag = false;
+				}
+				if(Timer_count-currentTimerCount >= 1)
+				{
+					if(AppNVMData.isBattLocked != 0)
+					{
+						battLockStateDisplay(TRUE);
+					}
+					else if(uartReadSuccessFlag)
+					{
+						battSOCDisplay();
+						battErrorStateDisplay();
+					}
+					else
+					{
+						battWarningStateDisplay();
+					}
+				}
+				currentTimerCount = Timer_count;
+				if(BMS_Fota_update_flag)
+				{
+					if(WorkFlag==0x00)
+					{
+						PROC_UART_STATE_SWITCH(PROCESS_UART_STATE_UPDATE);
+					}
+					
+				}
+				if(AppNVMData.isBattLocked==TRUE && ((UartReadMsg.data[(0x09+BATT_CELL_VOL_NUM+BATT_TEMP_NUM+2)*2+1])>>1)&0x03!=0x00 && Timer_count%10==0)//try to lock
+				{
+					UartWriteData.WriteCmd = 0x01;
+					UartWriteData.Data[0] = 0x00;
+					UartWriteData.Data[1] = 0x00;
+					osMessageQueuePut(UartWriteCmdHandle,&UartWriteData,0,1000);
+					PROC_UART_STATE_SWITCH(PROCESS_UART_STATE_READ);
+				}
+				else if (AppNVMData.isBattLocked==FALSE && ((UartReadMsg.data[(0x09+BATT_CELL_VOL_NUM+BATT_TEMP_NUM+2)*2+1])>>1)&0x03==0x00 && Timer_count%10==0 ) // try to unlock
+				{
+					UartWriteData.WriteCmd = 0x01;
+					UartWriteData.Data[0] = 0x00;
+					UartWriteData.Data[1] = 0x03;
+					osMessageQueuePut(UartWriteCmdHandle,&UartWriteData,0,1000);
+					PROC_UART_STATE_SWITCH(PROCESS_UART_STATE_READ);
+				}
+                break;
+            }
+            case PROCESS_UART_STATE_READ:
+            {
+                UINT16 CRC_chk_buffer;
+                Reg_Num = 0x21+BATT_CELL_VOL_NUM+BATT_TEMP_NUM + 2;//按照协议里面的0x21+X+N的结束地址
+                Uart_Read_Msg.Bms_Address = BMS_ADDRESS_CODE;
+                Uart_Read_Msg.Bms_Funcode = UART_READ_CODE;
+                Uart_Read_Msg.Reg_Begin_H = 0x00;
+                Uart_Read_Msg.Reg_Begin_L= 0x00;
+                Uart_Read_Msg.Reg_Num_H = Reg_Num>>8;
+                Uart_Read_Msg.Reg_Num_L = Reg_Num;
+                Uart_Uds_LEN = Reg_Num*2;
+                memset(UartReadMsg.Header,0x00,Uart_Uds_LEN);
+				CRC_chk_buffer = crc_chk((UINT8 *)&Uart_Read_Msg,6);
+				Uart_Read_Msg.CRC_L = CRC_chk_buffer;
+				Uart_Read_Msg.CRC_H = CRC_chk_buffer>>8;
+                //Uart_Recv_LEN = Uart_DataRecv_func((UINT8 *)&Uart_Read_Msg,(UINT8*)UartReadMsg.Header);
+				Uart_Recv_LEN = Uart_DataRecv_func(Uart_Read_Msg,(UINT8*)(UartReadMsg.Header));
+				if(Uart_Recv_LEN>0)
+				{
+					UartBattInfoRecvFlag =  TRUE;
+					uartBattInfoDecode(UartReadMsg.data);
+				}
+				else
+				{
+					UartBattInfoRecvFlag =  FALSE;
+				}
+                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("\nUart_Recv_buffer:  ");
+					for(int i=0;i<Uart_Recv_LEN;i++)
+					{
+						printf("%x ",*((UINT8 *)&UartReadMsg.Header+i));
+					}
+					printf("\n");
+				#endif
+                break;
+            }
+            case PROCESS_UART_STATE_WRITE:
+            {
+                Uart_WriteCmd_func(UartWriteData);
+                PROC_UART_STATE_SWITCH(PROCESS_UART_STATE_IDLE);
+                break;
+            }
+			case PROCESS_UART_STATE_UPDATE:
+				UartBattInfoRecvFlag =  FALSE;
+				#if  BMS_MANUFACTURE==1
+				{
+					SP_BMS_Update_Service();
+				}		
+				#elif BMS_MANUFACTURE==2
+					MS_BMS_Update_Service();
+				#endif
+
+				PROC_UART_STATE_SWITCH(PROCESS_UART_STATE_IDLE);
+				BMS_Fota_update_flag = FALSE;
+				break;
+            case PROCESS_UART_STATE_SLEEP:
+            {
+                USARTdrv->PowerControl(ARM_POWER_LOW);
+                while(TRUE)
+                {
+                    osDelay(60000/portTICK_PERIOD_MS);
+                }
+				osThreadExit();
+                break;
+            }
+
+        }
+    }
+}
+
+
+
+
+//Uart 接收的数据解码
+static BOOL uartBattInfoDecode(UINT8* dataPtr)
+{
+	//BattInfoType battInfo;
+	UINT8 i,temp=0;
+    UINT8 TEMP_NUM = BATT_TEMP_NUM + BATT_OTHER_TEMP_NUM;
+    UINT16 Batt_current;
+    for(i=0;i<BATT_CELL_VOL_NUM;i++)
+    {
+		battCellU[i] = (dataPtr[(0x02+i)*2] << 8) | dataPtr[(0x02+i)*2 + 1];
+    }
+    
+    battWorkState = (dataPtr[(0x03+BATT_CELL_VOL_NUM)*2+1])&0x03;//电池状态(原始数据),0表示静置,1表示放电,2表示充电
+    
+    for(i=0; i<BATT_TEMP_NUM; i++)
+    {
+	    battCellTemp[i] = dataPtr[(0x06+BATT_CELL_VOL_NUM+i)*2+1];
+    }
+    MOSTemp = dataPtr[(0x06+BATT_CELL_VOL_NUM+BATT_TEMP_NUM)*2+1];
+   	packTemp = dataPtr[(0x06+BATT_CELL_VOL_NUM+BATT_TEMP_NUM+1)*2+1];
+    
+    Batt_current = (dataPtr[(0x02+BATT_CELL_VOL_NUM)*2]<<8)|(dataPtr[(0x02+BATT_CELL_VOL_NUM)*2+1]);
+    //原始数据:充电为负,放电为正
+	if(battWorkState == 0x02) //充电过程
+	{
+		if(Batt_current >0x8000)// 数据为负
+		{			
+			//求补码,结果为负
+			Batt_current = (UINT16)((UINT16)(~(Batt_current))+1);
+        	Batt_current = Batt_current/10;
+			AppDataInfo.BattCurrentNegFlag = -1;
+		}
+		else
+		{
+			//源码,结果为负
+			Batt_current = Batt_current/10;
+			AppDataInfo.BattCurrentNegFlag = -1;
+		}
+	}
+	else //放电过程
+	{
+		if(Batt_current >0x8000)// 数据为负
+		{
+			//求补码,结果为正
+			Batt_current = (UINT16)((UINT16)(~(Batt_current))+1);
+        	Batt_current = Batt_current/10;
+			AppDataInfo.BattCurrentNegFlag = 1;
+		}
+		else
+		{
+			//源码,结果为正
+			Batt_current = Batt_current/10;
+			AppDataInfo.BattCurrentNegFlag = 1;
+		}
+	}
+
+	battI = Batt_current*AppDataInfo.BattCurrentNegFlag + 0x2710;
+    //bit0 ~ bit31 represent cell0 ~ cell31
+    battBalanceoInfo  = dataPtr[(0x06+BATT_CELL_VOL_NUM+TEMP_NUM)*2+1] | (dataPtr[(0x06+BATT_CELL_VOL_NUM+TEMP_NUM)*2] <<8) + (dataPtr[(0x07+BATT_CELL_VOL_NUM+TEMP_NUM)*2+1]<<16) | (dataPtr[(0x07+BATT_CELL_VOL_NUM+TEMP_NUM)*2] <<24);
+
+    bmsHwVersion = dataPtr[(0x08+BATT_CELL_VOL_NUM+TEMP_NUM)*2+1]; 
+    bmsSwVersion = dataPtr[(0x08+BATT_CELL_VOL_NUM+TEMP_NUM)*2];    
+
+    temp = ((dataPtr[(0x09+BATT_CELL_VOL_NUM+TEMP_NUM)*2+1])>>1)&0x03;    
+    battMOSSwitchState = ((temp&0x01)<<1)|((temp&0x02)>>1);	
+    if(AppNVMData.isBattLocked==TRUE)
+    {
+        battMOSSwitchState = battMOSSwitchState |(0x01<<2);
+    }
+    else
+    {
+        battMOSSwitchState = battMOSSwitchState |(0x00<<2);
+    }
+	battWarningState = (dataPtr[(0x09+BATT_CELL_VOL_NUM+TEMP_NUM)*2+0]<<16) | (dataPtr[(0x0A+BATT_CELL_VOL_NUM+TEMP_NUM)*2+0] << 8) |(dataPtr[(0x0A+BATT_CELL_VOL_NUM+TEMP_NUM)*2+1]);
+    battSOC = dataPtr[(0x0B+BATT_CELL_VOL_NUM+TEMP_NUM)*2+1];
+    battSOH = dataPtr[(0x0C+BATT_CELL_VOL_NUM+TEMP_NUM)*2+1];
+	Battdesigncap = (dataPtr[(0x0E+BATT_CELL_VOL_NUM+TEMP_NUM)*2])<<24|(dataPtr[(0x0E+BATT_CELL_VOL_NUM+TEMP_NUM)*2+1])<<16|(dataPtr[(0x0F+BATT_CELL_VOL_NUM+TEMP_NUM)*2])<<8|(dataPtr[(0x0F+BATT_CELL_VOL_NUM+TEMP_NUM)*2+1]);
+	battPackVol =((dataPtr[(0x18+BATT_CELL_VOL_NUM+TEMP_NUM)*2])<<8|(dataPtr[(0x18+BATT_CELL_VOL_NUM+TEMP_NUM)*2+1]))/10;  //uint 100mV
+	maxCellVol = (dataPtr[(0x19+BATT_CELL_VOL_NUM+TEMP_NUM)*2] << 8) | dataPtr[(0x19+BATT_CELL_VOL_NUM+TEMP_NUM)*2 + 1];
+	minCellVol = (dataPtr[(0x1A+BATT_CELL_VOL_NUM+TEMP_NUM)*2] << 8) | dataPtr[(0x1A+BATT_CELL_VOL_NUM+TEMP_NUM)*2 + 1];
+    battHeatEnableState = dataPtr[(0x1C+BATT_CELL_VOL_NUM+TEMP_NUM)*2+1]&0x01;
+
+	maxCellTemp = 0x00;
+	minCellTemp = 0xFF;
+	for(i=0;i<BATT_TEMP_NUM;i++)
+	{
+		maxCellTemp = max(maxCellTemp,battCellTemp[i]);
+		minCellTemp = min(minCellTemp,battCellTemp[i]);		
+	}
+	nbSwVersion = APPSWVERSION;
+	nbHwVersion = HWVERSION;
+	BmsErrorDecode(battWarningState);
+    return true;
+}
+
+
+
+
+
+
+//Uart线程初始化
+void UartTaskInit(void *arg)
+{
+    osThreadAttr_t task_attr;
+    memset(&task_attr,0,sizeof(task_attr));
+    memset(gProcess_Uart_TaskStack, 0xA5, PROC_UART_TASK_STACK_SIZE);
+    task_attr.name = "Uart_Task";
+    task_attr.stack_mem = gProcess_Uart_TaskStack;
+    task_attr.stack_size = PROC_UART_TASK_STACK_SIZE;
+    task_attr.priority = osPriorityBelowNormal7;
+    task_attr.cb_mem = &gProcess_Uart_Task_t;
+    task_attr.cb_size = sizeof(StaticTask_t);
+    UartTaskId = osThreadNew(UartTask, NULL, &task_attr);
+}
+void UartTaskDeInit(void *arg)
+{
+    osThreadTerminate(UartTaskId);
+    UartTaskId = NULL;
+}
+//函数区
+//Uart回调程序
+void USART_callback(uint32_t event)
+{
+    if(event & ARM_USART_EVENT_RX_TIMEOUT)
+    {
+        isRecvTimeout = true;
+    }
+    if(event & ARM_USART_EVENT_RECEIVE_COMPLETE)
+    {
+        isRecvComplete = true;
+    }
+}
+//Uart校验程序
+UINT16 crc_chk(UINT8* data, UINT8 length)
+{  
+    UINT8 j;
+    UINT16 reg_crc=0xFFFF;
+    while(length--)
+    { 
+        reg_crc ^= *data++;
+        for(j=0;j<8;j++)
+        { 
+            if(reg_crc & 0x01)
+            {
+                reg_crc=(reg_crc>>1) ^ 0xA001;
+            }
+            else
+            {
+                reg_crc=reg_crc >>1;
+            }
+        }
+    }
+    return reg_crc;
+}
+//Uart写命令函数
+UINT8 Uart_WriteCmd_func(Uart_Write_Data_Type UartWriteData)
+{
+    Uart_Write_Msg_Type Uart_Write_Msg;
+    UINT16 RegAddress = 0x0000;
+    UINT16 CRC_chk_buffer;
+    UINT8 timeout = 0x00;
+    UINT8 Uart_Recv_Buffer[8];
+    switch (UartWriteData.WriteCmd)
+    {
+        case 0x01://是否锁定
+        {   
+            RegAddress = 0x1B + BATT_CELL_VOL_NUM+BATT_TEMP_NUM+BATT_OTHER_TEMP_NUM;
+            Uart_Write_Msg.Bms_Address = BMS_ADDRESS_CODE;
+            Uart_Write_Msg.Bms_Funcode = UART_WRITE_CODE;
+            Uart_Write_Msg.Reg_Begin_H = RegAddress>>8;
+            Uart_Write_Msg.Reg_Begin_L = RegAddress;
+            Uart_Write_Msg.Reg_Num_H = 0x00;
+            Uart_Write_Msg.Reg_Num_L = 0x01;
+            Uart_Write_Msg.Data_Count = 0x02;//要写入的字节数
+            memcpy(Uart_Write_Msg.Data,UartWriteData.Data,2);
+            CRC_chk_buffer = crc_chk((UINT8 *)&Uart_Write_Msg,sizeof(Uart_Write_Msg)-2);
+            Uart_Write_Msg.CRC_L = CRC_chk_buffer;
+            Uart_Write_Msg.CRC_H = CRC_chk_buffer>>8;
+            break;
+        }
+		case 0x02://是否加热
+		{
+			RegAddress = 0x1C + BATT_CELL_VOL_NUM+BATT_TEMP_NUM+BATT_OTHER_TEMP_NUM;
+            Uart_Write_Msg.Bms_Address = BMS_ADDRESS_CODE;
+            Uart_Write_Msg.Bms_Funcode = UART_WRITE_CODE;
+            Uart_Write_Msg.Reg_Begin_H = RegAddress>>8;
+            Uart_Write_Msg.Reg_Begin_L = RegAddress;
+            Uart_Write_Msg.Reg_Num_H = 0x00;
+            Uart_Write_Msg.Reg_Num_L = 0x01;
+            Uart_Write_Msg.Data_Count = 0x02;//要写入的字节数
+            memcpy(Uart_Write_Msg.Data,UartWriteData.Data,2);
+            CRC_chk_buffer = crc_chk((UINT8 *)&Uart_Write_Msg,sizeof(Uart_Write_Msg)-2);
+            Uart_Write_Msg.CRC_L = CRC_chk_buffer;
+            Uart_Write_Msg.CRC_H = CRC_chk_buffer>>8;
+            break;
+		}
+        default:
+        {
+            UartWriteData.WriteCmd = 0x00;
+            return 0;
+            break;
+        }
+    }
+    USARTdrv->Send((UINT8 *)&Uart_Write_Msg,sizeof(Uart_Write_Msg));
+    #ifdef USING_PRINTF1
+        printf("Uart_Send_buffer:  ");
+        for(int i=0;i<sizeof(Uart_Write_Msg);i++)
+        {
+            printf("%x ",*((UINT8 *)&Uart_Write_Msg+i));
+        }
+        printf("\n");
+    #endif
+    USARTdrv->Receive(Uart_Recv_Buffer,8);
+    while((isRecvTimeout == false) && (isRecvComplete == false))
+    {
+        timeout++;
+        osDelay(100);
+        if (timeout>=10)
+        {
+            timeout =0;
+            isRecvTimeout = true;
+            break;
+        }
+    }
+    if (isRecvComplete == true)
+    {
+        #ifdef USING_PRINTF1
+            printf("Uart_Rece_buffer: ");
+            for(int i=0;i<8;i++)
+            {
+            printf("%x ",Uart_Recv_Buffer[i]);
+            }
+            printf("\n");
+        #endif
+        isRecvComplete = false;
+        if(Uart_Recv_Buffer[1]==0x10)
+        {
+            return UartWriteData.WriteCmd;
+        }
+        else
+        {
+            return 0x00;
+        }
+    }
+    else
+    {
+        isRecvTimeout = false;
+        return 0x00;
+    }
+}
+//Uart发送接收函数
+UINT8 Uart_DataRecv_func(Uart_Read_Msg_Type Uart_Read_Msg_Fun,UINT8* Uart_Recv_Buffer_Fun)
+{
+    UINT16 CRC_Rece_buffer;
+    UINT16 CRC_chk_buffer;
+    UINT16 Data_Len ;
+    UINT8 timeout = 0x00;
+	UINT8 pSendCmd[8];
+	memcpy(pSendCmd,(UINT8*)(&Uart_Read_Msg_Fun),8);
+    //Data_Len = (*(Uart_Read_Msg_Fun+4)|*(Uart_Read_Msg_Fun+5))*2+5;
+	Data_Len  = ((Uart_Read_Msg_Fun.Reg_Num_H<<8)|(Uart_Read_Msg_Fun.Reg_Num_L))*2+5;
+
+    //USARTdrv->Send(Uart_Read_Msg_Fun,8);
+	USARTdrv->Send(pSendCmd,8);
+    #ifdef USING_PRINTF1
+		
+        printf("Uart_Send_buffer:  ");
+        for(int i=0;i<8;i++)
+        // {
+             printf("%x ",pSendCmd[i]);
+        // }
+        printf("end\n");
+		//printf("%x ",*(Uart_Read_Msg_Fun));
+	//UINT8 temp = *(Uart_Read_Msg_Fun);
+    #endif
+    USARTdrv->Receive(Uart_Recv_Buffer_Fun,Data_Len);
+	while(true)
+    {
+        timeout++;
+        if((isRecvTimeout == true) || (isRecvComplete == true))
+        {
+            break;
+        }
+        else
+        {
+            osDelay(100);
+            if (timeout>=10)
+            {
+				// Data_Len = 0;
+                timeout =0;
+                isRecvTimeout = true;
+            }
+        } 
+    }
+     #ifdef USING_PRINTF1
+         printf("Uart_Rece_buffer1: ");
+         for(int j=0;j<Data_Len;j++)
+         {
+         printf("%x ",*(Uart_Recv_Buffer_Fun+j));
+         }
+     #endif
+    if (isRecvComplete == true)
+    {
+        isRecvComplete = false;
+        CRC_Rece_buffer =*(Uart_Recv_Buffer_Fun+Data_Len-1)<<8|*(Uart_Recv_Buffer_Fun+Data_Len-2);
+        CRC_chk_buffer = crc_chk(Uart_Recv_Buffer_Fun,Data_Len-2);
+	    #ifdef USING_PRINTF1
+	         printf("Uart_Rece_buffer after Crc: ");
+	         for(int i=0;i<Data_Len;i++)
+	         {
+	         	printf("%x ",*(Uart_Recv_Buffer_Fun+i));
+	   	     }
+	         printf("\tcrcchk:%x,%x\n ",CRC_chk_buffer,CRC_Rece_buffer);
+	    #endif
+        if (CRC_Rece_buffer == CRC_chk_buffer)//满足校验
+        {
+            return Data_Len;//此处指针移位出现重启问题
+        }
+        else //接收数据的校验不过
+        {
+            USARTdrv->Uninitialize();
+            osDelay(1000);
+            USARTdrv->Initialize(USART_callback);
+            USARTdrv->PowerControl(ARM_POWER_FULL);
+            USARTdrv->Control(ARM_USART_MODE_ASYNCHRONOUS |
+                      ARM_USART_DATA_BITS_8 |
+                      ARM_USART_PARITY_NONE |
+                      ARM_USART_STOP_BITS_1 |
+                      ARM_USART_FLOW_CONTROL_NONE, 9600);
+            memset(Uart_Recv_Buffer_Fun,0xff,Data_Len);
+            return 0;
+        }
+    }
+    else
+    {
+        memset(Uart_Recv_Buffer_Fun,0x00,Data_Len);
+        isRecvTimeout = false;
+        return 0;
+    }
+	return 0;
+}
+
+
+/**
+  \fn   BOOL BattHeaterSwitch(UINT8* heaterSwitch)
+  \param[in]  (UINT8*) heaterSwitch: the heater switch state
+  \brief    according to the current switch state and all the cell temp, it will turn on/off the switch
+  \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 isNeedtoSwitch = FALSE;
+	
+	UINT8 i =0;	
+	UINT8 currentSwitchState = 0;
+	//get the current switch state and the cell temp
+	currentSwitchState = battMOSSwitchState & 0x01;
+	if(currentSwitchState==0) 	//当前状态为关闭,判断是否应该开启
+	{
+		if(minCellTemp<=5+40 && maxCellTemp<25+40 && battSOC>=12)//温度偏移为40 
+		{
+			*heaterSwitch = 1;
+			isNeedtoSwitch = true;
+		}
+	}
+	else  						//当前状态为开启,判断是否应该关闭
+	{
+		if(minCellTemp>10+40 || maxCellTemp>30+40 || battSOC<10)
+		{
+			*heaterSwitch = 0;
+			isNeedtoSwitch= true;
+		}
+	}
+	return isNeedtoSwitch;
+}
+
+void battSOCDisplay()
+{
+	
+	static UINT8 lightTimer = 0;
+	UINT8 socLowLEDFlashPeriod = 10;//10*100 = 1000ms
+	UINT8 chargeLEDFlashPeriod = 6;//6*100 = 600ms
+	float dutyRatio = 0.4;
+	UINT8 temp;
+
+	if(AppNVMData.isBattLocked == TRUE)
+	{
+		return;
+	}
+	if(UartBattInfoRecvFlag == true)
+	{ 
+		lightTimer++;
+		
+		if(battWorkState == 0||battWorkState == 1)  //静置或放电状态
+		{
+			if(battSOC<=10)
+			{
+				if(lightTimer<(UINT8)(socLowLEDFlashPeriod*dutyRatio))
+				{
+					NetSocDisplay(LED_SOC_0,LED_TURN_ON);
+					NetSocDisplay(LED_SOC_1,LED_TURN_OFF);
+					NetSocDisplay(LED_SOC_2,LED_TURN_OFF);
+					NetSocDisplay(LED_SOC_3,LED_TURN_OFF);	
+				}
+				else if(lightTimer>=(UINT8)(socLowLEDFlashPeriod*dutyRatio) && lightTimer<socLowLEDFlashPeriod)
+				{
+					NetSocDisplay(LED_SOC_0,LED_TURN_OFF);
+					NetSocDisplay(LED_SOC_1,LED_TURN_OFF);
+					NetSocDisplay(LED_SOC_2,LED_TURN_OFF);
+					NetSocDisplay(LED_SOC_3,LED_TURN_OFF);	
+				}
+				else
+				{
+					NetSocDisplay(LED_SOC_0,LED_TURN_OFF);
+					NetSocDisplay(LED_SOC_1,LED_TURN_OFF);
+					NetSocDisplay(LED_SOC_2,LED_TURN_OFF);
+					NetSocDisplay(LED_SOC_3,LED_TURN_OFF);	
+					lightTimer = 0;
+				}			
+			}	
+			else if(battSOC>10&&battSOC<=25)
+			{
+				NetSocDisplay(LED_SOC_0,LED_TURN_ON);
+				NetSocDisplay(LED_SOC_1,LED_TURN_OFF);
+				NetSocDisplay(LED_SOC_2,LED_TURN_OFF);
+				NetSocDisplay(LED_SOC_3,LED_TURN_OFF);	
+				lightTimer = 0;
+			}
+			else if(battSOC>25&&battSOC<=50)
+			{
+				NetSocDisplay(LED_SOC_0,LED_TURN_ON);
+				NetSocDisplay(LED_SOC_1,LED_TURN_ON);
+				NetSocDisplay(LED_SOC_2,LED_TURN_OFF);
+				NetSocDisplay(LED_SOC_3,LED_TURN_OFF);	
+				lightTimer = 0;
+			}
+			else if(battSOC>50&&battSOC<=75)
+			{
+				NetSocDisplay(LED_SOC_0,LED_TURN_ON);
+				NetSocDisplay(LED_SOC_1,LED_TURN_ON);
+				NetSocDisplay(LED_SOC_2,LED_TURN_ON);
+				NetSocDisplay(LED_SOC_3,LED_TURN_OFF);	
+				lightTimer = 0;
+			}
+			else if(battSOC>75&&battSOC<=100)
+			{
+				NetSocDisplay(LED_SOC_0,LED_TURN_ON);
+				NetSocDisplay(LED_SOC_1,LED_TURN_ON);
+				NetSocDisplay(LED_SOC_2,LED_TURN_ON);
+				NetSocDisplay(LED_SOC_3,LED_TURN_ON);
+				lightTimer = 0;
+			}
+		}
+		else if(battWorkState == 2)
+		{
+			if(battSOC<=25)
+			{
+				if(lightTimer<(UINT8)(chargeLEDFlashPeriod*dutyRatio))
+				{
+					NetSocDisplay(LED_SOC_0,LED_TURN_ON);
+					NetSocDisplay(LED_SOC_1,LED_TURN_OFF);
+					NetSocDisplay(LED_SOC_2,LED_TURN_OFF);
+					NetSocDisplay(LED_SOC_3,LED_TURN_OFF);	
+				}
+				else if(lightTimer>=(UINT8)(chargeLEDFlashPeriod*dutyRatio) && lightTimer<chargeLEDFlashPeriod)
+				{
+					NetSocDisplay(LED_SOC_0,LED_TURN_OFF);
+					NetSocDisplay(LED_SOC_1,LED_TURN_OFF);
+					NetSocDisplay(LED_SOC_2,LED_TURN_OFF);
+					NetSocDisplay(LED_SOC_3,LED_TURN_OFF);	
+				}
+				else
+				{
+					NetSocDisplay(LED_SOC_0,LED_TURN_OFF);
+					NetSocDisplay(LED_SOC_1,LED_TURN_OFF);
+					NetSocDisplay(LED_SOC_2,LED_TURN_OFF);
+					NetSocDisplay(LED_SOC_3,LED_TURN_OFF);	
+					lightTimer = 0;
+				}			
+			}	
+			else if(battSOC>25&&battSOC<=50)
+			{
+				if(lightTimer<(UINT8)(chargeLEDFlashPeriod*dutyRatio))
+				{
+					NetSocDisplay(LED_SOC_0,LED_TURN_ON);
+					NetSocDisplay(LED_SOC_1,LED_TURN_ON);
+					NetSocDisplay(LED_SOC_2,LED_TURN_OFF);
+					NetSocDisplay(LED_SOC_3,LED_TURN_OFF);	
+				}
+				else if(lightTimer>=(UINT8)(chargeLEDFlashPeriod*dutyRatio) && lightTimer<chargeLEDFlashPeriod)
+				{
+					NetSocDisplay(LED_SOC_0,LED_TURN_ON);
+					NetSocDisplay(LED_SOC_1,LED_TURN_OFF);
+					NetSocDisplay(LED_SOC_2,LED_TURN_OFF);
+					NetSocDisplay(LED_SOC_3,LED_TURN_OFF);	
+				}
+				else
+				{
+					NetSocDisplay(LED_SOC_0,LED_TURN_ON);
+					NetSocDisplay(LED_SOC_1,LED_TURN_OFF);
+					NetSocDisplay(LED_SOC_2,LED_TURN_OFF);
+					NetSocDisplay(LED_SOC_3,LED_TURN_OFF);
+					lightTimer = 0;
+				}
+			}
+			else if(battSOC>50&&battSOC<=75)
+			{
+				if(lightTimer<(UINT8)(chargeLEDFlashPeriod*dutyRatio))
+				{
+					NetSocDisplay(LED_SOC_0,LED_TURN_ON);
+					NetSocDisplay(LED_SOC_1,LED_TURN_ON);
+					NetSocDisplay(LED_SOC_2,LED_TURN_ON);
+					NetSocDisplay(LED_SOC_3,LED_TURN_OFF);	
+				}
+				else if(lightTimer>=(UINT8)(chargeLEDFlashPeriod*dutyRatio) && lightTimer<chargeLEDFlashPeriod)
+				{
+					NetSocDisplay(LED_SOC_0,LED_TURN_ON);
+					NetSocDisplay(LED_SOC_1,LED_TURN_ON);
+					NetSocDisplay(LED_SOC_2,LED_TURN_OFF);
+					NetSocDisplay(LED_SOC_3,LED_TURN_OFF);	
+				}
+				else
+				{
+					NetSocDisplay(LED_SOC_0,LED_TURN_ON);
+					NetSocDisplay(LED_SOC_1,LED_TURN_ON);
+					NetSocDisplay(LED_SOC_2,LED_TURN_OFF);
+					NetSocDisplay(LED_SOC_3,LED_TURN_OFF);
+					lightTimer = 0;
+				}
+
+			}
+			else if(battSOC>75&&battSOC<=97)
+			{
+				if(lightTimer<(UINT8)(chargeLEDFlashPeriod*dutyRatio))
+				{
+					NetSocDisplay(LED_SOC_0,LED_TURN_ON);
+					NetSocDisplay(LED_SOC_1,LED_TURN_ON);
+					NetSocDisplay(LED_SOC_2,LED_TURN_ON);
+					NetSocDisplay(LED_SOC_3,LED_TURN_ON);	
+				}
+				else if(lightTimer>=(UINT8)(chargeLEDFlashPeriod*dutyRatio) && lightTimer<chargeLEDFlashPeriod)
+				{
+					NetSocDisplay(LED_SOC_0,LED_TURN_ON);
+					NetSocDisplay(LED_SOC_1,LED_TURN_ON);
+					NetSocDisplay(LED_SOC_2,LED_TURN_ON);
+					NetSocDisplay(LED_SOC_3,LED_TURN_OFF);	
+				}
+				else
+				{
+					NetSocDisplay(LED_SOC_0,LED_TURN_ON);
+					NetSocDisplay(LED_SOC_1,LED_TURN_ON);
+					NetSocDisplay(LED_SOC_2,LED_TURN_ON);
+					NetSocDisplay(LED_SOC_3,LED_TURN_OFF);	
+					lightTimer = 0;
+				}
+			}
+			else if(battSOC>97&&battSOC<=100)
+			{
+				NetSocDisplay(LED_SOC_0,LED_TURN_ON);
+				NetSocDisplay(LED_SOC_1,LED_TURN_ON);
+				NetSocDisplay(LED_SOC_2,LED_TURN_ON);
+				NetSocDisplay(LED_SOC_3,LED_TURN_ON);	
+			}		
+		}
+	}
+	
+}
+
+void battErrorStateDisplay()
+{	
+	static UINT8  errorLightTimer = 0;
+	//static UINT32 currentTimerCount=0;
+	
+	UINT8  errorLEDFlashPeriod = 6;//600ms
+	float errorDutyRatio = 0.4;
+
+	if(AppNVMData.isBattLocked == TRUE)
+	{
+		return;
+	}
+	
+	if(UartBattInfoRecvFlag == true)
+	{	
+	
+		errorLightTimer++;
+
+		if(battWarningState != 0)
+		{
+			if(errorLightTimer<(UINT8)(errorLEDFlashPeriod*errorDutyRatio)) 
+			{	
+				
+				FaultDisplay(LED_TURN_ON);
+				
+			}
+			else if(errorLightTimer>=(UINT8)(errorLEDFlashPeriod*errorDutyRatio) && errorLightTimer<errorLEDFlashPeriod)
+			{
+				
+				FaultDisplay(LED_TURN_OFF);
+				
+			}
+			else
+			{
+				
+				FaultDisplay(LED_TURN_OFF);
+				errorLightTimer = 0;			
+			}
+			
+		}
+		else
+		{
+			FaultDisplay(LED_TURN_OFF);
+			errorLightTimer = 0;
+		}	
+	}
+}
+
+void battWarningStateDisplay()
+{
+	static UINT8  warningLightTimer = 0;
+	//static UINT32 currentTimerCount=0;
+	
+	UINT8  warningLEDFlashPeriod = 6;//600ms
+	float warningDutyRatio = 0.4;
+
+	if(AppNVMData.isBattLocked == TRUE)
+	{
+		return;
+	}
+	
+	if(UartBattInfoRecvFlag == false)
+	{		
+		warningLightTimer++;
+
+		//if(battWarningState != 0)
+		{
+			if(warningLightTimer<(UINT8)(warningLEDFlashPeriod*warningDutyRatio)) 
+			{			
+				NetSocDisplay(LED_SOC_0,LED_TURN_ON);
+				FaultDisplay(LED_TURN_ON);
+				
+			}
+			else if(warningLightTimer>=(UINT8)(warningLEDFlashPeriod*warningDutyRatio) && warningLightTimer<warningLEDFlashPeriod)
+			{
+				NetSocDisplay(LED_SOC_0,LED_TURN_OFF);
+				FaultDisplay(LED_TURN_OFF);
+				
+			}
+			else
+			{
+				NetSocDisplay(LED_SOC_0,LED_TURN_OFF);
+				FaultDisplay(LED_TURN_OFF);
+				warningLightTimer = 0;			
+			}
+			
+		}
+			
+	}
+
+}
+
+
+void battLockStateDisplay(UINT8 lockState)
+{
+	static UINT8 currentState = 0;
+	static UINT8  errorLightTimer = 0;
+	//static UINT32 currentTimerCount=0;
+	
+	UINT8  errorLEDFlashPeriod = 10;//1000ms
+	float errorDutyRatio = 0.4;
+	
+	//printf("lockState = %d\ncurrent State = %d\n",lockState,currentState);
+	if(lockState==0)//no error
+	{
+		if(currentState!=lockState)
+		{
+			NetSocDisplay(LED_SOC_0,LED_TURN_OFF);
+			NetSocDisplay(LED_SOC_1,LED_TURN_OFF);
+			NetSocDisplay(LED_SOC_2,LED_TURN_OFF);
+			NetSocDisplay(LED_SOC_3,LED_TURN_OFF);
+			FaultDisplay(LED_TURN_OFF);
+			currentState = lockState;
+			errorLightTimer = 0;
+		}
+		else
+		{
+			return;
+		}
+
+	}
+	else  // error occurred, errorState = 1
+	{
+		if(errorLightTimer<(UINT8)(errorLEDFlashPeriod*errorDutyRatio)) 
+		{	
+			NetSocDisplay(LED_SOC_0,LED_TURN_ON);
+			NetSocDisplay(LED_SOC_1,LED_TURN_ON);
+			NetSocDisplay(LED_SOC_2,LED_TURN_ON);
+			NetSocDisplay(LED_SOC_3,LED_TURN_ON);
+			FaultDisplay(LED_TURN_ON);
+			
+		}
+		else if(errorLightTimer>=(UINT8)(errorLEDFlashPeriod*errorDutyRatio) && errorLightTimer<errorLEDFlashPeriod)
+		{
+			NetSocDisplay(LED_SOC_0,LED_TURN_OFF);
+			NetSocDisplay(LED_SOC_1,LED_TURN_OFF);
+			NetSocDisplay(LED_SOC_2,LED_TURN_OFF);
+			NetSocDisplay(LED_SOC_3,LED_TURN_OFF);
+			FaultDisplay(LED_TURN_OFF);			
+		}
+		else
+		{
+			NetSocDisplay(LED_SOC_0,LED_TURN_OFF);
+			NetSocDisplay(LED_SOC_1,LED_TURN_OFF);
+			NetSocDisplay(LED_SOC_2,LED_TURN_OFF);
+			NetSocDisplay(LED_SOC_3,LED_TURN_OFF);
+			FaultDisplay(LED_TURN_OFF);
+			errorLightTimer = 0;			
+		}		
+	}	
+	errorLightTimer++;
+}
+
+void relayPWMControl()
+{
+	static UINT8 timerCount=0;
+	//printf("timerCout=%d\n",timerCount);
+	if(timerCount<2)
+	{
+		relayControl(TRUE);
+		timerCount++;
+	}
+	else if(timerCount>=2 && timerCount<5)
+	{
+		relayControl(FALSE);
+		timerCount++;
+	}
+	else
+	{
+		relayControl(FALSE);
+		timerCount = 0;
+	}
+}
+
+
+
+UINT8  decryptionAlgorithm (UINT16 cipherText)
+{
+	UINT16 plainText = 1;	
+	UINT16 publicKeyD = 43;
+	UINT16 publicKeyN = 10961;
+	cipherText = cipherText % publicKeyN;
+	while(publicKeyD >0)
+	{
+		if(publicKeyD % 2 ==1)
+		{			
+			plainText = plainText * cipherText % publicKeyN;
+		}
+		publicKeyD = publicKeyD/2;		
+		cipherText = (cipherText * cipherText) % publicKeyN;
+	}
+	return (UINT8)plainText;
+}
+
+UINT16  encryptionAlgorithm (UINT16 plainText)
+{
+	UINT16 cipherText = 1; 
+	UINT16 privateKeyE = 37507;
+	UINT16 privateKeyN = 10961;
+	plainText = plainText % privateKeyN;
+	while(privateKeyE >0)
+	{
+	if(privateKeyE % 2 ==1)
+	{   
+	cipherText =  ( cipherText * plainText) % privateKeyN;
+	}
+	privateKeyE = privateKeyE/2;  
+	plainText = (plainText * plainText) % privateKeyN;
+	}
+	return cipherText;
+}
+UINT8 Uart_Encrypt_Send()
+{
+	UINT8 SeedNumberArrray[4]={0x38,0x56,0xfe,0xac};
+	UINT16 EncodeNumberArray[4];
+	UINT8 UartEncryptBuffer[17];
+	UINT8 UartDecryptBuffer[5];
+	UINT16 CRC_chk_buffer;
+	UINT8 timeCount = 0;
+	UartEncryptBuffer[0] = BMS_ADDRESS_CODE;
+	UartEncryptBuffer[1] = UART_ENCRYPT_CODE;
+	UartEncryptBuffer[2] = 0x0c;
+	for(int i=0;i<4;i++)
+	{
+		SeedNumberArrray[i]=rand();
+		EncodeNumberArray[i] = encryptionAlgorithm(SeedNumberArrray[i]);
+		UartEncryptBuffer[i+3] = SeedNumberArrray[i];
+		UartEncryptBuffer[i*2+7] = EncodeNumberArray[i]>>8;
+		UartEncryptBuffer[i*2+8] = EncodeNumberArray[i];
+	}
+	CRC_chk_buffer = crc_chk(UartEncryptBuffer,17-2);
+	UartEncryptBuffer[15] = CRC_chk_buffer;
+	UartEncryptBuffer[16] = CRC_chk_buffer>>8;
+	USARTdrv->Send(UartEncryptBuffer,17);
+	USARTdrv->Receive(UartDecryptBuffer,5); 
+	while((isRecvTimeout == false) && (isRecvComplete == false))
+	{
+		timeCount++;
+		osDelay(100);
+		if (timeCount>=10)
+		{
+			timeCount =0;
+			isRecvTimeout = true;
+			break;
+		}
+	}
+	#ifdef USING_PRINTF
+		printf("Uart_Rece_buffer: ");
+		for(int i=0;i<5;i++)
+		{
+		printf("%x ",UartDecryptBuffer[i]);
+		}
+    #endif	
+	if (isRecvComplete == true)
+	{
+		isRecvComplete = false;
+		return UartDecryptBuffer[2];
+	}
+	else
+	{
+		isRecvTimeout = false;
+		return 0x03;
+	}
+}
+
+
+
+
+/*-----------------------------------------------------------------------------*/
+void SP_BMS_Update_Service() //超力源BMS升级服务
+{
+	
+	UINT8 errorCount = 0;
+	UINT8 resetCount = 0;	
+	UINT16 currentPackage = 0;	
+	UINT32 updateDataTotalByteLen = 0;
+	UpdateStep updateStep = UPDATE_STEP_CHECK_VERSION;	
+	
+	UINT8 i,j,ret=0;
+	UINT8 dataLen = 0;
+		
+	UINT8 pUpdateMsgSend[80];
+	UINT32 updateMsgSendLen = 0;	
+	UINT32 currentPackageStartAddr = 0;
+	BMS_Update_Recv_Msg_Type pUpdateMsgRecv;
+	UINT8 bmsUpdateFlag = 1;
+	//BMS_Update_Recv_Msg_Type bmsMsg;
+	//static UpdateStep step = UPDATE_STEP_CHECK_VERSION;
+	UINT8 Cycle_conut = 0;
+	while(bmsUpdateFlag && Cycle_conut<2)
+	{
+		switch (updateStep)
+		{
+			case UPDATE_STEP_CHECK_VERSION:
+
+				dataLen = 0;
+				updateMsgSendLen = 7;
+				pUpdateMsgSend[0] = 0xEB; //start flag
+				pUpdateMsgSend[1] = 0x01;	//add flag
+				pUpdateMsgSend[2] = 0x01; //read
+				pUpdateMsgSend[3] = 0x03;	//data len
+				pUpdateMsgSend[4] = 0x90;	//cmd
+				pUpdateMsgSend[5] = 0x93;	//checksum
+				pUpdateMsgSend[6] = 0xF5;	//end flag		
+				//printf("updateMsgSendLen0 = %x\n",updateMsgSendLen);
+				memset((UINT8*)(&pUpdateMsgRecv) , 0, sizeof(BMS_Update_Recv_Msg_Type));
+				ret = SP_BMS_Update_Query(pUpdateMsgSend, updateMsgSendLen, (UINT8*)(&pUpdateMsgRecv),sizeof(BMS_Update_Recv_Msg_Type), 500);
+				//printf("updateMsgSendLen1 = %x\n",updateMsgSendLen);
+				if(ret!=0)
+				{
+					if(pUpdateMsgRecv.startFlag == 0xEB && pUpdateMsgRecv.endFlag == 0xF5)
+					{
+						if(pUpdateMsgRecv.cmd == 0x90)
+						{
+							if(pUpdateMsgRecv.data != 0xFF)
+							{
+								updateStep = UPDATE_STEP_REQUEST_UPDATE;
+								errorCount = 0;
+							}
+							else
+							{
+								updateStep = UPDATE_STEP_SET_BAUD_RATE;
+								errorCount = 0;
+							}
+						}
+						else
+						{
+							errorCount++;
+						}
+					}
+					else
+					{
+						errorCount++;
+					}
+				}			
+				else
+				{
+					errorCount++;
+				}
+				#ifdef USING_PRINTF1
+							//printf("update step:%d\n",updateStep);
+							printf("query:");
+							
+							for(j=0;j<updateMsgSendLen;j++)
+							{
+								printf("%x ",pUpdateMsgSend[j]);
+							}
+							
+							printf("\nanswer:");
+							for(j=0;j<sizeof(BMS_Update_Recv_Msg_Type);j++)
+							{
+								printf("%x ",*(((UINT8*)&pUpdateMsgRecv)+j));
+							}
+							printf("\n");
+							printf("next update step:%d\n",updateStep);
+				#endif
+				if(errorCount>10)
+				{
+					updateStep = UPDATE_STEP_RESET;
+					errorCount = 0;
+				}
+				osDelay(50);
+				break;
+			
+			case UPDATE_STEP_REQUEST_UPDATE:
+				dataLen = 1;
+				updateMsgSendLen = 8;
+				pUpdateMsgSend[0] = 0xEB; //start flag
+				pUpdateMsgSend[1] = 0x01;	//add flag
+				pUpdateMsgSend[2] = 0x00; //write
+				pUpdateMsgSend[3] = 0x04;	//data len
+				pUpdateMsgSend[4] = 0x80;	//cmd
+				pUpdateMsgSend[5] = 0x22;	//data
+				pUpdateMsgSend[6] = 0xA6;	//check
+				pUpdateMsgSend[7] = 0xF5;	//end flag
+				memset((UINT8*)(&pUpdateMsgRecv) , 0, sizeof(BMS_Update_Recv_Msg_Type));
+				ret = SP_BMS_Update_Query(pUpdateMsgSend, updateMsgSendLen, (UINT8*)(&pUpdateMsgRecv), sizeof(BMS_Update_Recv_Msg_Type), 500);
+				if(ret!=0)
+				{
+					if(pUpdateMsgRecv.startFlag == 0xEB && pUpdateMsgRecv.endFlag == 0xF5)
+					{
+						if(pUpdateMsgRecv.cmd == 0x80)
+						{
+							if(pUpdateMsgRecv.data == 0x33)
+							{
+								updateStep = UPDATE_STEP_START_UPDATE;
+								errorCount = 0;
+							}
+							else
+							{
+								errorCount++;
+							}						
+						}
+						else
+						{
+							errorCount++;
+						}
+					}
+					else
+					{
+						errorCount++;
+					}
+				}			
+				else
+				{
+					errorCount++;
+				}
+
+				if(errorCount>10)
+				{
+					updateStep = UPDATE_STEP_RESET;
+					errorCount = 0;
+				}
+				
+				#ifdef USING_PRINTF1
+							printf("update step:%d\n",updateStep);
+							printf("query:");
+							for(j=0;j<updateMsgSendLen;j++)
+							{
+								printf("%x ",pUpdateMsgSend[j]);
+							}
+							printf("\nanswer:");
+							for(j=0;j<sizeof(BMS_Update_Recv_Msg_Type);j++)
+							{
+								printf("%x ",*(((UINT8*)&pUpdateMsgRecv)+j));
+							}
+							printf("\n");
+							printf("next update step:%d\n",updateStep);
+				#endif
+				osDelay(50);
+				break;
+
+			case UPDATE_STEP_START_UPDATE:
+				dataLen = 1;
+				updateMsgSendLen = 8;
+				pUpdateMsgSend[0] = 0xEB; //start flag
+				pUpdateMsgSend[1] = 0x01;	//add flag
+				pUpdateMsgSend[2] = 0x00; //write
+				pUpdateMsgSend[3] = 0x04;	//data len
+				pUpdateMsgSend[4] = 0x80;	//cmd
+				pUpdateMsgSend[5] = 0x55;	//data
+				pUpdateMsgSend[6] = 0xD9;	//check
+				pUpdateMsgSend[7] = 0xF5;	//end flag
+				memset((UINT8*)(&pUpdateMsgRecv) , 0, sizeof(BMS_Update_Recv_Msg_Type));
+				ret = SP_BMS_Update_Query(pUpdateMsgSend, updateMsgSendLen, (UINT8*)(&pUpdateMsgRecv), 0, 500);
+				//updateStep = UPDATE_STEP_SET_BAUD_RATE;
+				updateStep = UPDATE_STEP_CHECK_VERSION_AGAIN;//2021-04-09跳过波特率设置
+				#ifdef USING_PRINTF1
+							
+							printf("query:");
+							for(j=0;j<updateMsgSendLen;j++)
+							{
+								printf("%x ",pUpdateMsgSend[j]);
+							}
+							printf("\nanswer:");
+							for(j=0;j<sizeof(BMS_Update_Recv_Msg_Type);j++)
+							{
+								printf("%x ",*(((UINT8*)&pUpdateMsgRecv)+j));
+							}
+							
+							printf("\n");		
+							printf("next update step:%d\n",updateStep);
+				#endif
+				break;
+			case UPDATE_STEP_CHECK_VERSION_AGAIN:
+				dataLen = 0;
+				updateMsgSendLen = 7;
+				pUpdateMsgSend[0] = 0xEB; //start flag
+				pUpdateMsgSend[1] = 0x01;	//add flag
+				pUpdateMsgSend[2] = 0x01; //read
+				pUpdateMsgSend[3] = 0x03;	//data len
+				pUpdateMsgSend[4] = 0x90;	//cmd
+				pUpdateMsgSend[5] = 0x93;	//checksum
+				pUpdateMsgSend[6] = 0xF5;	//end flag		
+				//printf("updateMsgSendLen0 = %x\n",updateMsgSendLen);
+				memset((UINT8*)(&pUpdateMsgRecv) , 0, sizeof(BMS_Update_Recv_Msg_Type));
+				ret = SP_BMS_Update_Query(pUpdateMsgSend, updateMsgSendLen, (UINT8*)(&pUpdateMsgRecv),sizeof(BMS_Update_Recv_Msg_Type), 100);
+				//printf("updateMsgSendLen1 = %x\n",updateMsgSendLen);
+				if(ret!=0)
+				{
+					if(pUpdateMsgRecv.startFlag == 0xEB && pUpdateMsgRecv.endFlag == 0xF5)
+					{
+						if(pUpdateMsgRecv.cmd == 0x90)
+						{
+							if(pUpdateMsgRecv.data != 0xFF)
+							{
+								updateStep = UPDATE_STEP_RESET;
+								errorCount = 0;
+							}
+							else
+							{
+								updateStep = UPDATE_STEP_SET_BAUD_RATE;
+								errorCount = 0;
+							}
+						}
+						else
+						{
+							errorCount++;
+						}
+					}
+					else
+					{
+						errorCount++;
+					}
+				}			
+				else
+				{
+					errorCount++;
+				}
+				#ifdef USING_PRINTF1
+							//printf("update step:%d\n",updateStep);
+							printf("query:");
+							
+							for(j=0;j<updateMsgSendLen;j++)
+							{
+								printf("%x ",pUpdateMsgSend[j]);
+							}
+							
+							printf("\nanswer:");
+							for(j=0;j<sizeof(BMS_Update_Recv_Msg_Type);j++)
+							{
+								printf("%x ",*(((UINT8*)&pUpdateMsgRecv)+j));
+							}
+							printf("\n");
+							printf("next update step:%d\n",updateStep);
+				#endif
+				if(errorCount>10)
+				{
+					updateStep = UPDATE_STEP_RESET;
+					errorCount = 0;
+				}
+				osDelay(50);
+				break;
+			case UPDATE_STEP_SET_BAUD_RATE:
+				printf("start step %d\n",updateStep);
+				dataLen = 4;
+				updateMsgSendLen = 12;
+				pUpdateMsgSend[0] = 0xEB; //start flag
+				pUpdateMsgSend[1] = 0x01;	//add flag
+				pUpdateMsgSend[2] = 0x00; //write
+				pUpdateMsgSend[3] = 0x08;	//data len
+				pUpdateMsgSend[4] = 0x81;	//cmd
+				pUpdateMsgSend[5] = 0x33;	//data
+				pUpdateMsgSend[6] = 0x00;	//baud rate:9600
+				pUpdateMsgSend[7] = 0x00;
+				pUpdateMsgSend[8] = 0x25;
+				pUpdateMsgSend[9] = 0x80;
+				pUpdateMsgSend[10] = 0x61;	//check
+				pUpdateMsgSend[11] = 0xF5;	//end flag
+				#ifdef USING_PRINTF1
+				printf("query:");
+				for(j=0;j<updateMsgSendLen;j++)
+				{
+					printf("%x ",pUpdateMsgSend[j]);
+				}
+				printf("\n");
+				#endif
+				memset((UINT8*)(&pUpdateMsgRecv) , 0, sizeof(BMS_Update_Recv_Msg_Type));
+				ret = SP_BMS_Update_Query(pUpdateMsgSend, updateMsgSendLen, (UINT8*)(&pUpdateMsgRecv), sizeof(BMS_Update_Recv_Msg_Type), 500);
+				printf("ret = %d\n",ret);
+				if(ret!=0)
+				{
+					if(pUpdateMsgRecv.startFlag == 0xEB && pUpdateMsgRecv.endFlag == 0xF5)
+					{
+						if(pUpdateMsgRecv.cmd == 0x81)
+						{
+							if(pUpdateMsgRecv.data == 0x11)
+							{
+								updateStep = UPDATE_STEP_PREPARE_SEND_DATA_LEN;
+								errorCount = 0;
+							}
+							else
+							{
+								errorCount++;
+							}						
+						}
+						else
+						{
+							errorCount++;
+						}
+					}
+					else
+					{
+						errorCount++;
+					}
+				}			
+				else
+				{
+					errorCount++;
+				}
+
+				if(errorCount>10)
+				{
+					updateStep = UPDATE_STEP_RESET;
+					errorCount = 0;
+				}
+				
+				#ifdef USING_PRINTF1
+					//printf("update step:%d\n",updateStep);
+					printf("query:");
+					for(j=0;j<updateMsgSendLen;j++)
+					{
+						printf("%x ",pUpdateMsgSend[j]);
+					}
+					printf("\nanswer:");
+					for(j=0;j<sizeof(BMS_Update_Recv_Msg_Type);j++)
+					{
+						printf("%x ",*(((UINT8*)&pUpdateMsgRecv)+j));
+					}
+					printf("\n");
+					printf("next update step:%d\n",updateStep);
+				#endif
+				osDelay(50);
+				break;
+			
+			
+			case UPDATE_STEP_PREPARE_SEND_DATA_LEN:
+				printf("start step %d\n",updateStep);
+				dataLen = 1;
+				updateMsgSendLen = 8;
+				pUpdateMsgSend[0] = 0xEB; //start flag
+				pUpdateMsgSend[1] = 0x01;	//add flag
+				pUpdateMsgSend[2] = 0x00; //write
+				pUpdateMsgSend[3] = 0x04;	//data len
+				pUpdateMsgSend[4] = 0x81;	//cmd
+				pUpdateMsgSend[5] = 0x44;	//data
+				pUpdateMsgSend[6] = 0xC9;	//check
+				pUpdateMsgSend[7] = 0xF5;	//end flag
+				memset((UINT8*)(&pUpdateMsgRecv) , 0, sizeof(BMS_Update_Recv_Msg_Type));
+				ret = SP_BMS_Update_Query(pUpdateMsgSend, updateMsgSendLen, (UINT8*)(&pUpdateMsgRecv), sizeof(BMS_Update_Recv_Msg_Type), 500);
+				if(ret!=0)
+				{
+					if(pUpdateMsgRecv.startFlag == 0xEB && pUpdateMsgRecv.endFlag == 0xF5)
+					{
+						if(pUpdateMsgRecv.cmd == 0x81)
+						{
+							if(pUpdateMsgRecv.data == 0x11)
+							{
+								updateStep = UPDATE_STEP_SEND_DATA_LEN;
+								errorCount = 0;
+							}
+							else
+							{
+								errorCount++;
+							}						
+						}
+						else
+						{
+							errorCount++;
+						}
+					}
+					else
+					{
+						errorCount++;
+					}
+				}			
+				else
+				{
+					errorCount++;
+				}
+
+				if(errorCount>10)
+				{
+					updateStep = UPDATE_STEP_RESET;
+					errorCount = 0;
+				}
+				
+				#ifdef USING_PRINTF1
+					//printf("update step:%d\n",updateStep);
+					printf("query:");
+					for(j=0;j<updateMsgSendLen;j++)
+					{
+						printf("%x ",pUpdateMsgSend[j]);
+					}
+					printf("\nanswer:");
+					for(j=0;j<sizeof(BMS_Update_Recv_Msg_Type);j++)
+					{
+						printf("%x ",*(((UINT8*)&pUpdateMsgRecv)+j));
+					}
+					printf("\n");	
+					printf("next update step:%d\n",updateStep);
+				#endif
+				osDelay(50);
+				break;		
+			case UPDATE_STEP_SEND_DATA_LEN:
+				
+				dataLen = 4;
+				BSP_QSPI_Read_Safe(&updateDataTotalByteLen,FLASH_BMS_FOTA_START_ADDR,4);
+				updateDataTotalByteLen = (((updateDataTotalByteLen)&0xFF)<<24)|(((updateDataTotalByteLen>>8)&0xFF)<<16)|(((updateDataTotalByteLen>>16)&0xFF)<<8)|(((updateDataTotalByteLen>>24)&0xFF));
+				updateMsgSendLen = 11;
+				pUpdateMsgSend[0] = 0xEB; //start flag
+				pUpdateMsgSend[1] = 0x01;	//add flag
+				pUpdateMsgSend[2] = 0x00; //write
+				pUpdateMsgSend[3] = 0x07;	//data len
+				pUpdateMsgSend[4] = 0x82;	//cmd
+				pUpdateMsgSend[5] = (updateDataTotalByteLen>>24)&0xFF;	//data: package byte len
+				pUpdateMsgSend[6] = (updateDataTotalByteLen>>16)&0xFF;	
+				pUpdateMsgSend[7] = (updateDataTotalByteLen>>8)&0xFF;	
+				pUpdateMsgSend[8] = (updateDataTotalByteLen)&0xFF;
+				pUpdateMsgSend[9] = SP_BMS_Update_CheckSUM(&pUpdateMsgSend[3], dataLen+2);	//check sum
+				pUpdateMsgSend[10] = 0xF5;	//end flag
+				
+				memset((UINT8*)(&pUpdateMsgRecv),0,sizeof(BMS_Update_Recv_Msg_Type));
+				ret = SP_BMS_Update_Query(pUpdateMsgSend, updateMsgSendLen, (UINT8*)(&pUpdateMsgRecv), sizeof(BMS_Update_Recv_Msg_Type), 500);
+				if(ret!=0)
+				{
+					if(pUpdateMsgRecv.startFlag == 0xEB && pUpdateMsgRecv.endFlag == 0xF5)
+					{
+						if(pUpdateMsgRecv.cmd == 0x81)
+						{
+							if(pUpdateMsgRecv.data == 0x11)
+							{
+								updateStep = UPDATE_STEP_PREPARE_SEND_UPDATE_DATA;
+								errorCount = 0;
+							}
+							else
+							{
+								errorCount++;
+							}						
+						}
+						else
+						{
+							errorCount++;
+						}
+					}
+					else
+					{
+						errorCount++;
+					}
+				}			
+				else
+				{
+					errorCount++;
+				}
+
+				if(errorCount>10)
+				{
+					updateStep = UPDATE_STEP_RESET;
+					errorCount = 0;
+				}
+				
+				#ifdef USING_PRINTF1
+							//printf("update step:%d\n",updateStep);
+							printf("query:");
+							for(j=0;j<updateMsgSendLen;j++)
+							{
+								printf("%x ",pUpdateMsgSend[j]);
+							}
+							printf("\nanswer:");
+							for(j=0;j<sizeof(BMS_Update_Recv_Msg_Type);j++)
+							{
+								printf("%x ",*(((UINT8*)&pUpdateMsgRecv)+j));
+							}
+							printf("\n");
+							printf("next update step:%d\n",updateStep);
+				#endif
+				osDelay(50);
+				break;	
+				
+			case UPDATE_STEP_PREPARE_SEND_UPDATE_DATA:
+				dataLen = 1;
+				updateMsgSendLen = 8;
+				pUpdateMsgSend[0] = 0xEB; //start flag
+				pUpdateMsgSend[1] = 0x01;	//add flag
+				pUpdateMsgSend[2] = 0x00; //write
+				pUpdateMsgSend[3] = 0x04;	//data len
+				pUpdateMsgSend[4] = 0x81;	//cmd
+				pUpdateMsgSend[5] = 0x55;	//data
+				pUpdateMsgSend[6] = 0xDA;	//check
+				pUpdateMsgSend[7] = 0xF5;	//end flag
+				memset((UINT8*)(&pUpdateMsgRecv) , 0, sizeof(BMS_Update_Recv_Msg_Type));
+				ret = SP_BMS_Update_Query(pUpdateMsgSend, updateMsgSendLen,(UINT8*)(&pUpdateMsgRecv), sizeof(BMS_Update_Recv_Msg_Type), 500);
+				if(ret!=0)
+				{
+					if(pUpdateMsgRecv.startFlag == 0xEB && pUpdateMsgRecv.endFlag == 0xF5)
+					{
+						if(pUpdateMsgRecv.cmd == 0x81)
+						{
+							if(pUpdateMsgRecv.data == 0x11)
+							{
+								updateStep = UPDATE_STEP_SEND_UPDATE_DATA;
+								errorCount = 0;
+							}
+							else
+							{
+								errorCount++;
+							}						
+						}
+						else
+						{
+							errorCount++;
+						}
+					}
+					else
+					{
+						errorCount++;
+					}
+				}			
+				else
+				{
+					errorCount++;
+				}
+
+				if(errorCount>10)
+				{
+					updateStep = UPDATE_STEP_RESET;
+					errorCount = 0;
+				}
+				
+				#ifdef USING_PRINTF1
+					//printf("update step:%d\n",updateStep);
+					printf("query:");
+					for(j=0;j<updateMsgSendLen;j++)
+					{
+						printf("%x ",pUpdateMsgSend[j]);
+					}
+					printf("\nanswer:");
+					for(j=0;j<sizeof(BMS_Update_Recv_Msg_Type);j++)
+					{
+						printf("%x ",*(((UINT8*)&pUpdateMsgRecv)+j));
+					}
+					printf("\n");	
+					printf("next update step:%d\n",updateStep);
+				#endif
+				osDelay(50);
+				break;
+			case UPDATE_STEP_SEND_UPDATE_DATA:
+				dataLen = 64;
+				updateMsgSendLen = 75;
+							
+				for(currentPackage=0;currentPackage<updateDataTotalByteLen/64;currentPackage++)
+				{
+					currentPackageStartAddr = currentPackage*64;
+				
+					pUpdateMsgSend[0] = 0xEB; //start flag
+					pUpdateMsgSend[1] = 0x01;	//add flag
+					pUpdateMsgSend[2] = 0x00; //write
+					pUpdateMsgSend[3] = 0x47;	//data len			
+					pUpdateMsgSend[4] = 0x82;	//cmd
+					pUpdateMsgSend[5] = (currentPackageStartAddr>>24)&0xFF;
+					pUpdateMsgSend[6] = (currentPackageStartAddr>>16)&0xFF;
+					pUpdateMsgSend[7] = (currentPackageStartAddr>>8)&0xFF;
+					pUpdateMsgSend[8] = currentPackageStartAddr&0xFF;
+					BSP_QSPI_Read_Safe(&pUpdateMsgSend[9], FLASH_BMS_FOTA_START_ADDR+4+currentPackage*dataLen, dataLen);  //data			
+					pUpdateMsgSend[8+dataLen+1] = SP_BMS_Update_CheckSUM(&pUpdateMsgSend[3], dataLen+6);  //check sum
+					pUpdateMsgSend[8+dataLen+2] = 0xF5;	//end flag
+					memset((UINT8*)(&pUpdateMsgRecv) , 0, sizeof(BMS_Update_Recv_Msg_Type));
+					ret = SP_BMS_Update_Query(pUpdateMsgSend, updateMsgSendLen, (UINT8*)(&pUpdateMsgRecv), sizeof(BMS_Update_Recv_Msg_Type), 500);
+					if(ret!=0)
+					{
+						if(pUpdateMsgRecv.startFlag == 0xEB && pUpdateMsgRecv.endFlag == 0xF5)
+						{
+							if(pUpdateMsgRecv.cmd == 0x81)
+							{
+								if(pUpdateMsgRecv.data == 0x11)
+								{
+									if(currentPackage+1 == updateDataTotalByteLen/64)
+									{
+										updateStep = UPDATE_STEP_SEND_DATA_END;
+									}
+									errorCount = 0;
+								}
+								else
+								{
+									errorCount++;
+								}						
+							}
+							else
+							{
+								errorCount++;
+							}
+						}
+						else
+						{
+							errorCount++;
+						}
+					}			
+					else
+					{
+						errorCount++;
+					}
+
+					if(errorCount>10)
+					{					
+						updateStep = UPDATE_STEP_RESET;
+						errorCount = 0;
+						break;
+					}
+				#ifdef USING_PRINTF1
+							//printf("update step:%d\n",updateStep);
+							printf("query:");
+							for(j=0;j<updateMsgSendLen;j++)
+							{
+								printf("%x ",pUpdateMsgSend[j]);
+							}
+							printf("\nanswer:");
+							for(j=0;j<sizeof(BMS_Update_Recv_Msg_Type);j++)
+							{
+								printf("%x ",*(((UINT8*)&pUpdateMsgRecv)+j));
+							}
+							printf("\n");
+							printf("next update step:%d\n",updateStep);
+				#endif
+				}
+				osDelay(50);
+				break;
+
+			case UPDATE_STEP_SEND_DATA_END:
+				dataLen = 1;
+				updateMsgSendLen = 8;
+				pUpdateMsgSend[0] = 0xEB; //start flag
+				pUpdateMsgSend[1] = 0x01;	//add flag
+				pUpdateMsgSend[2] = 0x00; //write
+				pUpdateMsgSend[3] = 0x04;	//data len
+				pUpdateMsgSend[4] = 0x81;	//cmd
+				pUpdateMsgSend[5] = 0x66;	//data
+				pUpdateMsgSend[6] = 0xEB;	//check
+				pUpdateMsgSend[7] = 0xF5;	//end flag
+				memset((UINT8*)(&pUpdateMsgRecv) , 0, sizeof(BMS_Update_Recv_Msg_Type));
+				ret = SP_BMS_Update_Query(pUpdateMsgSend, updateMsgSendLen, (UINT8*)(&pUpdateMsgRecv), sizeof(BMS_Update_Recv_Msg_Type), 500);
+				if(ret!=0)
+				{
+					if(pUpdateMsgRecv.startFlag == 0xEB && pUpdateMsgRecv.endFlag == 0xF5)
+					{
+						if(pUpdateMsgRecv.cmd == 0x81)
+						{
+							if(pUpdateMsgRecv.data == 0x11)
+							{
+								updateStep = UPDATE_STEP_START_INSTALL;
+								errorCount = 0;
+							}
+							else
+							{
+								errorCount++;
+							}						
+						}
+						else
+						{
+							errorCount++;
+						}
+					}
+					else
+					{
+						errorCount++;
+					}
+				}			
+				else
+				{
+					errorCount++;
+				}
+
+				if(errorCount>10)
+				{
+					updateStep = UPDATE_STEP_RESET;
+					errorCount = 0;
+				}
+				
+				#ifdef USING_PRINTF1
+							//printf("update step:%d\n",updateStep);
+							printf("query:");
+							for(j=0;j<updateMsgSendLen;j++)
+							{
+								printf("%x ",pUpdateMsgSend[j]);
+							}
+							printf("\nanswer:");
+							for(j=0;j<sizeof(BMS_Update_Recv_Msg_Type);j++)
+							{
+								printf("%x ",*(((UINT8*)&pUpdateMsgRecv)+j));
+							}
+							printf("\n");
+							printf("next update step:%d\n",updateStep);
+				#endif
+				osDelay(50);
+				break;			
+
+			case UPDATE_STEP_START_INSTALL:
+				dataLen = 1;
+				updateMsgSendLen = 8;
+				pUpdateMsgSend[0] = 0xEB; //start flag
+				pUpdateMsgSend[1] = 0x01;	//add flag
+				pUpdateMsgSend[2] = 0x00; //write
+				pUpdateMsgSend[3] = 0x04;	//data len
+				pUpdateMsgSend[4] = 0x81;	//cmd
+				pUpdateMsgSend[5] = 0x99;	//data
+				pUpdateMsgSend[6] = 0x1E;	//check
+				pUpdateMsgSend[7] = 0xF5;	//end flag
+				memset((UINT8*)(&pUpdateMsgRecv) , 0, sizeof(BMS_Update_Recv_Msg_Type));
+				SP_BMS_Update_Query(pUpdateMsgSend, updateMsgSendLen, (UINT8*)(&pUpdateMsgRecv), 0, 500);
+				
+				updateStep = UPDATE_STEP_END;
+				
+				#ifdef USING_PRINTF1
+							//printf("update step:%d\n",updateStep);
+							printf("query:");
+							for(j=0;j<updateMsgSendLen;j++)
+							{
+								printf("%x ",pUpdateMsgSend[j]);
+							}
+							printf("\nanswer:");
+							for(j=0;j<sizeof(BMS_Update_Recv_Msg_Type);j++)
+							{
+								printf("%x ",*(((UINT8*)&pUpdateMsgRecv)+j));
+							}
+							printf("\n");	
+							printf("next update step:%d\n",updateStep);
+				#endif
+				osDelay(50);
+				break;
+			case UPDATE_STEP_END:
+				updateStep = UPDATE_STEP_CHECK_VERSION;
+				printf("update end\n");
+				bmsUpdateFlag = 0;
+				break;
+			case UPDATE_STEP_RESET:
+				dataLen = 1;
+				updateMsgSendLen = 8;
+				pUpdateMsgSend[0] = 0xEB; //start flag
+				pUpdateMsgSend[1] = 0x01;	//add flag
+				pUpdateMsgSend[2] = 0x00; //write
+				pUpdateMsgSend[3] = 0x04;	//data len
+				pUpdateMsgSend[4] = 0x81;	//cmd
+				pUpdateMsgSend[5] = 0xAA;	//data
+				pUpdateMsgSend[6] = 0x2F;	//check
+				pUpdateMsgSend[7] = 0xF5;	//end flag
+				memset((UINT8*)(&pUpdateMsgRecv) , 0, sizeof(BMS_Update_Recv_Msg_Type));
+				SP_BMS_Update_Query(pUpdateMsgSend, updateMsgSendLen, (UINT8*)(&pUpdateMsgRecv), 0, 500);
+				osDelay(50);
+				
+				resetCount++;
+				if(resetCount>=2)
+				{
+					updateStep = UPDATE_STEP_DOWNLOAD_BREAK_OFF;
+					resetCount = 0;
+				}
+				else
+				{
+					updateStep = UPDATE_STEP_PREPARE_SEND_DATA_LEN;
+				}
+			#ifdef USING_PRINTF
+				printf("update error!!\n rest and start send data lenth again!!\n continue update!\n");
+			#endif
+				break;
+			case UPDATE_STEP_DOWNLOAD_BREAK_OFF:
+				dataLen = 1;
+				updateMsgSendLen = 8;
+				pUpdateMsgSend[0] = 0xEB; //start flag
+				pUpdateMsgSend[1] = 0x01;	//add flag
+				pUpdateMsgSend[2] = 0x00; //write
+				pUpdateMsgSend[3] = 0x04;	//data len
+				pUpdateMsgSend[4] = 0x81;	//cmd
+				pUpdateMsgSend[5] = 0xBB;	//data
+				pUpdateMsgSend[6] = 0x40;	//check
+				pUpdateMsgSend[7] = 0xF5;	//end flag
+				memset((UINT8*)(&pUpdateMsgRecv) , 0, sizeof(BMS_Update_Recv_Msg_Type));
+				SP_BMS_Update_Query(pUpdateMsgSend, updateMsgSendLen, (UINT8*)(&pUpdateMsgRecv), 0, 500);
+				osDelay(50);
+				updateStep = UPDATE_STEP_CHECK_VERSION;
+				Cycle_conut++;
+				break;
+			case UPDATE_STEP_ERROR:
+				updateStep = UPDATE_STEP_CHECK_VERSION;
+				printf("update error end\n");
+				bmsUpdateFlag = 0;
+			break;
+
+			default:
+				updateStep = UPDATE_STEP_CHECK_VERSION;
+				printf("update default end\n");
+				bmsUpdateFlag = 0;
+			break;
+		}
+	}
+}
+
+UINT8 SP_BMS_Update_Query(UINT8* pSend,UINT32 sendLen, UINT8* pRead, UINT32 readLen, UINT32 timeout)
+{
+
+	UINT8 timeCount = 0;
+	UINT8 j=0;
+	USARTdrv->Send(pSend,sendLen);
+	#ifdef USING_PRINTF
+		printf("query in:");
+		for(j=0;j<sendLen;j++)
+		{
+			printf("%x ",*(pSend+j));
+		}
+		printf("\n");	
+	#endif
+	if(readLen>0)
+	{
+		USARTdrv->Receive(pRead,readLen);         
+		while((isRecvTimeout == false) && (isRecvComplete == false))
+		{
+			timeCount++;
+			osDelay(100);
+			if (timeCount>=timeout/100)
+			{
+				timeCount =0;
+				isRecvTimeout = true;
+				break;
+			}
+		}
+		#ifdef USING_PRINTF
+			printf("\nanswer in:");
+			for(j=0;j<readLen;j++)
+			{
+				printf("%x ",*(pRead+j));
+			}
+			printf("\n");
+		#endif	
+		if (isRecvComplete == true)
+		{
+			isRecvComplete = false;
+			if(*(pRead+0)!=0xEB)
+			{
+				USARTdrv->Uninitialize();
+				osDelay(100);
+				USARTdrv->Initialize(USART_callback);
+				USARTdrv->PowerControl(ARM_POWER_FULL);
+				USARTdrv->Control(ARM_USART_MODE_ASYNCHRONOUS |
+						ARM_USART_DATA_BITS_8 |
+						ARM_USART_PARITY_NONE |
+						ARM_USART_STOP_BITS_1 |
+						ARM_USART_FLOW_CONTROL_NONE, 9600);
+				#ifdef USING_PRINTF
+					printf("\nuart reset in \n");	
+				#endif
+				return  0;
+			}
+			return readLen;
+		}
+		else
+		{
+			memset(pRead,0x00,readLen);
+			isRecvTimeout = false;
+			return 0;
+		}
+	}
+	else
+	{
+			return 1;
+	}
+}
+UINT8 SP_BMS_Update_CheckSUM(UINT8* pSendData,UINT8 len)
+{
+	UINT8 ret = 0;
+	UINT8 i=0;
+	for(i=0;i<len;i++)
+	{
+			ret +=*(pSendData+i);
+	}
+	return ret&0xFF;
+}
+//________________________________________________________________________________
+updateBMSStatus MS_BMS_Update_Service() //美顺BMS升级服务
+{
+	#ifdef USING_PRINTF
+		UINT8 ii = 0;
+	#endif
+	
+	UINT8 errorCount = 0;	
+	UINT16 currentPackage = 0;	
+	UINT32 updateDataTotalByteLen = 0;
+	UINT16 updateDataPackageCount = 0;
+	UINT8  ReadNVMTemp[64];
+	UpdateStep_MS_BMS updateStep = MS_UPDATE_STEP_SEND_FIRMWARE_UPDATE_REQUEST_AND_JUMP_TO_BOOTLOADER;	
+	
+	
+	UINT16 i,j=0;
+	UINT8 dataLen = 0;
+	UINT8 ret0 = 0;
+	updateBMSStatus ret = updateFailed;
+		
+	UINT8 pUpdateMsgSend[80];
+	UINT32 updateMsgSendLen = 0;
+	UINT32 updateMsgReadLen = 0;
+	
+	BOOL bmsUpdateFlag = TRUE;
+	UINT8 bmsAnswerMsg[8];
+	
+	//static UpdateStep step = UPDATE_STEP_CHECK_VERSION;
+	UINT8 Cycle_conut = 0;
+	UINT16 CRCtemp = 0;
+	UINT8 headerLen = 5;
+
+	UINT8 checkSum = 0x00;
+	UINT8 checkSumCal = 0x00;
+	UINT8 tempLen = 0x00;	
+
+	BSP_QSPI_Read_Safe(&checkSum,FLASH_BMS_FOTA_START_ADDR,1);
+
+	memset(ReadNVMTemp, 0, 64);
+	BSP_QSPI_Read_Safe(ReadNVMTemp, FLASH_BMS_FOTA_START_ADDR+1, 4);  //data
+
+	updateDataTotalByteLen = ((ReadNVMTemp[0]<<24)&0xFF000000) | ((ReadNVMTemp[1]<<16)&0xFF0000) | ((ReadNVMTemp[2]<<8)&0xFF00) | (ReadNVMTemp[3]&0xFF) ;
+	updateDataPackageCount = (updateDataTotalByteLen+(64-1))/64;  //进一法 e = (a+(b-1))/b	
+
+	for(i=0; i<((updateDataTotalByteLen+4)+(64-1))/64;i++)
+	{
+		memset(ReadNVMTemp, 0, 64);
+		if((i+1)*64 < (updateDataTotalByteLen+4))
+		{	
+			tempLen = 64;
+			BSP_QSPI_Read_Safe(ReadNVMTemp,FLASH_BMS_FOTA_START_ADDR+1+i*64,64);
+		}
+		else
+		{
+			tempLen = (updateDataTotalByteLen+4) - i*64;
+			BSP_QSPI_Read_Safe(ReadNVMTemp,FLASH_BMS_FOTA_START_ADDR+1+i*64,tempLen);
+		}
+		
+		for(j = 0; j< tempLen; j++)
+		{
+			checkSumCal = (checkSumCal + ReadNVMTemp[j]) & 0xFF;
+		}
+		//osDelay(10);
+	}
+	if(checkSum != checkSumCal)
+	{
+		#ifdef USING_PRINTF
+			printf("checksum error: checksum = %x, checksumCal = %x\n",checkSum,checkSumCal);
+		#endif
+		ret = updateErrorCheckSumError;	
+		return ret;
+	}
+	else
+	{
+		#ifdef USING_PRINTF
+			printf("checksum OK: checksum = %x, checksumCal = %x\n",checkSum,checkSumCal);
+		#endif
+	}
+
+	#ifdef USING_PRINTF
+		printf(" bmsUpdateFlag = %x, Cycle_conut = %x\n",bmsUpdateFlag,Cycle_conut);
+	#endif
+	while(bmsUpdateFlag && Cycle_conut<2)
+	{
+		#ifdef USING_PRINTF
+			printf("update ms bms step %d\n:",updateStep);				
+		#endif
+		switch (updateStep)
+		{
+			
+			case MS_UPDATE_STEP_SEND_FIRMWARE_UPDATE_REQUEST_AND_JUMP_TO_BOOTLOADER:  //0x01				
+				dataLen = 0x00;
+				updateMsgSendLen = 6+dataLen;
+				updateMsgReadLen = 8;
+				
+				pUpdateMsgSend[0] = 0x01; //node byte
+				pUpdateMsgSend[1] = 0x40;	//func byte
+				pUpdateMsgSend[2] = updateStep; //cmd byte
+				pUpdateMsgSend[3] = dataLen;	//data len
+											//no data type
+				CRCtemp = MS_BMS_Update_CRC16(pUpdateMsgSend, 4);
+				pUpdateMsgSend[4] = (CRCtemp>>8)&0xFF; // CRC High
+				pUpdateMsgSend[5] = CRCtemp&0xFF;		//CRC Low
+				
+				memset((UINT8*)(bmsAnswerMsg) , 0, 8);
+				ret0 = MS_BMS_Update_Query(pUpdateMsgSend, updateMsgSendLen, (UINT8*)(bmsAnswerMsg), updateMsgReadLen, 500);
+				#ifdef USING_PRINTF
+				printf("update step 1 answer,updateMsgReadLen = %x:\n",updateMsgReadLen);
+				
+				 for(ii=0;ii<updateMsgReadLen;ii++)
+					printf("%x ",bmsAnswerMsg[ii]);
+
+					printf("\nret0 = %d",ret0);
+					printf("\n");
+				#endif
+				if(ret0!=0)
+				{
+					if(bmsAnswerMsg[0] == 0x01 && bmsAnswerMsg[1] == 0x40)  // node and func byte
+					{
+						if(bmsAnswerMsg[2] == MS_UPDATE_STEP_FIRMWARE_UPDATE_REQUEST_ANSWER && bmsAnswerMsg[3] == 0x02)	//answer cmd byte:0x02, answer data len:0x02
+						{
+							if(bmsAnswerMsg[4] == 0x00)	//answer data byte1
+							{
+								if(bmsAnswerMsg[5] == 0x00)	//answer data byte2
+								{
+									updateStep = MS_UPDATE_STEP_SEND_FIRMWARE_INFO;
+									errorCount = 0;
+								}
+							}
+							else if(bmsAnswerMsg[4] == 0x01) //不允许升级
+							{
+								if(bmsAnswerMsg[5] == 0x01)//电量过低
+								{
+									updateStep = MS_UPDATE_STEP_ERROR;
+									ret = updateErrorBMSPowerLow;
+								}
+								else if(bmsAnswerMsg[5] == 0x02)//电池存在保护状态不允许升级
+								{
+									updateStep = MS_UPDATE_STEP_ERROR;
+									ret = updateErrorBMSWarningProtect;
+								}
+								else if(bmsAnswerMsg[5] == 0x03) //不支持升级
+								{
+									updateStep = MS_UPDATE_STEP_ERROR;
+									ret = updateErrorBMSNotSurport;
+								}
+								else if(bmsAnswerMsg[5] == 0x04) //当前电池处于充放电状态
+								{
+									updateStep = MS_UPDATE_STEP_ERROR;
+									ret = updateErrorBMSWorkState;
+								}
+								else
+								{
+									errorCount++;
+								}
+							}						
+						}
+						else
+						{
+							errorCount++;
+						}
+					}
+					else
+					{
+						errorCount++;
+					}
+				}			
+				else
+				{
+					errorCount++;
+				}
+
+				if(errorCount>10)
+				{
+					updateStep = MS_UPDATE_STEP_ERROR;
+					errorCount = 0;
+				}								
+				osDelay(50);
+				printf(" step 1 ret = %d\n",ret);
+				break;
+			case MS_UPDATE_STEP_SEND_FIRMWARE_INFO:  //0x03
+				dataLen = 52;
+				updateMsgSendLen = 6+dataLen;
+				updateMsgReadLen = 7;
+				pUpdateMsgSend[0] = 0x01; //node byte
+				pUpdateMsgSend[1] = 0x40;	//func byte
+				pUpdateMsgSend[2] = updateStep; //cmd byte
+				pUpdateMsgSend[3] = dataLen;	//data len
+
+				memset(ReadNVMTemp, 0, 64);
+				BSP_QSPI_Read_Safe(ReadNVMTemp, FLASH_BMS_FOTA_START_ADDR+headerLen, 16);	//data
+				MEMCPY(&pUpdateMsgSend[4], ReadNVMTemp, 16);  //厂家信息,未开启校验
+				MEMCPY(&pUpdateMsgSend[4+16], ReadNVMTemp, 16);	//保护板硬件序列号,未开启校验
+				pUpdateMsgSend[4+16*2 + 0] = (updateDataTotalByteLen>>24)&0xFF;	//固件包大小
+				pUpdateMsgSend[4+16*2 + 1] = (updateDataTotalByteLen>>16)&0xFF;
+				pUpdateMsgSend[4+16*2 + 2] = (updateDataTotalByteLen>>8)&0xFF;
+				pUpdateMsgSend[4+16*2 + 3] = (updateDataTotalByteLen)&0xFF;				
+				MEMCPY(&pUpdateMsgSend[4+16*2+4], ReadNVMTemp, 16); // 固件包头信息,未开启校验
+				
+				CRCtemp = MS_BMS_Update_CRC16(pUpdateMsgSend, 4+dataLen);
+				
+				pUpdateMsgSend[4+dataLen] = (CRCtemp>>8)&0xFF; // CRC High
+				pUpdateMsgSend[5+dataLen] = CRCtemp&0xFF;		//CRC Low
+				
+				memset((UINT8*)(bmsAnswerMsg) , 0, 8);
+				ret0 = MS_BMS_Update_Query(pUpdateMsgSend, updateMsgSendLen, (UINT8*)(bmsAnswerMsg), updateMsgReadLen, 500);
+				#ifdef USING_PRINTF
+				printf("update step 3 answer:\n");
+				 for(ii=0;ii<updateMsgReadLen;ii++)
+					printf("%x ",bmsAnswerMsg[ii]);
+
+					printf("\nret0 = %d",ret0);
+					printf("\n");
+				#endif
+				if(ret0!=0)
+				{
+					if(bmsAnswerMsg[0] == 0x01 && bmsAnswerMsg[1] == 0x40)  // node and func byte
+					{
+						if(bmsAnswerMsg[2] == MS_UPDATE_STEP_FIRMWARE_INFO_CHECK_AND_UPDATE_REQEST_ANSWER && bmsAnswerMsg[3] == 0x01)	//answer cmd byte:0x04, answer data len:0x01
+						{
+							if(bmsAnswerMsg[4] == 0x00)	//answer data byte1
+							{								
+								updateStep = MS_UPDATE_STEP_EREASE_APP_FLASH_REQUEST;
+								errorCount = 0;
+							}
+							else if(bmsAnswerMsg[4] == 0x01) //厂家信息错误
+							{
+								errorCount++;
+								ret = updateErrorFirmwareInfoError;
+							}		
+							else if(bmsAnswerMsg[4] == 0x02) //硬件序列号不匹配
+							{
+								errorCount++;
+								ret = updateErrorFirmwareInfoError;
+							}
+							else if(bmsAnswerMsg[4] == 0x03) //固件大小超出范围
+							{
+								errorCount++;
+								ret = updateErrorFirmwareSizeError;
+							}
+							else if(bmsAnswerMsg[4] == 0x04) //固件包头信息错误
+							{
+								errorCount++;
+								ret = updateErrorFirmwareInfoError;
+							}
+							else
+							{
+								errorCount++;
+							}
+						}
+						else
+						{
+							errorCount++;
+						}
+					}
+					else
+					{
+						errorCount++;
+					}
+				}			
+				else
+				{
+					errorCount++;
+				}
+
+				if(errorCount>10)
+				{
+					updateStep = MS_UPDATE_STEP_ERROR;
+					errorCount = 0;
+				}		
+				printf(" step 3 ret = %d\n",ret);
+				osDelay(50);
+				break;
+			case MS_UPDATE_STEP_EREASE_APP_FLASH_REQUEST:  //0x05
+				dataLen = 0;
+				updateMsgSendLen = 6+dataLen;
+				updateMsgReadLen = 8;
+				pUpdateMsgSend[0] = 0x01; //node byte
+				pUpdateMsgSend[1] = 0x40;	//func byte
+				pUpdateMsgSend[2] = updateStep; //cmd byte
+				pUpdateMsgSend[3] = dataLen;	//data len				
+				
+				CRCtemp = MS_BMS_Update_CRC16(pUpdateMsgSend, 4+dataLen);
+				
+				pUpdateMsgSend[4+dataLen] = (CRCtemp>>8)&0xFF; // CRC High
+				pUpdateMsgSend[5+dataLen] = CRCtemp&0xFF;		//CRC Low
+				
+				memset((UINT8*)(bmsAnswerMsg) , 0, 8);
+				ret0 = MS_BMS_Update_Query(pUpdateMsgSend, updateMsgSendLen, (UINT8*)(bmsAnswerMsg), updateMsgReadLen, 500);
+				#ifdef USING_PRINTF
+				printf("update step 5 answer:\n");
+				 for(ii=0;ii<updateMsgReadLen;ii++)
+					printf("%x ",bmsAnswerMsg[ii]);
+
+					printf("\nret0 = %d",ret0);
+					printf("\n");
+				#endif
+				if(ret0!=0)
+				{
+					if(bmsAnswerMsg[0] == 0x01 && bmsAnswerMsg[1] == 0x40)  // node and func byte
+					{
+						if(bmsAnswerMsg[2] == MS_UPDATE_STEP_EREASE_FLASH_ANSWER && bmsAnswerMsg[3] == 0x02)	//answer cmd byte:0x06, answer data len:0x02
+						{
+							if(bmsAnswerMsg[4] == 0x00)	//answer data byte1, erease successed
+							{								
+								updateStep = MS_UPDATE_STEP_SEND_UPDATE_DATA; //0x07
+								errorCount = 0;
+							}
+							else if(bmsAnswerMsg[4] == 0x01) //擦除失败
+							{
+								errorCount++;
+								ret = updateErrorAppErease;
+							}							
+							else
+							{
+								errorCount++;
+							}
+						}
+						else
+						{
+							errorCount++;
+						}
+					}
+					else
+					{
+						errorCount++;
+					}
+				}			
+				else
+				{
+					errorCount++;
+				}
+
+				if(errorCount>10)
+				{
+					updateStep = MS_UPDATE_STEP_ERROR;
+					errorCount = 0;
+				}								
+				osDelay(50);
+				break;
+			case MS_UPDATE_STEP_SEND_UPDATE_DATA:  //0x07
+				
+				updateMsgReadLen = 7;
+				pUpdateMsgSend[0] = 0x01; //node byte
+				pUpdateMsgSend[1] = 0x40;	//func byte
+				pUpdateMsgSend[2] = updateStep; //cmd byte
+				
+				for(i = 0; i < updateDataPackageCount ; i++ )	
+				{					
+					
+
+					memset(ReadNVMTemp, 0, 64);
+					
+					if((i+1)*64 < (updateDataTotalByteLen))
+					{	
+						tempLen = 64;
+						BSP_QSPI_Read_Safe(ReadNVMTemp,FLASH_BMS_FOTA_START_ADDR+headerLen+i*64,64);
+					}
+					else
+					{
+						tempLen = (updateDataTotalByteLen+4) - i*64;
+						BSP_QSPI_Read_Safe(ReadNVMTemp,FLASH_BMS_FOTA_START_ADDR+headerLen+i*64,tempLen);
+					}
+
+					CRCtemp = MS_BMS_Update_CRC16(ReadNVMTemp, tempLen);
+
+					dataLen = tempLen+6;  //data len =count(2+2 byte) + crc(2byte) +  update data len
+					updateMsgSendLen = 6+dataLen; // updateMsgSendLen = data len + header len(6byte)
+
+					pUpdateMsgSend[3] = dataLen;	//data len
+					
+					pUpdateMsgSend[4] = ((i+1)>>8)&0xFF;  //当前包序号,大端模式
+					pUpdateMsgSend[5] = (i+1)&0xFF;
+
+					pUpdateMsgSend[6] = (updateDataPackageCount>>8)&0xFF;
+					pUpdateMsgSend[7] = updateDataPackageCount&0xFF;
+					pUpdateMsgSend[8] = (CRCtemp>>8)&0xFF; // data CRC High
+					pUpdateMsgSend[9] = CRCtemp&0xFF;		//data CRC Low					
+					
+					MEMCPY(&pUpdateMsgSend[4+6], ReadNVMTemp, 64);  //升级数据,64字节
+					
+					
+					CRCtemp = MS_BMS_Update_CRC16(pUpdateMsgSend, 4+dataLen);
+					
+					pUpdateMsgSend[4+dataLen] = (CRCtemp>>8)&0xFF; // CRC High
+					pUpdateMsgSend[5+dataLen] = CRCtemp&0xFF;		//CRC Low
+					
+					memset((UINT8*)(bmsAnswerMsg) , 0, 8);
+					ret0 = MS_BMS_Update_Query(pUpdateMsgSend, updateMsgSendLen, (UINT8*)(bmsAnswerMsg), updateMsgReadLen, 500);
+					#ifdef USING_PRINTF
+						printf("update step 7 answer:\n");
+					 for(ii=0;ii<updateMsgReadLen;ii++)
+						printf("%x ",bmsAnswerMsg[ii]);
+
+						printf("\nret0 = %d",ret0);
+						printf("\n");
+					#endif
+					if(ret0!=0)
+					{
+						if(bmsAnswerMsg[0] == 0x01 && bmsAnswerMsg[1] == 0x40)  // node and func byte
+						{
+							if(bmsAnswerMsg[2] == MS_UPDATE_STEP_UPDATE_DATA_WRITE_ANSWER && bmsAnswerMsg[3] == 0x01)	//answer cmd byte:0x04, answer data len:0x01
+							{
+								if(bmsAnswerMsg[4] == 0x00)	//answer data byte1,接收并操作成功
+								{								
+									updateStep = MS_UPDATE_STEP_EREASE_APP_FLASH_REQUEST;
+									errorCount = 0;
+								}
+								else if(bmsAnswerMsg[4] == 0x01) //固件块校验失败
+								{
+									errorCount=10;
+									ret = updateErrorPackageCRC;
+								}		
+								else if(bmsAnswerMsg[4] == 0x02) //烧写失败
+								{
+									errorCount=10;
+									ret = updateErrorPackageWrite;
+								}
+								else if(bmsAnswerMsg[4] == 0x03) //固件块编号异常
+								{
+									errorCount=10;
+									ret = updateErrorPackageNo;
+								}								
+								else
+								{
+									errorCount=10;
+								}
+							}
+							else
+							{
+								errorCount=10;
+							}
+						}
+						else
+						{
+							errorCount=10;
+						}
+					}			
+					else
+					{
+						errorCount=10;
+					}
+
+					if(errorCount>=10)
+					{
+						updateStep = MS_UPDATE_STEP_ERROR;
+						errorCount = 0;
+						i--;
+						break;
+					}								
+					osDelay(50);
+				}
+				if(i == updateDataPackageCount)
+				{
+					updateStep = MS_UPDATE_STEP_SEND_UPDATE_DATA_END_AND_JUMP_TO_APP;
+				}
+				break;
+			case MS_UPDATE_STEP_SEND_UPDATE_DATA_END_AND_JUMP_TO_APP:  //0x09
+				dataLen = 0x00;
+				updateMsgSendLen = 6+dataLen;
+				updateMsgReadLen = 7;
+				
+				pUpdateMsgSend[0] = 0x01; //node byte
+				pUpdateMsgSend[1] = 0x40;	//func byte
+				pUpdateMsgSend[2] = updateStep; //cmd byte
+				pUpdateMsgSend[3] = dataLen;	//data len
+											//no data type
+				CRCtemp = MS_BMS_Update_CRC16(pUpdateMsgSend, 4);
+				pUpdateMsgSend[4] = (CRCtemp>>8)&0xFF; // CRC High
+				pUpdateMsgSend[5] = CRCtemp&0xFF;		//CRC Low
+				
+				memset((UINT8*)(bmsAnswerMsg) , 0, 8);
+				ret0 = MS_BMS_Update_Query(pUpdateMsgSend, updateMsgSendLen, (UINT8*)(bmsAnswerMsg), updateMsgReadLen, 500);
+				#ifdef USING_PRINTF
+				printf("update step 9 answer:\n");
+				 for(ii=0;ii<updateMsgReadLen;ii++)
+					printf("%x ",bmsAnswerMsg[ii]);
+
+					printf("\nret0 = %d",ret0);
+					printf("\n");
+				#endif
+				if(ret0!=0)
+				{
+					if(bmsAnswerMsg[0] == 0x01 && bmsAnswerMsg[1] == 0x40)  // node and func byte
+					{
+						if(bmsAnswerMsg[2] == MS_UPDATE_STEP_JUMP_TO_APP_ANSWER && bmsAnswerMsg[3] == 0x01)	//answer cmd byte:0x0A, answer data len:0x01
+						{
+							if(bmsAnswerMsg[4] == 0x00)	//answer data byte1, update succeed
+							{
+								errorCount = 0;
+								updateStep = MS_UPDATE_STEP_READ_CURRENT_RUNNING_MODE; //0x0B
+							}
+							else if(bmsAnswerMsg[4] == 0x01) //升级失败
+							{
+								errorCount = 10;
+								ret = updateFailed;
+							}						
+						}
+						else
+						{
+							errorCount++;
+						}
+					}
+					else
+					{
+						errorCount++;
+					}
+				}			
+				else
+				{
+					errorCount++;
+				}
+
+				if(errorCount>=10)
+				{
+					updateStep = MS_UPDATE_STEP_ERROR;
+					errorCount = 0;
+				}								
+				osDelay(50);
+				break;
+			case MS_UPDATE_STEP_READ_CURRENT_RUNNING_MODE:  //0x0B
+				dataLen = 0x00;
+				updateMsgSendLen = 6+dataLen;
+				updateMsgReadLen = 8;
+				
+				pUpdateMsgSend[0] = 0x01; //node byte
+				pUpdateMsgSend[1] = 0x40;	//func byte
+				pUpdateMsgSend[2] = updateStep; //cmd byte
+				pUpdateMsgSend[3] = dataLen;	//data len
+											//no data type
+				CRCtemp = MS_BMS_Update_CRC16(pUpdateMsgSend, 4);
+				pUpdateMsgSend[4] = (CRCtemp>>8)&0xFF; // CRC High
+				pUpdateMsgSend[5] = CRCtemp&0xFF;		//CRC Low
+				
+				memset((UINT8*)(bmsAnswerMsg) , 0, 8);
+				ret0 = MS_BMS_Update_Query(pUpdateMsgSend, updateMsgSendLen, (UINT8*)(bmsAnswerMsg), updateMsgReadLen, 500);
+				#ifdef USING_PRINTF
+				printf("update step A answer:\n");
+				 for(ii=0;ii<updateMsgReadLen;ii++)
+					printf("%x ",bmsAnswerMsg[ii]);
+
+					printf("\nret0 = %d",ret0);
+					printf("\n");
+				#endif
+				if(ret0!=0)
+				{
+					if(bmsAnswerMsg[0] == 0x01 && bmsAnswerMsg[1] == 0x40)  // node and func byte
+					{
+						if(bmsAnswerMsg[2] == MS_UPDATE_STEP_CURRENT_RUNNING_MODE_ANSWER && bmsAnswerMsg[3] == 0x02)	//answer cmd byte:0x0C, answer data len:0x02
+						{
+							if(bmsAnswerMsg[4] == 0x01)	//answer data byte1, update succeed, app is running
+							{
+								errorCount = 0;
+								updateStep = MS_UPDATE_STEP_END;
+							}
+							else if(bmsAnswerMsg[4] == 0x00) //update failed , boot is running,error
+							{
+								errorCount = 10;
+							}						
+						}
+						else
+						{
+							errorCount++;
+						}
+					}
+					else
+					{
+						errorCount++;
+					}
+				}			
+				else
+				{
+					errorCount++;
+				}
+
+				if(errorCount>=3)
+				{
+					updateStep = MS_UPDATE_STEP_ERROR;
+					errorCount = 0;
+				}								
+				osDelay(50);
+				break;
+			case MS_UPDATE_STEP_END: //0x0D
+				errorCount = 0;
+				bmsUpdateFlag = FALSE;
+				ret = updateOK;
+				break;
+			case MS_UPDATE_STEP_ERROR:	//0x0E
+				errorCount = 0;
+				bmsUpdateFlag = true;
+				Cycle_conut++;
+				if(Cycle_conut>2)
+				{
+					ret = updateErrorTimeout;
+					bmsUpdateFlag = FALSE;
+				}
+				break;
+			default:
+				bmsUpdateFlag = FALSE;
+				break;
+		}
+	}
+	#ifdef USING_PRINTF
+		printf("last ret = %x\n",ret);
+	#endif
+	return ret;
+
+}
+UINT8 MS_BMS_Update_Query(UINT8* pSend,UINT32 sendLen, UINT8* pRead, UINT32 readLen, UINT32 timeout)
+{
+
+	UINT8 timeCount = 0;
+	UINT8 j=0;
+	USARTdrv->Send(pSend,sendLen);
+	#ifdef USING_PRINTF
+		printf("query in:");
+		for(j=0;j<sendLen;j++)
+		{
+			printf("%x ",*(pSend+j));
+		}
+		printf("\n");	
+	#endif
+	if(readLen>0)
+	{
+		USARTdrv->Receive(pRead,readLen);         
+		while((isRecvTimeout == false) && (isRecvComplete == false))
+		{
+			timeCount++;
+			osDelay(100);
+			if (timeCount>=timeout/100)
+			{
+				timeCount =0;
+				isRecvTimeout = true;
+				break;
+			}
+		}
+		#ifdef USING_PRINTF
+			printf("\nanswer in:");
+			for(j=0;j<readLen;j++)
+			{
+				printf("%x ",*(pRead+j));
+			}
+			printf("\n");
+		#endif	
+		if (isRecvComplete == true)
+		{
+			isRecvComplete = false;
+			if(*(pRead+0)!=0x01)
+			{
+				USARTdrv->Uninitialize();
+				osDelay(100);
+				USARTdrv->Initialize(USART_callback);
+				USARTdrv->PowerControl(ARM_POWER_FULL);
+				USARTdrv->Control(ARM_USART_MODE_ASYNCHRONOUS |
+						ARM_USART_DATA_BITS_8 |
+						ARM_USART_PARITY_NONE |
+						ARM_USART_STOP_BITS_1 |
+						ARM_USART_FLOW_CONTROL_NONE, 9600);
+				#ifdef USING_PRINTF
+					printf("\nuart reset in \n");	
+				#endif
+				return  0;
+			}
+			return readLen;
+		}
+		else
+		{
+			memset(pRead,0x00,readLen);
+			isRecvTimeout = false;
+			return 0;
+		}
+	}
+	else
+	{
+			return 1;
+	}
+}
+
+
+
+static void __invert_uint8(UINT8* dBuf, UINT8* srcBuf)
+{
+	 int i;
+	 UINT8 tmp[4];
+	 tmp[0] = 0;
+	 for (i = 0;i < 8;i++)
+	 {
+		  if(srcBuf[0] & (1 << i))
+		  {
+		   	tmp[0] |= 1<<(7-i);
+		  }
+	 }
+	 dBuf[0] = tmp[0];
+}
+
+
+static void __invert_uint16(UINT16* dBuf, UINT16* srcBuf)
+{
+	 int i;
+	 UINT16 tmp[4];
+	 tmp[0] = 0;
+	 for (i = 0;i < 16;i++)
+	 {
+		  if(srcBuf[0] & (1 << i))
+		  {
+		   	tmp[0] |= 1 << (15 - i);
+		  }
+	 }
+	 dBuf[0] = tmp[0];
+}
+
+UINT16 MS_BMS_Update_CRC16(UINT8* pSendData,UINT16 len)
+{
+	
+	UINT16 wCRCin = 0xFFFF;
+	UINT16 wCPoly = 0x8005;
+	UINT8 wChar = 0;
+	UINT16 crc_rslt = 0;
+	int i;
+	while (len--)
+	{
+		wChar = *(pSendData++);
+		__invert_uint8(&wChar, &wChar);
+		wCRCin ^= (wChar << 8);
+		for (i = 0;i < 8;i++)
+		{
+			if(wCRCin & 0x8000)
+			{
+				wCRCin = (wCRCin << 1) ^ wCPoly;
+			}
+			else
+			{
+				wCRCin = wCRCin << 1;
+			}
+		}
+	}
+	__invert_uint16(&wCRCin, &wCRCin);
+	crc_rslt = ((wCRCin << 8) & 0xFF00) | ((wCRCin >> 8) & 0x00FF);
+	return (crc_rslt);
+}
+
+UINT8 BmsErrorDecode(UINT32 battWarningState)
+{
+	UINT16 ErrorNumTemp;
+	UINT8 ret;
+	if(battWarningState==0)
+	{
+		return 0;
+	}
+	else
+	{
+		if(osOK==osMutexAcquire(Error_Mutex, 100))
+		{
+			ret = ((battWarningState) & 0x01) == 1 ;
+			if (ret)
+			{
+				ErrorNumTemp = 7;
+				PutErrorNum((UINT16 *)ErrorNum,sizeof(ErrorNum),ErrorNumTemp);
+				//str += "ERROR:存在电芯过放告警故障!!\n";单体电压过低
+			}
+
+			ret = ((battWarningState >> 1) & 0x01) == 1 ;
+			if (ret)
+			{
+				ErrorNumTemp = 10;
+				PutErrorNum((UINT16 *)ErrorNum,sizeof(ErrorNum),ErrorNumTemp);
+				//str += "ERROR:存在总电压过放告警故障!!\n";总电压过低
+			}
+
+			ret = ((battWarningState >> 2) & 0x01) == 1 ;
+			if (ret)
+			{
+				ErrorNumTemp = 8;
+				PutErrorNum((UINT16 *)ErrorNum,sizeof(ErrorNum),ErrorNumTemp);
+				//str += "ERROR:存在电芯过压告警故障!!\n";
+			}
+
+			ret = ((battWarningState >> 3) & 0x01) == 1 ;
+			if (ret)
+			{
+				ErrorNumTemp = 11;
+				PutErrorNum((UINT16 *)ErrorNum,sizeof(ErrorNum),ErrorNumTemp);
+				//str += "ERROR:存在总电压过压告警故障!!\n";
+			}
+
+			ret = ((battWarningState >> 4) & 0x01) == 1 ;
+			if (ret)
+			{
+				ErrorNumTemp = 12;
+				PutErrorNum((UINT16 *)ErrorNum,sizeof(ErrorNum),ErrorNumTemp);
+				//str += "ERROR:存在放电过流告警故障!!\n";
+			}
+
+			ret = ((battWarningState >> 5) & 0x01) == 1 ;
+			if (ret)
+			{
+				ErrorNumTemp = 13;
+				PutErrorNum((UINT16 *)ErrorNum,sizeof(ErrorNum),ErrorNumTemp);
+				//str += "ERROR:存在充电过流告警故障!!\n";
+			}
+
+			ret = ((battWarningState >> 6) & 0x01) == 1 ;
+			if (ret)
+			{
+				ErrorNumTemp = 2;
+				PutErrorNum((UINT16 *)ErrorNum,sizeof(ErrorNum),ErrorNumTemp);
+				//str += "ERROR:存在放电过温告警故障!!\n";
+			}
+
+			ret = ((battWarningState >> 7) & 0x01) == 1 ;
+			if (ret)
+			{
+				ErrorNumTemp = 2;
+				PutErrorNum((UINT16 *)ErrorNum,sizeof(ErrorNum),ErrorNumTemp);
+				//str += "ERROR:存在充电过温告警故障!!\n";
+			}
+
+			ret = ((battWarningState >> 8) & 0x01) == 1 ;
+			if (ret)
+			{
+				//str += "ERROR:存在环境高温告警故障!!\n";
+			}
+
+			ret = ((battWarningState >> 9) & 0x01) == 1 ;
+			if (ret)
+			{
+				//str += "ERROR:存在环境低温告警故障!!\n";
+			}
+
+			ret = ((battWarningState >> 10) & 0x01) == 1 ;
+			if (ret)
+			{
+				ErrorNumTemp = 27;
+				PutErrorNum((UINT16 *)ErrorNum,sizeof(ErrorNum),ErrorNumTemp);
+				//str += "ERROR:存在battSOC低告警故障!!\n";
+			}
+
+			ret = ((battWarningState >> 11) & 0x01) == 1 ;
+			if (ret)
+			{
+				ErrorNumTemp = 3;
+				PutErrorNum((UINT16 *)ErrorNum,sizeof(ErrorNum),ErrorNumTemp);
+				//str += "ERROR:存在MOS高温告警故障!!\n";
+			}
+
+			ret = ((battWarningState >> 16) & 0x01) == 1;
+			if (ret)
+			{
+				ErrorNumTemp = 18;
+				PutErrorNum((UINT16 *)ErrorNum,sizeof(ErrorNum),ErrorNumTemp);
+				//str += "ERROR:存在温度采集失效/传感器故障!!\n";
+			}
+
+			ret = ((battWarningState >> 17) & 0x01) == 1;
+			if (ret)
+			{
+				ErrorNumTemp = 19;
+				PutErrorNum((UINT16 *)ErrorNum,sizeof(ErrorNum),ErrorNumTemp);
+				//str += "ERROR:存在电压采集失效/断线故障!!\n";
+			}
+
+			ret = ((battWarningState >> 18) & 0x01) == 1;
+			if (ret)
+			{
+				ErrorNumTemp = 17;
+				PutErrorNum((UINT16 *)ErrorNum,sizeof(ErrorNum),ErrorNumTemp);
+				//str += "ERROR:存在放电MOS失效故障!!\n";
+			}
+
+			ret = ((battWarningState >> 19) & 0x01) == 1;
+			if (ret)
+			{
+				ErrorNumTemp = 16;
+				PutErrorNum((UINT16 *)ErrorNum,sizeof(ErrorNum),ErrorNumTemp);
+				//str += "ERROR:存在充电MOS失效故障!!\n";
+			}
+
+			ret = ((battWarningState >> 20) & 0x01) == 1;
+			if (ret)
+			{
+				ErrorNumTemp = 22;
+				PutErrorNum((UINT16 *)ErrorNum,sizeof(ErrorNum),ErrorNumTemp);
+				//str += "ERROR:存在电芯不均衡告警!!\n";
+			}
+
+			ret = ((battWarningState >> 22) & 0x01) == 1;
+			if (ret)
+			{
+				ErrorNumTemp = 1;
+				PutErrorNum((UINT16 *)ErrorNum,sizeof(ErrorNum),ErrorNumTemp);
+				//str += "ERROR:存在放电低温告警故障!!\n";
+			}
+
+			ret = ((battWarningState >> 23) & 0x01) == 1 ;
+			if (ret)
+			{
+				ErrorNumTemp = 1;
+				PutErrorNum((UINT16 *)ErrorNum,sizeof(ErrorNum),ErrorNumTemp);
+				//str += "ERROR:存在充电低温告警故障!!\n";
+			}
+		}
+		else
+		{
+			#ifdef USING_PRINTF
+				printf("get Muxtex error\n");
+			#endif
+		}
+		osMutexRelease(Error_Mutex);
+	}
+	return 1;
+}

+ 9 - 12
src/app.c

@@ -1,23 +1,20 @@
 /****************************************************************************
  *
- * Copy right:   2021-, Copyrigths of RLWL Ltd.
- * File name:    app.h
- * Description:  App definition H file
+ * Copy right:   2021-, Copyrigths of RLWL Ltd.Chen J
+ * File name:    app.c
+ * Description:  App definition c file,主要负责内核启动以及各线程启动
  * History:      Rev3.0   2021-07-06
  *
  ****************************************************************************/
 #include "app.h"
 void appInit(void *arg)
 {
-    #ifdef USING_PRINTF1	
-    	printf("%s[%d]\r\n",__FUNCTION__, __LINE__);
-    #endif
-    // MainTaskInit(arg);
-    // AdcTaskInit();
-    // UartTaskInit(arg);
-    // GpsTaskInit();
-	// CANTaskInit(arg);
-    // TcpTaskInit(arg);
+    AppTaskMainInit(arg);
+    AppTaskTcpInit(arg);
+    AppTaskLedInit(arg);
+    AppTaskGpsInit(arg);
+    AppTaskUartInit(arg);
+    AppTaskCanInit(arg);
 }
 void main_entry(void) 
 {

+ 0 - 114
src/hal_module_adapter.c

@@ -2545,118 +2545,4 @@ BOOL NB_ADC_Get(UINT32* adcValue, ADC_CHANNEL_TYPE adcChannel)
   return TRUE;
  else
   return FALSE;
-}
-UINT8 LookUpRTtable(UINT32 R_value)
-{
-	UINT8 Temp_Table1[23] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22};
-	UINT8 Temp_Table2[217] = {23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,
-	49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,
-	84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,
-	115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,
-	142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,
-	169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,
-	196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,
-	223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239};
-	UINT32 R_Table1[23] = {202269,191063,180554,170694,161438,152746,144580,136905,129687,122898,116508,
-						110493,104827,99488,94455,89710,85233,81008,77019,73252,69693,66329,63148};
-	UINT16 R_Table2[217] = {
-	60140,57293,54599,52049,49633,47343,45174,43117,41166,39315,37558,35891,34307,32802,31373,
-	30014,28722,27493,26324,25211,24152,23144,22183,21268,20395,19564,18771,18015,17293,16604,
-	15947,15319,14720,14147,13600,13077,12577,12098,11641,11203,10784,10383,10000,9632,9280,8942,
-	8619,8309,8012,7727,7454,7191,6940,6698,6466,6244,6030,5825,5627,5438,5255,5080,4911,4749,4593,
-	4443,4299,4160,4026,3898,3773,3654,3539,3428,3321,3218,3119,3023,2931,2841,2755,2672,2592,2515,
-	2441,2369,2299,2232,2167,2104,2044,1985,1928,1874,1821,1769,1720,1672,1626,1581,1537,1495,1455,
-	1415,1377,1340,1305,1270,1236,1204,1172,1142,1112,1083,1056,1029,1002,977,952,928,905,883,861,
-	839,819,799,779,760,742,724,707,690,674,658,642,627,613,599,585,571,558,546,533,521,509,498,487,
-	476,466,455,445,436,426,417,408,399,391,382,374,366,359,351,344,337,330,323,316,310,304,298,292,
-	286,280,274,269,264,259,254,249,244,239,234,230,226,221,217,213,209,205,201,198,194,190,187,183,
-	180,177,174,171,168,165,162,159,156,153,151,148,145,143,141,138,136,133,131,129,127,125};
-	if(R_value>R_Table2[0])
-	{
-		if(R_value<=R_Table1[22])//判断是否超出表尾
-		{
-			return Temp_Table1[22];
-		}
-		else if(R_value>=R_Table1[0])//判断是否超出表头
-		{
-			return Temp_Table1[0];
-		}
-		else 
-		{
-			for(int i=0;i<23-1;i++)
-			{
-				if ((R_value<=R_Table1[i])&&(R_value>R_Table1[i+1]))//中间判断
-				{
-					return Temp_Table1[i];
-				}
-				else
-				{
-					continue;
-				} 
-				
-			}
-		}
-	}//R-1
-	else
-	{
-		if(R_value<=R_Table2[216])//判断是否超出表尾
-		{
-			return Temp_Table2[216];
-		}
-		else if(R_value>=R_Table2[0])//判断是否超出表头
-		{
-			return Temp_Table2[0];
-		}
-		else 
-		{
-			for(int i=0;i<217-1;i++)
-			{
-				if ((R_value<R_Table2[i])&&(R_value>=R_Table2[i+1]))//中间判断
-				{
-					return Temp_Table2[i+1];
-				}
-				else
-				{
-					continue;
-				} 
-				
-			}
-		}
-	}//R-2
-}
-
-UINT16 GetErrorNum(UINT16 *ErrorArray,UINT8 Errorlen)
-{
-	UINT16 OutNum;
-	OutNum = *(ErrorArray);
-	for(int i=0;i<Errorlen-1;i++)
-	{
-		*(ErrorArray+i) = *(ErrorArray+i+1);
-		if(*(ErrorArray+i+1)==0)
-			break;
-	}
-	return OutNum;
-}
-UINT8 PutErrorNum(UINT16 *ErrorArray,UINT8 Errorlen,UINT16 ErrorNum)
-{
-	for(int i=0;i<Errorlen;i++)
-	{
-		if(*(ErrorArray+i)==0)
-		{
-			*(ErrorArray+i) = ErrorNum;
-			return 0;
-		}
-		else
-		{
-			if(*(ErrorArray+i)==ErrorNum)
-			{
-				return 1;
-			}
-			else
-			{
-				continue;
-			}
-		}
-	}
-	return 2;
 }