/* * @Author : ChenJie * @Date : 2021-10-14 09:27:15 * @Version : V3.0 * @LastEditors : ChenJie * @LastEditTime : 2021-10-18 10:10:55 * @Description : 应用层函数定义区,UTF-8 * @FilePath : \PLAT\project\ec616_0h00\apps\qx_app\src\AppFunc.c */ #include "AppFunc.h" #include "numeric.h" #include "hal_module_adapter.h" /** * @brief : 故障代码处理函数,将故障代码进行排序并输出 * @param {*} * @return {*} */ void ErrorNumHandleFunc(void) { UINT16 ErrorArrayBuffer[20] = {0}; MEMCPY(ErrorArrayBuffer, sfmv_idx_fltCode, sfmd_num_fltNum * 2); BOOL isSorted; UINT16 temp = 0; for (UINT8 i = 0; i < sfmd_num_fltNum; i++) { isSorted = TRUE; //假设剩下的元素已经排序好了 for (UINT8 j = 0; j < sfmd_num_fltNum - i; j++) { if (ErrorArrayBuffer[j] < ErrorArrayBuffer[j + 1]) { temp = ErrorArrayBuffer[j]; ErrorArrayBuffer[j] = ErrorArrayBuffer[j + 1]; ErrorArrayBuffer[j + 1] = temp; isSorted = FALSE; //一旦需要交换数组元素,就说明剩下的元素没有排序好 } } if (isSorted) break; //如果没有发生交换,说明剩下的元素已经排序好了 } if (osOK == osMutexAcquire(Error_Mutex, 1)) { for (UINT8 index = 0; index < 20; index++) { if (ErrorArrayBuffer[index] != 0) { PutErrorNum((UINT16 *)ErrorNum, ErrorNumLength, (ErrorArrayBuffer[index] % 10000U)); } } } osMutexRelease(Error_Mutex); } /** * @brief : 租期到期日期计算函数 * @param {UINT8} *StartTimeArray * @param {UINT16} rentalDays * @param {UINT8} *ExpiryTimeArray * @return {*} */ void ExpiryTimeCal(UINT8 *StartTimeArray, UINT16 rentalDays, UINT8 *ExpiryTimeArray) { UINT8 lastday = 0; UINT8 year = 0, month = 0, hour = 0, minute = 0, second = 0; UINT16 day = 0; year = *(StartTimeArray + 0); month = *(StartTimeArray + 1); day = *(StartTimeArray + 2) + rentalDays; if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) { lastday = 31; } else if (month == 4 || month == 6 || month == 9 || month == 11) { lastday = 30; } else { if ((year % 400 == 0) || (year % 4 == 0 && year % 100 != 0)) lastday = 29; else lastday = 28; } while (day > lastday) { day -= lastday; month += 1; if (month > 12) { month -= 12; year += 1; } if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) { lastday = 31; } else if (month == 4 || month == 6 || month == 9 || month == 11) { lastday = 30; } else { if ((year % 400 == 0) || (year % 4 == 0 && year % 100 != 0)) lastday = 29; else lastday = 28; } } *(ExpiryTimeArray + 0) = year; *(ExpiryTimeArray + 1) = month; *(ExpiryTimeArray + 2) = day; *(ExpiryTimeArray + 3) = *(StartTimeArray + 3); *(ExpiryTimeArray + 4) = *(StartTimeArray + 4); *(ExpiryTimeArray + 5) = *(StartTimeArray + 5); return; } /** * @brief :租期到期判断函数 * @param {*} * @return {*} */ INT8 rentalEndDetectFunc(void) { OsaUtcTimeTValue TimeStracture; UTC8TimeType UTC8Time, ExpiryTime; UINT16 year; UINT8 month, day, hour, minute, sec; appGetSystemTimeUtcSync(&TimeStracture); year = (TimeStracture.UTCtimer1 & 0xffff0000) >> 16; month = (TimeStracture.UTCtimer1 & 0xff00) >> 8; day = TimeStracture.UTCtimer1 & 0xff; hour = (TimeStracture.UTCtimer2 & 0xff000000) >> 24; minute = (TimeStracture.UTCtimer2 & 0xff0000) >> 16; sec = (TimeStracture.UTCtimer2 & 0xff00) >> 8; UTCToBeijing((UTC8TimeType *)&UTC8Time, year, month, day, hour, minute, sec); if (UTC8Time.year > 2000) { #ifdef USING_PRINTF printf("retal Jug:%d %d %d %d,%d %d %d %d\n", UTC8Time.year, UTC8Time.month, UTC8Time.day, UTC8Time.hour, AppDataInfo.ExpiryTimeArray[0], AppDataInfo.ExpiryTimeArray[1], AppDataInfo.ExpiryTimeArray[2], AppDataInfo.ExpiryTimeArray[3]); #endif if (((UTC8Time.year - 0x07D0) & 0xFF) == AppDataInfo.ExpiryTimeArray[0]) //年份相等判定月份 { if (UTC8Time.month == AppDataInfo.ExpiryTimeArray[1]) //月份相等判定日期 { if (UTC8Time.day == AppDataInfo.ExpiryTimeArray[2]) //日期相等判定小时 { // if(UTC8Time.hour<=AppDataInfo.ExpiryTimeArray[3])//小时相等不锁定,小时超出锁定 // { // return 0; // } // else // { // return 1; // } return 0; } else if (UTC8Time.day > AppDataInfo.ExpiryTimeArray[2]) { return 1; } else if (UTC8Time.day < AppDataInfo.ExpiryTimeArray[2]) { return 0; } } else if (UTC8Time.month > AppDataInfo.ExpiryTimeArray[1]) //实际月份大于终止月份 { return 1; } else if (UTC8Time.month < AppDataInfo.ExpiryTimeArray[1]) //实际月份小于终止月份 { return 0; } } else if (((UTC8Time.year - 0x07D0) & 0xFF) > AppDataInfo.ExpiryTimeArray[0]) //实际年份大于终止年份 { return 1; } else if (((UTC8Time.year - 0x07D0) & 0xFF) < AppDataInfo.ExpiryTimeArray[0]) //年比较,实际年份小于终止年份 { return 0; } } else { return -1; //没有获取到时间返回 } } /** * @brief :电池是否业务锁定判断函数(锁定放电) * @param {*} * @return {*} */ void BattLockFunc(void) { if (AppDataInfo.RentalType == 0) //测试模式 { ; } else if (AppDataInfo.RentalType == 1) //零售模式 { if (AppDataInfo.RentalLock == TRUE) { AppDataInfo.UserLock = FALSE; AppDataInfo.RentalLock = FALSE; AppDataInfo.appDataModify = TRUE; } } else if (AppDataInfo.RentalType == 2) // 租赁模式 { INT8 ret = -1; ret = rentalEndDetectFunc(); if (ret == 1 && AppDataInfo.RentalLock == FALSE) //租期判定是否超期函数 { #ifdef USING_PRINTF printf("retal lock,%d\n", ret); #endif AppDataInfo.RentalLock = TRUE; AppDataInfo.appDataModify = TRUE; } else if (ret == 0 && AppDataInfo.RentalLock == TRUE) { #ifdef USING_PRINTF printf("retal unlock,%d\n", ret); #endif AppDataInfo.RentalLock = FALSE; AppDataInfo.appDataModify = TRUE; AppDataInfo.UserLock = FALSE; } } if (AppDataInfo.BattForceLock == FALSE) { if (AppDataInfo.RentalLock == FALSE && AppDataInfo.UserLock == FALSE) { AppDataInfo.BattLock = FALSE; AppDataInfo.appDataModify = TRUE; } else if (AppDataInfo.RentalLock == TRUE || AppDataInfo.UserLock == TRUE) { AppDataInfo.BattLock = TRUE; AppDataInfo.appDataModify = TRUE; } } else { AppDataInfo.BattLock = TRUE; AppDataInfo.appDataModify = TRUE; } return; } /** * @brief : 电池工作模式延时处理函数 * @param {UINT8} battWorkCurrentState * @return {*} */ void BattWorkDelayFunc(UINT8 battWorkCurrentState) { static UINT16 workDelayCounter = 0; if (battWorkCurrentState == BATT_IDLE_SYM && BattWorkStateDelay == BATT_DISCHARGE_SYM) //从放电转静置 10s延时 { workDelayCounter++; if (workDelayCounter >= 10) { workDelayCounter = 0; BattWorkStateDelay = battWorkCurrentState; } } else if (battWorkCurrentState == BATT_IDLE_SYM && BattWorkStateDelay == BATT_CHARGE_SYM) //从充电转静置10s延时 { workDelayCounter++; if (workDelayCounter >= 10) { workDelayCounter = 0; BattWorkStateDelay = battWorkCurrentState; } } else if (battWorkCurrentState == BATT_DISCHARGE_SYM && BattWorkStateDelay != BATT_DISCHARGE_SYM) //从 充电或者静置 转放电 1s延时 { workDelayCounter++; if (workDelayCounter >= 1) { workDelayCounter = 0; BattWorkStateDelay = battWorkCurrentState; } } else if (battWorkCurrentState == BATT_CHARGE_SYM && BattWorkStateDelay != BATT_CHARGE_SYM) //从 放电或者静置 转充电 30s延时 { workDelayCounter++; if (workDelayCounter >= 30) { workDelayCounter = 0; BattWorkStateDelay = battWorkCurrentState; } } else { BattWorkStateDelay = battWorkCurrentState; workDelayCounter = 0; } return; } /** * @brief : R-T查表函数 (需优化) * @param {UINT32} R_value * @return {*} */ 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 } /** * @brief : tcp校验函数 * @param {UINT8} *data * @param {UINT16} length * @return {*} */ UINT8 bcc_chk(UINT8 *data, UINT16 length) { UINT8 bcc_chk_return = 0x00; UINT16 count = 0; while (count < length) { bcc_chk_return ^= data[count]; count++; } return bcc_chk_return; } /** * @brief : 加热判断函数,根据当前状态判断是否需要改变状态 * @param {UINT8} *heaterSwitch * @param {UINT8} HeatForceControl * @return {*} */ BOOL BattHeaterSwitch(UINT8 *heaterSwitch, UINT8 HeatForceControl) { BOOL isNeedtoSwitch = FALSE; UINT8 currentSwitchState = 0; currentSwitchState = battHeatEnableState & 0x01; if (currentSwitchState == 0) //当前状态为关闭,判断是否应该开启 { if (tmsd_st_heatAct == 1) { *heaterSwitch = 1; isNeedtoSwitch = true; } } else //当前状态为开启,判断是否应该关闭 { if (tmsd_st_heatAct == 0) { *heaterSwitch = 0; isNeedtoSwitch = true; } } return isNeedtoSwitch; } /** * @brief : 蜂鸣器控制函数 * @param {UINT8} BuzzerPeriod * @param {float} DutyRatio * @return {*} */ void relayControlFunc(UINT8 BuzzerPeriod, float DutyRatio) { static UINT8 BuzzerTimer = 0; BuzzerTimer++; if (BuzzerTimer < (UINT8)(BuzzerPeriod * DutyRatio)) { relayControl(TRUE); } else if (BuzzerTimer >= (UINT8)(BuzzerPeriod * DutyRatio) && BuzzerTimer < BuzzerPeriod) { relayControl(FALSE); } else { relayControl(FALSE); BuzzerTimer = 0; } } /** * @brief : LED控制函数,根据不同状态进行LED显示 * @param {*} * @return {*} */ void LEDDisplay(void) { UINT8 LedBattSoc = 0; LedBattSoc = socd_pct_bcuSoc / 10; static UINT8 currentState = 0; static UINT8 LightTimer = 0; static UINT8 ErrorLightTimer = 0; UINT8 LEDFlashPeriod = 10; //1000ms float DutyRatio = 0.4; LightTimer++; ErrorLightTimer++; #ifdef USING_PRINTF1 printf("[%d]-%d-%d-%d\n", __LINE__, LightTimer, ErrorLightTimer, battSOC); #endif if (AppDataInfo.BattLock == TRUE) //电池整处于锁定状态 { if (LightTimer < (UINT8)(LEDFlashPeriod * 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); FaultDisplay(LED_TURN_ON); } else if (LightTimer >= (UINT8)(LEDFlashPeriod * DutyRatio) && LightTimer < LEDFlashPeriod) { 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); LightTimer = 0; } return; } else //电池未处于锁定状态 { if (currentState != AppDataInfo.BattLock) { currentState = AppDataInfo.BattLock; LightTimer = 0; } else if (UartErrorFlag == 1) //电池未收到UART信息,出现Uart故障 { if (LightTimer < (UINT8)(LEDFlashPeriod * 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); FaultDisplay(LED_TURN_ON); } else if (LightTimer >= (UINT8)(LEDFlashPeriod * DutyRatio) && LightTimer < LEDFlashPeriod) { 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); LightTimer = 0; } return; } else if (UartRecvFlag == 1) //电池接收到UART信息,且正确运行 { if (battWorkState == 0x02) //充电模式下,如果只有“SOC低故障”,那么就不显示故障灯 zhengchao20210713 add { if ((((battWarningState >> 10) & 0x01) == 0x01) && ((battWarningState & 0xFFFFFBFF) == 0x00)) return; } if (getbit(sfmd_st_fltAct, 1) == 1) //电池存在故障 { if (ErrorLightTimer < (UINT8)(LEDFlashPeriod * DutyRatio)) { FaultDisplay(LED_TURN_ON); } else if (ErrorLightTimer >= (UINT8)(LEDFlashPeriod * DutyRatio) && ErrorLightTimer < LEDFlashPeriod) { FaultDisplay(LED_TURN_OFF); } else { FaultDisplay(LED_TURN_OFF); ErrorLightTimer = 0; } } else { FaultDisplay(LED_TURN_OFF); ErrorLightTimer = 0; } if (battWorkState == 0 || battWorkState == 1) //静置或放电状态 { if (LedBattSoc <= 10) { if (LightTimer < (UINT8)(LEDFlashPeriod * 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)(LEDFlashPeriod * DutyRatio) && LightTimer < LEDFlashPeriod) { 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 (LedBattSoc > 10 && LedBattSoc <= 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 (LedBattSoc > 25 && LedBattSoc <= 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 (LedBattSoc > 50 && LedBattSoc <= 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 (LedBattSoc > 75 && LedBattSoc <= 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 (LedBattSoc <= 25) { if (LightTimer < (UINT8)(LEDFlashPeriod * 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)(LEDFlashPeriod * DutyRatio) && LightTimer < LEDFlashPeriod) { 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 (LedBattSoc > 25 && LedBattSoc <= 50) { if (LightTimer < (UINT8)(LEDFlashPeriod * 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)(LEDFlashPeriod * DutyRatio) && LightTimer < LEDFlashPeriod) { 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 (LedBattSoc > 50 && LedBattSoc <= 75) { if (LightTimer < (UINT8)(LEDFlashPeriod * 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)(LEDFlashPeriod * DutyRatio) && LightTimer < LEDFlashPeriod) { 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 (LedBattSoc > 75 && LedBattSoc <= 97) { if (LightTimer < (UINT8)(LEDFlashPeriod * 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)(LEDFlashPeriod * DutyRatio) && LightTimer < LEDFlashPeriod) { 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 (LedBattSoc > 97 && LedBattSoc <= 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); } } } } } /** * @brief : 串口数据解码函数 * @param {UINT8} *dataPtr * @return {*} */ BOOL uartBattInfoDecode(UINT8 *dataPtr) { UINT8 i = 0, temp = 0; INT8 BattCurrentNegFlag = 1; UINT8 TEMP_NUM = 0; UINT16 Batt_current; UINT8 BATT_CELL_VOL_NUM = 0, BATT_TEMP_NUM = 0; UINT32 Battsumvoltage = 0; BATT_CELL_VOL_NUM = (dataPtr[(0x00) * 2] << 8) | (dataPtr[(0x00) * 2 + 1]); BATT_TEMP_NUM = ((dataPtr[(0x01) * 2] << 8) | (dataPtr[(0x01) * 2 + 1])) - BMS_OTHER_TEMP; if ((AppDataInfo.BattCellCount != BATT_CELL_VOL_NUM || AppDataInfo.BattTempCount != BATT_TEMP_NUM) && (BATT_CELL_VOL_NUM != 0) && (BATT_TEMP_NUM != 0)) { AppDataInfo.appDataModify = TRUE; AppDataInfo.BattCellCount = BATT_CELL_VOL_NUM; AppDataInfo.BattTempCount = BATT_TEMP_NUM; } else { BATT_CELL_VOL_NUM = AppDataInfo.BattCellCount; BATT_TEMP_NUM = AppDataInfo.BattTempCount; } #ifdef USING_PRINTF1 printf("BattCellCount:%d,BATT_CELL_VOL_NUM:%d ", AppDataInfo.BattCellCount, BATT_CELL_VOL_NUM); printf("BattTempCount:%d,BATT_TEMP_NUM:%d ", AppDataInfo.BattTempCount, BATT_TEMP_NUM); #endif for (i = 0; i < BATT_CELL_VOL_NUM; i++) { battCellU[i] = (dataPtr[(0x02 + i) * 2] << 8) | dataPtr[(0x02 + i) * 2 + 1]; Battsumvoltage = Battsumvoltage + battCellU[i]; } battWorkState = (dataPtr[(0x03 + BATT_CELL_VOL_NUM) * 2 + 1]) & 0x03; //电池状态(原始数据),0表示静置,1表示放电,2表示充电 TEMP_NUM = BATT_TEMP_NUM + BMS_OTHER_TEMP; for (i = 0; i < BATT_TEMP_NUM; i++) { battCellTemp[i] = dataPtr[(0x06 + BATT_CELL_VOL_NUM + i) * 2 + 1]; } avrgCellVol = Battsumvoltage / BATT_CELL_VOL_NUM; 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]; chargerConnectState = (dataPtr[(0x03 + BATT_CELL_VOL_NUM) * 2 + 1] >> 2) & 0x01; //充电器连接状态,0表示未连接,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; BattCurrentNegFlag = -1; } else { //源码,结果为负 Batt_current = Batt_current / 10; BattCurrentNegFlag = -1; } } else //放电过程 { if (Batt_current > 0x8000) // 数据为负 { //求补码,结果为正 Batt_current = (UINT16)((UINT16)(~(Batt_current)) + 1); Batt_current = Batt_current / 10; BattCurrentNegFlag = 1; } else { //源码,结果为正 Batt_current = Batt_current / 10; BattCurrentNegFlag = 1; } } battI = Batt_current * 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]; #ifdef USING_PRINTF1 printf("[%d]-%x\n", __LINE__, (dataPtr[(0x09 + BATT_CELL_VOL_NUM + TEMP_NUM) * 2 + 1])); printf("[%d]-%x\n", __LINE__, (dataPtr[(0x1B + BATT_CELL_VOL_NUM + TEMP_NUM) * 2])); #endif temp = ((dataPtr[(0x09 + BATT_CELL_VOL_NUM + TEMP_NUM) * 2 + 1]) >> 1) & 0x03; battMOSSwitchState = ((temp & 0x01) << 1) | ((temp & 0x02) >> 1); if (AppDataInfo.BattLock == 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]); battProtectState = (dataPtr[(0x03 + BATT_CELL_VOL_NUM) * 2 + 0] << 24) | (dataPtr[(0x04 + BATT_CELL_VOL_NUM) * 2 + 0] << 16) | (dataPtr[(0x04 + BATT_CELL_VOL_NUM) * 2 + 1] << 8) | (dataPtr[(0x05 + BATT_CELL_VOL_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; AvgBattTemp = 0; UINT16 SumBattTemp = 0; for (i = 0; i < BATT_TEMP_NUM; i++) { SumBattTemp = SumBattTemp + battCellTemp[i]; maxCellTemp = max(maxCellTemp, battCellTemp[i]); minCellTemp = min(minCellTemp, battCellTemp[i]); } AvgBattTemp = (SumBattTemp - maxCellTemp - minCellTemp) / (BATT_TEMP_NUM - 2); nbSwVersion = APPSWVERSION; nbHwVersion = HWVERSION; return true; } /** * @brief : 获取故障码函数,从故障数组中获取故障码,并将之前的故障码向前移动 * @param {UINT16} *ErrorArray * @param {UINT8} Errorlen * @return {*} */ UINT16 GetErrorNum(UINT16 *ErrorArray, UINT8 Errorlen) { UINT16 OutNum; OutNum = *(ErrorArray); for (UINT8 i = 0; i < Errorlen - 1; i++) { *(ErrorArray + i) = *(ErrorArray + i + 1); if (*(ErrorArray + i + 1) == 0) break; } return OutNum; } /** * @brief : 故障码注入函数,将故障码写入到故障数组中,如果存在则不写入,如果存在则不写入 * @param {UINT16} *ErrorArray * @param {UINT8} Errorlen * @param {UINT16} ErrorNum * @return {*} */ UINT8 PutErrorNum(UINT16 *ErrorArray, UINT8 Errorlen, UINT16 ErrorNum) { for (UINT8 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; } /** * @brief : App运行数据存储函数 * @param {*} * @return {*} */ void SaveAppData(void) { OSAFILE fp = PNULL; UINT32 writeCount = 0; AppDataHeader AppDataHr; fp = OsaFopen(APP_DATAINFO_FILE_NAME, "wb"); //read & write if (OsaFseek(fp, 0, SEEK_SET) != 0) { #ifdef USING_PRINTF printf("Seek file failed [%d] \r\n", __LINE__); #endif OsaFclose(fp); return; } if (fp == PNULL) { #ifdef USING_PRINTF printf(" NVM, can't open/create NVM: 'qxappconfig.nvm', save NVM failed\n"); #endif return; } AppDataHr.fileBodySize = sizeof(AppDataInfo); AppDataHr.checkSum = OsaCalcCrcValue((UINT8 *)&AppDataInfo, sizeof(AppDataInfo)); writeCount = OsaFwrite(&AppDataHr, sizeof(AppDataHr), 1, fp); if (writeCount != 1) { #ifdef USING_PRINTF printf(" NVM: 'qxappconfig.nvm', write the file header failed\n"); #endif OsaFclose(fp); return; } AppDataInfo.appDataModify = FALSE; writeCount = OsaFwrite(&AppDataInfo, sizeof(AppDataInfo), 1, fp); if (writeCount != 1) { #ifdef USING_PRINTF printf(" NVM: 'qxappconfig.nvm', write the file body failed\n"); #endif OsaFclose(fp); return; } OsaFclose(fp); return; } /** * @brief : bcu数据存储函数 * @param {*} * @return {*} */ void SaveBcuData(void) { OSAFILE fp = PNULL; UINT32 writeCount = 0; BcuDataHeader BcuDataHr; fp = OsaFopen(BCU_DATAINFO_FILE_NAME, "wb"); //read & write if (OsaFseek(fp, 0, SEEK_SET) != 0) { OsaFclose(fp); return; } if (fp == PNULL) { return; } BcuDataHr.fileBodySize = sizeof(BcuDataInfo); BcuDataHr.checkSum = OsaCalcCrcValue((UINT8 *)&BcuDataInfo, sizeof(BcuDataInfo)); writeCount = OsaFwrite(&BcuDataHr, sizeof(BcuDataHr), 1, fp); if (writeCount != 1) { OsaFclose(fp); return; } BcuDataInfo.appDataModify = FALSE; writeCount = OsaFwrite(&BcuDataInfo, sizeof(BcuDataInfo), 1, fp); if (writeCount != 1) { OsaFclose(fp); return; } OsaFclose(fp); return; } /** * @brief : 运行数据加载函数,将运行数据进行加载,若新增了数据项,则保持前面数据项不动 * @param {*} * @return {*} */ void LoadAppData(void) { OSAFILE fp = PNULL; UINT32 readCount = 0; UINT8 crcCheck = 0; void *pReadAppConfig = (void *)&AppDataInfo; AppDataHeader AppDataHr; fp = OsaFopen(APP_DATAINFO_FILE_NAME, "rb"); //read only if (fp == PNULL) { #ifdef USING_PRINTF printf(" NVM, can't open NVM: 'qxappData.nvm', use the defult value\n"); #endif setDefaultAppDataInfo(); SaveAppData(); return; } readCount = OsaFread(&AppDataHr, sizeof(AppDataHr), 1, fp); UINT8 readtimes = 0; while (readCount != 1 && readtimes <= 5) { readtimes++; readCount = OsaFread(&AppDataHr, sizeof(AppDataHr), 1, fp); osDelay(10); } if (readtimes > 5) { OsaFclose(fp); setDefaultAppDataInfo(); SaveAppData(); return; } if (AppDataHr.fileBodySize == sizeof(AppDataInfo)) //结构体数据没变动,可直接读出 { readCount = OsaFread(pReadAppConfig, AppDataHr.fileBodySize, 1, fp); //crcCheck = OsaCalcCrcValue((UINT8 *)pReadAppConfig, sizeof(AppNVMData)); readtimes = 0; while (readtimes <= 5 && readCount != 1) { readtimes++; readCount = OsaFread(pReadAppConfig, AppDataHr.fileBodySize, 1, fp); //crcCheck = OsaCalcCrcValue((UINT8 *)pReadAppConfig, sizeof(AppNVMData)); } } else { setDefaultAppDataInfo(); readCount = OsaFread(pReadAppConfig, AppDataHr.fileBodySize, 1, fp); //crcCheck = OsaCalcCrcValue((UINT8 *)pReadAppConfig, sizeof(AppNVMData)); readtimes = 0; while (readtimes <= 5 && readCount != 1) { readtimes++; readCount = OsaFread(pReadAppConfig, AppDataHr.fileBodySize, 1, fp); //crcCheck = OsaCalcCrcValue((UINT8 *)pReadAppConfig, sizeof(AppNVMData)); } SaveAppData(); #ifdef USING_PRINTF printf(" Struct update\n"); #endif } OsaFclose(fp); return; } /** * @brief : Bcu存储数据加载函数 * @param {*} * @return {*} */ void LoadBcuData(void) { OSAFILE fp = PNULL; UINT32 readCount = 0; UINT8 crcCheck = 0; void *pReadAppConfig = (void *)&BcuDataInfo; BcuDataHeader BcuDataHr; fp = OsaFopen(BCU_DATAINFO_FILE_NAME, "rb"); //read only if (fp == PNULL) { #ifdef USING_PRINTF printf(" NVM, can't open NVM: 'qxappData.nvm', use the defult value\n"); #endif setDefaultBcuDataInfo(); SaveBcuData(); return; } readCount = OsaFread(&BcuDataHr, sizeof(BcuDataHr), 1, fp); UINT8 readtimes = 0; while (readCount != 1 && readtimes <= 5) { readtimes++; readCount = OsaFread(&BcuDataHr, sizeof(BcuDataHr), 1, fp); osDelay(10); } if (readtimes > 5) { OsaFclose(fp); setDefaultBcuDataInfo(); SaveBcuData(); return; } if (BcuDataHr.fileBodySize == sizeof(BcuDataInfo)) //结构体数据没变动,可直接读出 { readCount = OsaFread(pReadAppConfig, BcuDataHr.fileBodySize, 1, fp); //crcCheck = OsaCalcCrcValue((UINT8 *)pReadAppConfig, sizeof(AppNVMData)); readtimes = 0; while (readtimes <= 5 && readCount != 1) { readtimes++; readCount = OsaFread(pReadAppConfig, BcuDataHr.fileBodySize, 1, fp); //crcCheck = OsaCalcCrcValue((UINT8 *)pReadAppConfig, sizeof(AppNVMData)); } } else { setDefaultBcuDataInfo(); readCount = OsaFread(pReadAppConfig, BcuDataHr.fileBodySize, 1, fp); //crcCheck = OsaCalcCrcValue((UINT8 *)pReadAppConfig, sizeof(AppNVMData)); readtimes = 0; while (readtimes <= 5 && readCount != 1) { readtimes++; readCount = OsaFread(pReadAppConfig, BcuDataHr.fileBodySize, 1, fp); //crcCheck = OsaCalcCrcValue((UINT8 *)pReadAppConfig, sizeof(AppNVMData)); } SaveBcuData(); #ifdef USING_PRINTF printf(" Struct update\n"); #endif } OsaFclose(fp); return; } /** * @brief : App配置文件保存函数 * @param {*} * @return {*} */ void SaveAppConfig(void) { OSAFILE fp = PNULL; UINT32 writeCount = 0; AppConfigDataHeader AppConfigHr; //4 bytes /* * open the NVM file */ AppNVMData.appDataModify = FALSE; fp = OsaFopen(APP_CONFIG_FILE_NAME, "wb"); //read & write if (OsaFseek(fp, 0, SEEK_SET) != 0) { #ifdef USING_PRINTF printf("Seek file failed [%d] \r\n", __LINE__); #endif OsaFclose(fp); return; } if (fp == PNULL) { #ifdef USING_PRINTF printf(" NVM, can't open/create NVM: 'qxappconfig.nvm', save NVM failed\n"); #endif return; } /* * write the header */ AppConfigHr.fileBodySize = sizeof(AppNVMData); AppConfigHr.checkSum = OsaCalcCrcValue((UINT8 *)&AppNVMData, sizeof(AppNVMData)); writeCount = OsaFwrite(&AppConfigHr, sizeof(AppConfigHr), 1, fp); if (writeCount != 1) { #ifdef USING_PRINTF printf(" NVM: 'qxappconfig.nvm', write the file header failed\n"); #endif OsaFclose(fp); return; } /* * write the file body */ writeCount = OsaFwrite(&AppNVMData, sizeof(AppNVMData), 1, fp); if (writeCount != 1) { #ifdef USING_PRINTF printf(" NVM: 'qxappconfig.nvm', write the file body failed\n"); #endif } OsaFclose(fp); return; } /** * @brief : App配置文件加载函数 * @param {*} * @return {*} */ void LoadAppConfig(void) { OSAFILE fp = PNULL; UINT32 readCount = 0; AppConfigDataHeader AppConfigHr; UINT8 crcCheck = 0; void *pReadAppConfig = (void *)&AppNVMData; /* * open the NVM file */ fp = OsaFopen(APP_CONFIG_FILE_NAME, "rb"); //read only if (fp == PNULL) { #ifdef USING_PRINTF printf(" NVM, can't open NVM: 'qxappConfig.nvm', use the defult value\n"); #endif setDefaultAppConfigData(); SaveAppConfig(); return; } /* * read the file header */ readCount = OsaFread(&AppConfigHr, sizeof(AppConfigHr), 1, fp); UINT8 readtimes = 0; while (readCount != 1 && readtimes <= 5) { #ifdef USING_PRINTF printf("NVM: 'qxappconfig.nvm', can't read header, return: %d, use the defult value \n"); #endif readtimes++; readCount = OsaFread(&AppConfigHr, sizeof(AppConfigHr), 1, fp); osDelay(10); } if (readtimes > 5) { OsaFclose(fp); setDefaultAppConfigData(); SaveAppConfig(); return; } if (AppConfigHr.fileBodySize != sizeof(AppNVMData)) //file version is the same, but NVM file size not right { #ifdef USING_PRINTF printf("MW NVM: 'midwareconfig.nvm', file body size not right: (%u/%u), use the defult value", AppConfigHr.fileBodySize, sizeof(AppNVMData)); #endif OsaFclose(fp); setDefaultAppConfigData(); SaveAppConfig(); return; } /* * read the file body */ readCount = OsaFread(pReadAppConfig, AppConfigHr.fileBodySize, 1, fp); crcCheck = OsaCalcCrcValue((UINT8 *)pReadAppConfig, sizeof(AppNVMData)); readtimes = 0; //while (readtimes<=5 && crcCheck != AppConfigHr.checkSum) while (readtimes <= 5 && readCount != 1 && crcCheck != AppConfigHr.checkSum) { readtimes++; readCount = OsaFread(pReadAppConfig, AppConfigHr.fileBodySize, 1, fp); crcCheck = OsaCalcCrcValue((UINT8 *)pReadAppConfig, sizeof(AppNVMData)); } if (readtimes > 5) { #ifdef USING_PRINTF printf(" NVM: 'qxappconfig.nvm', can't read body, or body not right, (%u/%u), use the defult value\n ", crcCheck, AppConfigHr.checkSum); #endif OsaFclose(fp); setDefaultAppConfigData(); SaveAppConfig(); return; } OsaFclose(fp); return; } /** * @brief : App配置文件初始化函数 * @param {*} * @return {*} */ static void setDefaultAppConfigData(void) { UINT8 i = 0; memset(&AppNVMData, 0x00, sizeof(AppConfigDataType)); AppNVMData.appDataModify = TRUE; //数据更改标志位 memcpy(AppNVMData.battSN, DEFAULT_SN, BATT_SN_LEN); AppNVMData.isBattLocked = 0; AppNVMData.reserved1 = 0; AppNVMData.reserved2 = 0; AppNVMData.reserved3 = 0; AppNVMData.reserved4 = 0; AppNVMData.reserved5 = 0; AppNVMData.reserved6 = 0; AppNVMData.reserved7 = 0; AppNVMData.reserved8 = 0; AppNVMData.EOLState = EOLSTATE; return; } /** * @brief : App数据初始化函数 * @param {*} * @return {*} */ static void setDefaultAppDataInfo(void) { memset(&AppDataInfo, 0x00, sizeof(AppDataInfo)); AppDataInfo.appDataModify = false; AppDataInfo.BattCellCount = 17; AppDataInfo.BattTempCount = 5; AppDataInfo.BattInfoSendFreqHigh = 10; AppDataInfo.BattInfoSendFreqNomal = 30; AppDataInfo.BattInfoSendFreqLow = 60; AppDataInfo.PosInfoSendFreqHigh = 10; AppDataInfo.PosInfoSendFreqNormal = 30; AppDataInfo.PosInfoSendFreqLow = 60; AppDataInfo.AccMileage = 0; AppDataInfo.SysReStartCount = 0; AppDataInfo.RelayControl = 0; AppDataInfo.BattForceLock = 0; AppDataInfo.BattLock = 0; AppDataInfo.BattStolenFlag = 0; AppDataInfo.UserLock = 0; // 用户锁锁定 AppDataInfo.RentalLock = 0; //租期锁锁定 AppDataInfo.RentalType = 0; //租期类型 memset(AppDataInfo.ExpiryTimeArray, 0x00, 6); //超期时间 AppDataInfo.ErrorMsg = 0; return; } /** * @brief : BCU存储量初始化函数 * @param {*} * @return {*} */ static void setDefaultBcuDataInfo(void) { memset(&BcuDataInfo, 0x00, sizeof(BcuDataInfo)); BcuDataInfo.appDataModify = false; memset(BcuDataInfo.blcv_Q_totalCpE, 0x00, 28 * sizeof(UINT32)); memset(BcuDataInfo.blcv_Q_reqCpE, 0x00, 28 * sizeof(UINT16)); BcuDataInfo.socd_pct_bcuSocE = 1200; BcuDataInfo.socd_pct_battSocE = 1200; BcuDataInfo.sohd_tm_chrgStartStatE = 0; BcuDataInfo.sohd_flg_chrgEndE = 0; BcuDataInfo.sohv_Q_cellCapArrE[28]; memset(BcuDataInfo.sohv_Q_cellCapArrE, 0, 28 * sizeof(UINT16)); memset(BcuDataInfo.sohv_V_chrgStartStatE, 0, 28 * sizeof(UINT16)); BcuDataInfo.sohd_Q_chrgE = 0; memset(BcuDataInfo.sohv_Q_packCapArrE, 0, 10 * sizeof(UINT16)); BcuDataInfo.sfmd_flg_mainCirClosFltE = 0; BcuDataInfo.sfmd_flg_heatCirClosFltE = 0; BcuDataInfo.sfmd_flg_heatCirOpenFltE = 0; return; } /** * @brief : 认证加密函数,将明文加密为译文 * @param {UINT16} plainText * @return {*} */ 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; } /** * @brief : 认证解密函数,将译文解密为明文 * @param {UINT16} cipherText * @return {*} */ // 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; // } /** * @brief : Fota升级处理函数,将接收的数据进行校验,搬运至升级区域,并进行应答 * @param {UINT8} *DataPtr * @param {INT32} connectId * @return {*} */ void Fota_Func(UINT8 *DataPtr, INT32 connectId) { Fota_Type Fota_S; UINT8 Fota_Answer[43]; UINT8 Fota_Cmd; INT8 ret; UINT8 *Data_Read_Buffer = PNULL; UINT8 Data_Read_Crc; 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, (FLASH_BMS_FOTA_START_ADDR - FLASH_FOTA_REGION_START)); //512k-32k = 480k -> 0x75300 0x78000 } 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); Data_Read_Buffer = malloc(Fota_S.Fota_Recv_Data_Len); if (Fota_S.Fota_CRC == *(DataPtr + Fota_S.Fota_Recv_Data_Len + 42) || Data_Read_Buffer != PNULL) { UINT8 Fota_Recv_Data_Len_4 = 0; if (Fota_S.Fota_Recv_Data_Len % 4 != 0) { Fota_Recv_Data_Len_4 = Fota_S.Fota_Recv_Data_Len + 4 - (Fota_S.Fota_Recv_Data_Len % 4); } else { Fota_Recv_Data_Len_4 = Fota_S.Fota_Recv_Data_Len; } BSP_QSPI_Write_Safe(Fota_S.Fota_Recv_Data, Fota_S.Fota_Flash_Addres + Fota_S.Fota_Current_Addres, Fota_Recv_Data_Len_4); memset(Data_Read_Buffer, 0x00, 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("Data_Read_Buffer:\n"); for (int i = 0; i < Fota_S.Fota_Recv_Data_Len; i++) { printf("%x ", *(Data_Read_Buffer + i)); } printf("\n"); #endif 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_Recv_Data_Len_4); } } else //数据校验失败 { Fota_Answer[3] = 0x02; } if (Data_Read_Buffer != PNULL) free(Data_Read_Buffer); Data_Read_Buffer = PNULL; 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) { NB_Fota_update_flag = TRUE; } else { NB_Fota_update_flag = FALSE; } 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; } } } 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; BSP_QSPI_Erase_Safe(Fota_S.Fota_Flash_Addres, (FLASH_BMS_FOTA_END_ADDR - FLASH_BMS_FOTA_START_ADDR)); //512k-32k = 480k -> 0x75300 0x78000 } 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); Data_Read_Buffer = malloc(Fota_S.Fota_Recv_Data_Len); if (Fota_S.Fota_CRC == *(DataPtr + Fota_S.Fota_Recv_Data_Len + 42) || Data_Read_Buffer != PNULL) { UINT8 Fota_Recv_Data_Len_4 = 0; if (Fota_S.Fota_Recv_Data_Len % 4 != 0) { Fota_Recv_Data_Len_4 = Fota_S.Fota_Recv_Data_Len + 4 - (Fota_S.Fota_Recv_Data_Len % 4); } else { Fota_Recv_Data_Len_4 = Fota_S.Fota_Recv_Data_Len; } BSP_QSPI_Write_Safe(Fota_S.Fota_Recv_Data, Fota_S.Fota_Flash_Addres + Fota_S.Fota_Current_Addres, Fota_Recv_Data_Len_4); memset(Data_Read_Buffer, 0x00, 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_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_Recv_Data_Len_4); } } else //数据校验失败 { Fota_Answer[3] = 0x02; } if (Data_Read_Buffer != PNULL) free(Data_Read_Buffer); Data_Read_Buffer = PNULL; 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) { BMS_Fota_update_flag = TRUE; } else { BMS_Fota_update_flag = FALSE; } 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; } } } } /** * @brief : fota网络校验函数 * @param {UINT8} *data * @param {UINT8} length * @return {*} */ 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; } /** * @brief : Fota校验函数 * @param {UINT8} *data * @param {UINT8} length * @return {*} */ static UINT8 Fota_crc_chk(UINT8 *data, UINT8 length) { UINT8 reg_crc = 0x00; while (length--) { reg_crc ^= *data++; } return reg_crc; } /** * @brief : 1000ms 周期姓发送报文,根据调用周期及计时器,每100ms发送2帧报文,报文周期为1000ms * @param {*} * @return {*} */ void CanMsgTx1000ms() { static UINT32 timerRecord = 0; UINT8 count = 0; CAN_Msg_Type canMsg; 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}; if (TimeCounter - timerRecord > 0) { timerRecord = TimeCounter; count = TimeCounter % 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; } } } /** * @brief : 周期性报文组包,根据不同的ID,进行组包,并放入指针中 * @param {UINT32} ID * @param {UINT8} *msgData * @return {*} */ void CANEncodeFunction(UINT32 ID, UINT8 *msgData) { memset(msgData, 0xFF, 8); switch (ID) { case 0x6A0: *(UINT16 *)(msgData + 0) = ((battCellU[0] >> 8) & 0xFF) | (((battCellU[0] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 2) = ((battCellU[1] >> 8) & 0xFF) | (((battCellU[1] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 4) = ((battCellU[2] >> 8) & 0xFF) | (((battCellU[2] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 6) = ((battCellU[3] >> 8) & 0xFF) | (((battCellU[3] & 0xFF) << 8) & 0xFF00); break; case 0x6A1: *(UINT16 *)(msgData + 0) = ((battCellU[4] >> 8) & 0xFF) | (((battCellU[4] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 2) = ((battCellU[5] >> 8) & 0xFF) | (((battCellU[5] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 4) = ((battCellU[6] >> 8) & 0xFF) | (((battCellU[6] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 6) = ((battCellU[7] >> 8) & 0xFF) | (((battCellU[7] & 0xFF) << 8) & 0xFF00); break; case 0x6A2: *(UINT16 *)(msgData + 0) = ((battCellU[8] >> 8) & 0xFF) | (((battCellU[8] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 2) = ((battCellU[9] >> 8) & 0xFF) | (((battCellU[9] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 4) = ((battCellU[10] >> 8) & 0xFF) | (((battCellU[10] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 6) = ((battCellU[11] >> 8) & 0xFF) | (((battCellU[11] & 0xFF) << 8) & 0xFF00); break; case 0x6A3: *(UINT16 *)(msgData + 0) = ((battCellU[12] >> 8) & 0xFF) | (((battCellU[12] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 2) = ((battCellU[13] >> 8) & 0xFF) | (((battCellU[13] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 4) = ((battCellU[14] >> 8) & 0xFF) | (((battCellU[14] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 6) = ((battCellU[15] >> 8) & 0xFF) | (((battCellU[15] & 0xFF) << 8) & 0xFF00); break; case 0x6A4: *(UINT16 *)(msgData + 0) = ((battCellU[16] >> 8) & 0xFF) | (((battCellU[16] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 2) = ((battCellU[17] >> 8) & 0xFF) | (((battCellU[17] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 4) = ((battCellU[18] >> 8) & 0xFF) | (((battCellU[18] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 6) = ((battCellU[19] >> 8) & 0xFF) | (((battCellU[19] & 0xFF) << 8) & 0xFF00); break; case 0x6A5: *(UINT16 *)(msgData + 0) = ((battCellU[20] >> 8) & 0xFF) | (((battCellU[20] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 2) = ((battCellU[21] >> 8) & 0xFF) | (((battCellU[21] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 4) = ((battCellU[22] >> 8) & 0xFF) | (((battCellU[22] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 6) = ((battCellU[23] >> 8) & 0xFF) | (((battCellU[23] & 0xFF) << 8) & 0xFF00); break; case 0x6A6: *(UINT16 *)(msgData + 0) = ((battCellU[24] >> 8) & 0xFF) | (((battCellU[24] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 2) = ((battCellU[25] >> 8) & 0xFF) | (((battCellU[25] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 4) = ((battCellU[26] >> 8) & 0xFF) | (((battCellU[26] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 6) = ((battCellU[27] >> 8) & 0xFF) | (((battCellU[27] & 0xFF) << 8) & 0xFF00); break; case 0x6B0: *(UINT8 *)(msgData + 0) = battCellTemp[0] & 0xFF; *(UINT8 *)(msgData + 1) = battCellTemp[1] & 0xFF; *(UINT8 *)(msgData + 2) = battCellTemp[2] & 0xFF; *(UINT8 *)(msgData + 3) = battCellTemp[3] & 0xFF; *(UINT8 *)(msgData + 4) = battCellTemp[4] & 0xFF; *(UINT8 *)(msgData + 5) = battCellTemp[5] & 0xFF; *(UINT8 *)(msgData + 6) = battCellTemp[6] & 0xFF; *(UINT8 *)(msgData + 7) = battCellTemp[7] & 0xFF; break; case 0x6BA: *(UINT8 *)(msgData + 0) = MOSTemp & 0xFF; *(UINT8 *)(msgData + 1) = packTemp & 0xFF; *(UINT8 *)(msgData + 2) = fastChargeTemp & 0xFF; *(UINT8 *)(msgData + 3) = normalChargeTemp & 0xFF; *(UINT8 *)(msgData + 4) = heatTemp1 & 0xFF; *(UINT8 *)(msgData + 5) = heatTemp2 & 0xFF; *(UINT8 *)(msgData + 6) = nbReservedTemp1 & 0xFF; *(UINT8 *)(msgData + 7) = nbReservedTemp2 & 0xFF; break; case 0x6C0: *(UINT16 *)(msgData + 0) = ((minCellVol >> 8) & 0xFF) | (((minCellVol & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 2) = ((maxCellVol >> 8) & 0xFF) | (((maxCellVol & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 4) = ((battPackVol >> 8) & 0xFF) | (((battPackVol & 0xFF) << 8) & 0xFF00); *(UINT8 *)(msgData + 6) = maxCellTemp & 0xFF; *(UINT8 *)(msgData + 7) = minCellTemp & 0xFF; break; case 0x6C1: *(UINT8 *)(msgData + 0) = battSOC & 0xFF; *(UINT8 *)(msgData + 1) = battSOH & 0xFF; *(UINT16 *)(msgData + 2) = ((battI >> 8) & 0xFF) | (((battI & 0xFF) << 8) & 0xFF00); *(UINT8 *)(msgData + 4) = battWorkState & 0xFF; *(UINT32 *)(msgData + 5) = ((battWarningState >> 16) & 0xFF) | ((battWarningState)&0xFF00) | (((battWarningState & 0xFF) << 16) & 0xFF0000); break; case 0x6C2: *(UINT32 *)(msgData + 0) = ((nbSwVersion >> 24) & 0xFF) | ((nbSwVersion >> 8) & 0xFF00) | ((nbSwVersion << 8) & 0xFF0000) | (((nbSwVersion & 0xFF) << 24) & 0xFF000000); *(UINT16 *)(msgData + 4) = ((nbHwVersion >> 8) & 0xFF) | (((nbHwVersion & 0xFF) << 8) & 0xFF00); *(UINT8 *)(msgData + 6) = bmsSwVersion & 0xFF; *(UINT8 *)(msgData + 7) = bmsHwVersion & 0xFF; break; case 0x6C3: *(UINT32 *)(msgData + 0) = ((battBalanceoInfo >> 24) & 0xFF) | ((battBalanceoInfo >> 8) & 0xFF00) | ((battBalanceoInfo << 8) & 0xFF0000) | (((battBalanceoInfo & 0xFF) << 24) & 0xFF000000); *(UINT8 *)(msgData + 4) = battMOSSwitchState & 0xFF; *(UINT8 *)(msgData + 5) = battHeatEnableState & 0xFF; break; case 0x6C4: reservedSignal1 = battProtectState & 0xFF; reservedSignal2 = (battProtectState >> 8) & 0xFF; reservedSignal3 = (battProtectState >> 16) & 0xFF; reservedSignal4 = (battProtectState >> 24) & 0xFF; *(UINT8 *)(msgData + 0) = reservedSignal1 & 0xFF; *(UINT8 *)(msgData + 1) = reservedSignal2 & 0xFF; *(UINT8 *)(msgData + 2) = reservedSignal3 & 0xFF; *(UINT8 *)(msgData + 3) = reservedSignal4 & 0xFF; *(UINT8 *)(msgData + 4) = reservedSignal5 & 0xFF; *(UINT8 *)(msgData + 5) = reservedSignal6 & 0xFF; *(UINT8 *)(msgData + 6) = reservedSignal7 & 0xFF; *(UINT8 *)(msgData + 7) = reservedSignal8 & 0xFF; break; case 0x7C0: *(UINT16 *)(msgData + 0) = ((battCellU[0] >> 8) & 0xFF) | (((battCellU[0] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 2) = ((battCellU[1] >> 8) & 0xFF) | (((battCellU[1] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 4) = ((battCellU[2] >> 8) & 0xFF) | (((battCellU[2] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 6) = ((battCellU[3] >> 8) & 0xFF) | (((battCellU[3] & 0xFF) << 8) & 0xFF00); break; case 0x7C1: *(UINT16 *)(msgData + 0) = ((battCellU[4] >> 8) & 0xFF) | (((battCellU[4] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 2) = ((battCellU[5] >> 8) & 0xFF) | (((battCellU[5] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 4) = ((battCellU[6] >> 8) & 0xFF) | (((battCellU[6] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 6) = ((battCellU[7] >> 8) & 0xFF) | (((battCellU[7] & 0xFF) << 8) & 0xFF00); break; case 0x7C2: *(UINT16 *)(msgData + 0) = ((battCellU[8] >> 8) & 0xFF) | (((battCellU[8] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 2) = ((battCellU[9] >> 8) & 0xFF) | (((battCellU[9] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 4) = ((battCellU[10] >> 8) & 0xFF) | (((battCellU[10] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 6) = ((battCellU[11] >> 8) & 0xFF) | (((battCellU[11] & 0xFF) << 8) & 0xFF00); break; case 0x7C3: *(UINT16 *)(msgData + 0) = ((battCellU[12] >> 8) & 0xFF) | (((battCellU[12] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 2) = ((battCellU[13] >> 8) & 0xFF) | (((battCellU[13] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 4) = ((battCellU[14] >> 8) & 0xFF) | (((battCellU[14] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 6) = ((battCellU[15] >> 8) & 0xFF) | (((battCellU[15] & 0xFF) << 8) & 0xFF00); break; case 0x7C4: *(UINT16 *)(msgData + 0) = ((battCellU[16] >> 8) & 0xFF) | (((battCellU[16] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 2) = ((battCellU[17] >> 8) & 0xFF) | (((battCellU[17] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 4) = ((battCellU[18] >> 8) & 0xFF) | (((battCellU[18] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 6) = ((battCellU[19] >> 8) & 0xFF) | (((battCellU[19] & 0xFF) << 8) & 0xFF00); break; case 0x7C5: *(UINT16 *)(msgData + 0) = ((battCellU[20] >> 8) & 0xFF) | (((battCellU[20] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 2) = ((battCellU[21] >> 8) & 0xFF) | (((battCellU[21] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 4) = ((battCellU[22] >> 8) & 0xFF) | (((battCellU[22] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 6) = ((battCellU[23] >> 8) & 0xFF) | (((battCellU[23] & 0xFF) << 8) & 0xFF00); break; case 0x7C6: *(UINT16 *)(msgData + 0) = ((battCellU[24] >> 8) & 0xFF) | (((battCellU[24] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 2) = ((battCellU[25] >> 8) & 0xFF) | (((battCellU[25] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 4) = ((battCellU[26] >> 8) & 0xFF) | (((battCellU[26] & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 6) = ((battCellU[27] >> 8) & 0xFF) | (((battCellU[27] & 0xFF) << 8) & 0xFF00); break; case 0x7C7: *(UINT8 *)(msgData + 0) = battCellTemp[0] & 0xFF; *(UINT8 *)(msgData + 1) = battCellTemp[1] & 0xFF; *(UINT8 *)(msgData + 2) = battCellTemp[2] & 0xFF; *(UINT8 *)(msgData + 3) = battCellTemp[3] & 0xFF; *(UINT8 *)(msgData + 4) = battCellTemp[4] & 0xFF; *(UINT8 *)(msgData + 5) = battCellTemp[5] & 0xFF; *(UINT8 *)(msgData + 6) = battCellTemp[6] & 0xFF; *(UINT8 *)(msgData + 7) = battCellTemp[7] & 0xFF; break; case 0x7C8: *(UINT8 *)(msgData + 0) = MOSTemp & 0xFF; *(UINT8 *)(msgData + 1) = packTemp & 0xFF; *(UINT8 *)(msgData + 2) = fastChargeTemp & 0xFF; *(UINT8 *)(msgData + 3) = normalChargeTemp & 0xFF; *(UINT8 *)(msgData + 4) = heatTemp1 & 0xFF; *(UINT8 *)(msgData + 5) = heatTemp2 & 0xFF; *(UINT8 *)(msgData + 6) = nbReservedTemp1 & 0xFF; *(UINT8 *)(msgData + 7) = nbReservedTemp2 & 0xFF; break; case 0x7C9: *(UINT16 *)(msgData + 0) = ((minCellVol >> 8) & 0xFF) | (((minCellVol & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 2) = ((maxCellVol >> 8) & 0xFF) | (((maxCellVol & 0xFF) << 8) & 0xFF00); *(UINT16 *)(msgData + 4) = ((battPackVol >> 8) & 0xFF) | (((battPackVol & 0xFF) << 8) & 0xFF00); *(UINT8 *)(msgData + 6) = maxCellTemp & 0xFF; *(UINT8 *)(msgData + 7) = minCellTemp & 0xFF; break; case 0x7CA: *(UINT8 *)(msgData + 0) = battSOC & 0xFF; *(UINT8 *)(msgData + 1) = battSOH & 0xFF; *(UINT16 *)(msgData + 2) = ((battI >> 8) & 0xFF) | (((battI & 0xFF) << 8) & 0xFF00); *(UINT8 *)(msgData + 4) = battWorkState & 0xFF; *(UINT32 *)(msgData + 5) = ((battWarningState >> 16) & 0xFF) | ((battWarningState)&0xFF00) | (((battWarningState & 0xFF) << 16) & 0xFF0000); break; case 0x7CB: *(UINT32 *)(msgData + 0) = ((nbSwVersion >> 24) & 0xFF) | ((nbSwVersion >> 8) & 0xFF00) | ((nbSwVersion << 8) & 0xFF0000) | (((nbSwVersion & 0xFF) << 24) & 0xFF000000); *(UINT16 *)(msgData + 4) = ((nbHwVersion >> 8) & 0xFF) | (((nbHwVersion & 0xFF) << 8) & 0xFF00); *(UINT8 *)(msgData + 6) = bmsSwVersion & 0xFF; *(UINT8 *)(msgData + 7) = bmsHwVersion & 0xFF; break; case 0x7CC: *(UINT32 *)(msgData + 0) = ((battBalanceoInfo >> 24) & 0xFF) | ((battBalanceoInfo >> 8) & 0xFF00) | ((battBalanceoInfo << 8) & 0xFF0000) | (((battBalanceoInfo & 0xFF) << 24) & 0xFF000000); *(UINT8 *)(msgData + 4) = battMOSSwitchState & 0xFF; *(UINT8 *)(msgData + 5) = battHeatEnableState & 0xFF; break; case 0x7CD: reservedSignal1 = battProtectState & 0xFF; reservedSignal2 = (battProtectState >> 8) & 0xFF; reservedSignal3 = (battProtectState >> 16) & 0xFF; reservedSignal4 = (battProtectState >> 24) & 0xFF; *(UINT8 *)(msgData + 0) = reservedSignal1 & 0xFF; *(UINT8 *)(msgData + 1) = reservedSignal2 & 0xFF; *(UINT8 *)(msgData + 2) = reservedSignal3 & 0xFF; *(UINT8 *)(msgData + 3) = reservedSignal4 & 0xFF; *(UINT8 *)(msgData + 4) = reservedSignal5 & 0xFF; *(UINT8 *)(msgData + 5) = reservedSignal6 & 0xFF; *(UINT8 *)(msgData + 6) = reservedSignal7 & 0xFF; *(UINT8 *)(msgData + 7) = reservedSignal8 & 0xFF; break; case 0x7B0: *(UINT8 *)(msgData + 0) = (AppNVMData.battSN[0]) & 0xFF; *(UINT8 *)(msgData + 1) = (AppNVMData.battSN[1]) & 0xFF; *(UINT8 *)(msgData + 2) = (AppNVMData.battSN[2]) & 0xFF; *(UINT8 *)(msgData + 3) = (AppNVMData.battSN[3]) & 0xFF; *(UINT8 *)(msgData + 4) = (AppNVMData.battSN[4]) & 0xFF; *(UINT8 *)(msgData + 5) = (AppNVMData.battSN[5]) & 0xFF; *(UINT8 *)(msgData + 6) = (AppNVMData.battSN[6]) & 0xFF; *(UINT8 *)(msgData + 7) = (AppNVMData.battSN[7]) & 0xFF; break; case 0x7B1: *(UINT8 *)(msgData + 0) = (AppNVMData.battSN[8]) & 0xFF; *(UINT8 *)(msgData + 1) = (AppNVMData.battSN[9]) & 0xFF; *(UINT8 *)(msgData + 2) = (AppNVMData.battSN[10]) & 0xFF; *(UINT8 *)(msgData + 3) = (AppNVMData.battSN[11]) & 0xFF; *(UINT8 *)(msgData + 4) = (AppNVMData.battSN[12]) & 0xFF; *(UINT8 *)(msgData + 5) = (AppNVMData.battSN[13]) & 0xFF; *(UINT8 *)(msgData + 6) = (AppNVMData.battSN[14]) & 0xFF; *(UINT8 *)(msgData + 7) = (AppNVMData.battSN[15]) & 0xFF; break; case 0x7B2: *(UINT8 *)(msgData + 0) = (AppNVMData.battSN[16]) & 0xFF; break; default: break; } } /** * @brief : UDS函数,根据报文内容,进行包括读取版本号、读写SN、查询状态,用于完成下线检测和通过CAN接收升级包等操作 * @param {CAN_Msg_Type} *CanRxMsg * @return {*} */ void UDS_Service(CAN_Msg_Type *CanRxMsg) { 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}; UINT32 posCode, negCode; UINT32 updateDifferDataByteLen = 0; static UINT8 updateDataBuffer[100]; static UINT8 controllerFlag = 0xFF; UINT32 flashStartAddr = 0x00; static UINT32 updateDifferDataSliceCounter = 0; static UINT8 UDSSwitch = 0; static UINT8 UDSDialogMode = 01; static UINT8 UDSBattSN[BATT_SN_LEN]; for (i = 0; i < 2; i++) { UDSAnswer.DLC = 8; memset(UDSAnswer.Data, 0, UDSAnswer.DLC); UDSService[i] = CanRxMsg[i].Data[0]; UDSSubService[i] = CanRxMsg[i].Data[1]; UDSSubServiceActionCode[i] = CanRxMsg[i].Data[2]; 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); //SaveAppConfig(); 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 = GpsFlag; 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(AppNVMData.battSN, UDSBattSN, BATT_SN_LEN); AppNVMData.EOLState = 1; //SN号写入完成,表明已经进行过下线配置 SaveAppConfig(); } 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] != 0x00 && UDSSubServiceActionCode[i] != 0xFF) { //Clear the Flash controllerFlag = UDSSubServiceActionCode[i]; boolRet = UDSClearFotaDownloadRegion(controllerFlag); //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 if (controllerFlag == 0x01) { flashStartAddr = FLASH_FOTA_REGION_START; } else if (controllerFlag == 0x02 || controllerFlag == 0x03) { flashStartAddr = FLASH_BMS_FOTA_START_ADDR; } else { UDSNegtiveAnswer(0x08, i, 0xFFFFFFFF); return; } ret = (uint8_t)BSP_QSPI_Write_Safe(updateDataBuffer, flashStartAddr + (updateDifferDataPackageCounter)*100, 100); errorCount = 0; while (ret != QSPI_OK && errorCount < 3) //try to write most 3 times { errorCount++; BSP_QSPI_Erase_Safe(flashStartAddr + (updateDifferDataPackageCounter)*100, 100); ret = (uint8_t)BSP_QSPI_Write_Safe(updateDataBuffer, flashStartAddr + (updateDifferDataPackageCounter)*100, 100); } if (ret == QSPI_OK) // write successed { UDSPositiveAnswer(0x08, i, tempSliceCounter); memset(updateDataBuffer, 0, 100); sliceCounterFlag = 0x0; updateDifferDataPackageCounter++; } else //write fail { UDSNegtiveAnswer(0x08, i, 0xFFFFFFFF); //failed to write this package to flash } } 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); } } } 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 { if (UDSSubServiceActionCode[i] == controllerFlag) { if (controllerFlag == 0x02 || controllerFlag == 0x03) //update bms { BMS_Fota_update_flag = true; } downloadReady = FALSE; UDSPositiveAnswer(0x04, i, UDSSubServiceActionCode[i]); } else { UDSNegtiveAnswer(0x05, i, 0xEE); } } 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; } } /** * @brief : UDS肯定响应,发送肯定响应报文 * @param {UINT8} answerLen * @param {UINT8} messageIndex * @param {UINT32} posCode * @return {*} */ 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; } /** * @brief : UDS否定响应,发送否定响应报文 * @param {UINT8} answerLen * @param {UINT8} messageIndex * @param {UINT32} negCode * @return {*} */ 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; } /** * @brief : 清空计数,并准备接收数据包 * @param {*} * @return {*} */ BOOL UDSAskforDownLoadData() { updateDifferDataPackageCounter = 0; downloadReady = true; return TRUE; } /** * @brief : 清除数据接收的flash区域 * @param {UINT8} controllerFlag * @return {*} */ BOOL UDSClearFotaDownloadRegion(UINT8 controllerFlag) { UINT8 ret = FALSE; if (controllerFlag == 0x01) { ret = BSP_QSPI_Erase_Safe(FLASH_FOTA_REGION_START, 0x46000); //512k-32k -200k = 280k -> 0x46000 } else if (controllerFlag == 0x02 || controllerFlag == 0x03) { ret = BSP_QSPI_Erase_Safe(FLASH_BMS_FOTA_START_ADDR, FLASH_BMS_FOTA_LEN); } if (ret == QSPI_OK) { return TRUE; } else { return FALSE; } }