#include"common.h" #include "drv_io.h" #include "app.h" #include "app_rs485_1.h" #include "app_rs485_2.h" #include "drv_can.h" #include "app_adas.h" #include "measure_vol.h" #include "app_can.h" #include "low_power.h" #include "app_end_ctr.h" #include "drv_io.h" #include "shark_xl.h" // CB_VAL cb_val_last; uint8_t cb_operate_state = CB_BAT_NO; uint8_t Check_CB_oper_sta_start = 0; DELAY_COMMON Check_CB_oper_sta_delay; uint8_t cfg_operate = CFG_BAT_NO; uint8_t work_normal = 0; uint8_t is_intelligent = 1; uint8_t CB_OPERATE_PRECEDENCE_PARRALLEL = PRE_SERIES; uint8_t CB_OPERATE_PRECEDENCE_Config = PRE_SERIES; DELAY_COMMON Series_delay; uint8_t one_bat_initial = 1; uint8_t serise_low_qd_status = 0; const double nhb_default = 600; SHENG_YU_LI_CHENG sheng_yu_li_cheng; DELAY_COMMON save_param_delay; shark_bool shark_battery_series_locked; u8 shark_battery_series_times; shark_bool shark_battery_switch_busy; shark_bool shark_printf_enabled; void Misc_Initial(void) { GPIO_Initial(); } void CB_Operate_Initial(void) { _CB_Operate_Initial(); // memset(&cb_val_last,0x00,sizeof(cb_val_last)); //Check_CB_oper_sta_delay.set = 1; //Check_CB_oper_sta_delay.count = 0; Battery_CB_Switch(CB_BAT_NO); } void App_Initial(void) { CB_OPERATE_PRECEDENCE_PARRALLEL = CB_OPERATE_PRECEDENCE_Config; memset(&Series_delay,0x00,sizeof(Series_delay)); Initial_Neng_Hao_Bi(); } uint8_t Check_Battery_1_On(void) { uint32_t vol = 0; if(IS_CHARGER_ON()) return 0; if((sub_bms_info_2.packet_common.bms_status & BMS_STA_S_OPEN) == 0) { vol = Measure_Vol(); if(vol != 0xFFFFFFFF && vol > sub_bms_info_2.packet_common.m_total_vol) return 1; } return 0; } uint8_t Check_Battery_2_On(void) { uint32_t vol = 0; if(IS_CHARGER_ON()) return 0; if((sub_bms_info_1.packet_common.bms_status & BMS_STA_S_OPEN) == 0) { vol = Measure_Vol(); if(vol != 0xFFFFFFFF && vol > sub_bms_info_1.packet_common.m_total_vol) return 1; } return 0; } shark_bool battery_wait_voltage_parallel(void) { u64 time1 = shark_get_time() + 1000; u64 time2 = shark_get_time() + 5000; u32 voltage_min, voltage_max; if (sub_bms_info_1.connected == CONFIG_UART_GOOD) { if (sub_bms_info_2.connected == CONFIG_UART_GOOD) { voltage_max = shark_battery_get_voltage_max(); } else { voltage_max = shark_battery_get_voltage1(); } } else if (sub_bms_info_2.connected == CONFIG_UART_GOOD) { voltage_max = shark_battery_get_voltage2(); } else { return shark_false; } voltage_min = voltage_max - SHARK_BATT_VOLTAGE_FUZZ; if (IS_CHARGER_ON()) { voltage_max = SHARK_CHARGER_VOLTAGE_MAX; } else { voltage_max += SHARK_BATT_VOLTAGE_FUZZ; } while (shark_true) { u32 time = shark_get_time_safe(); u32 voltage = Measure_Vol(); if (voltage < voltage_min) { if (time > time1) { println("parallel: %d < %d", voltage, voltage_min); return shark_false; } } else if (voltage > voltage_max) { if (time > time2) { println("parallel: %d > %d", voltage, voltage_max); return shark_false; } } else { break; } } return shark_true; } shark_bool battery_wait_voltage_series(u32 voltage_min) { u64 time = shark_get_time() + 1000; if (sub_bms_info_1.connected != CONFIG_UART_GOOD) { return shark_false; } if (sub_bms_info_1.connected != CONFIG_UART_GOOD) { return shark_false; } while (shark_true) { u32 voltage = Measure_Vol(); if (voltage > voltage_min) { println("series: %d > %d", voltage, voltage_min); break; } if (time < shark_get_time_safe()) { println("series: %d < %d", voltage, voltage_min); return shark_false; } } return shark_true; } static u8 shark_battery_switch_series(void) { u32 voltage1 = shark_battery_get_voltage1(); u32 voltage2 = shark_battery_get_voltage2(); if (shark_battery_set_power(SHARK_BATT_POWER_FULL, SHARK_BATT_POWER_OFF, SHARK_BATT_MASK_BOTH) != SHARK_BATT_MASK_BOTH) { return CB_BAT_NO; } if (shark_battery_set_power(SHARK_BATT_POWER_FULL, SHARK_BATT_POWER_SMALL, SHARK_BATT_MASK_BOTH) != SHARK_BATT_MASK_BOTH) { return CB_BAT_NO; } shark_bms_set_mos_series(); if (!battery_wait_voltage_series(voltage1 + (voltage2 / 3))) { shark_bms_set_mos_close(); return CB_BAT_NO; } if (shark_battery_set_power(SHARK_BATT_POWER_FULL, SHARK_BATT_POWER_FULL, SHARK_BATT_MASK_BOTH) != SHARK_BATT_MASK_BOTH) { shark_bms_set_mos_close(); return CB_BAT_NO; } sub_bms_info_1.used = shark_true; sub_bms_info_2.used = shark_true; shark_battery_series_locked = shark_false; return CB_BAT1_BAT2_SERIES; } static u8 shark_battery_switch_parrallel(void) { shark_bms_set_mos_parrallel(); sub_bms_info_1.used = shark_true; sub_bms_info_2.used = shark_true; return CB_BAT1_BAT2_PARRALLEL; } static u8 shark_battery_switch_bat1(shark_battery_mask_t mask) { if (shark_battery_set_power(SHARK_BATT_POWER_FULL, SHARK_BATT_POWER_OFF, mask) != mask) { return CB_BAT_NO; } shark_bms_set_mos_bat1(); sub_bms_info_1.used = shark_true; sub_bms_info_2.used = shark_false; return CB_BAT1; } static u8 shark_battery_switch_bat2(shark_battery_mask_t mask) { if (shark_battery_set_power(SHARK_BATT_POWER_OFF, SHARK_BATT_POWER_FULL, mask) != mask) { return CB_BAT_NO; } shark_bms_set_mos_bat2(); sub_bms_info_1.used = shark_false; sub_bms_info_2.used = shark_true; return CB_BAT2; } static u8 shark_battery_switch_charge(void) { u8 capacity1 = shark_battery_get_capacity1(); u8 capacity2 = shark_battery_get_capacity2(); u32 voltage1 = shark_battery_get_voltage1(); u32 voltage2 = shark_battery_get_voltage2(); if (shark_battery_charge_complete1()) { return shark_battery_switch_bat2(SHARK_BATT_MASK_BOTH); } if (shark_battery_charge_complete2()) { return shark_battery_switch_bat1(SHARK_BATT_MASK_BOTH); } if (capacity1 < capacity2) { return shark_battery_switch_bat1(SHARK_BATT_MASK_BOTH); } if (capacity2 < capacity1) { return shark_battery_switch_bat2(SHARK_BATT_MASK_BOTH); } if (voltage1 < voltage2) { return shark_battery_switch_bat1(SHARK_BATT_MASK_BOTH); } else { return shark_battery_switch_bat2(SHARK_BATT_MASK_BOTH); } } static u8 shark_battery_switch_single(void) { u32 voltage1 = shark_battery_get_voltage1(); u32 voltage2 = shark_battery_get_voltage2(); u64 time = shark_get_time() + 500; u32 open1 = 0; u32 open2 = 0; if (sub_bms_info_1.exit_times < sub_bms_info_2.exit_times) { return shark_battery_switch_bat1(SHARK_BATT_MASK_BOTH); } if (sub_bms_info_2.exit_times < sub_bms_info_1.exit_times) { return shark_battery_switch_bat2(SHARK_BATT_MASK_BOTH); } while (time > shark_get_time_safe()) { if (BAT1_IS_OPEN()) { open1++; } if (BAT2_IS_OPEN()) { open2++; } } println("open: %d %d", open1, open2); println("voltage: %d %d", voltage1, voltage2); if (open1 > open2) { return shark_battery_switch_bat1(SHARK_BATT_MASK_BOTH); } if (open1 < open2) { return shark_battery_switch_bat2(SHARK_BATT_MASK_BOTH); } if (voltage1 > voltage2) { return shark_battery_switch_bat1(SHARK_BATT_MASK_BOTH); } else { return shark_battery_switch_bat2(SHARK_BATT_MASK_BOTH); } } static shark_bool shark_battery_series_enabled(void) { if (QD_Dect()) { if (shark_xl_check()) { return shark_false; } #ifndef HAN_GUO_VERSION if (shark_battery_series_locked) { return shark_false; } #endif if (shark_battery_series_times > SHARK_SERIES_MAX_TIMES) { return shark_false; } } if (shark_battery_get_capacity1() < SERIES_ENTER_PERCENT) { return shark_false; } if (shark_battery_get_capacity2() < SERIES_ENTER_PERCENT) { return shark_false; } if (shark_battery_get_voltage1() < SERIES_PROTECT_VOL) { return shark_false; } if (shark_battery_get_voltage2() < SERIES_PROTECT_VOL) { return shark_false; } if (IS_CHARGE_IN()) { return shark_false; } return shark_true; } static shark_bool shark_battery_check_series(u8 operate) { if (operate != CB_BAT1_BAT2_SERIES) { if (is_intelligent == 0) { return shark_false; } if (CB_OPERATE_PRECEDENCE_PARRALLEL != PRE_SERIES) { return shark_false; } } return shark_battery_series_enabled(); } static shark_bool shark_battery_check_parrallel(u8 operate) { if (operate != CB_BAT1_BAT2_PARRALLEL) { if (is_intelligent == 0) { return shark_false; } if (CB_OPERATE_PRECEDENCE_PARRALLEL != PRE_PARRALLEL) { return shark_false; } return shark_false; } if (shark_battery_get_voltage_delta() > PARRALLEL_BL_DELTA_VOL) { return shark_false; } return SHARK_BOOL(IS_CHARGE_IN()); } static u8 shark_battery_switch_auto(u8 operate) { if (operate == cb_operate_state) { return operate; } shark_bms_set_mos_close(); sub_bms_info_1.used = shark_false; sub_bms_info_2.used = shark_false; if (shark_battery_set_power(SHARK_BATT_POWER_FULL, SHARK_BATT_POWER_FULL, SHARK_BATT_MASK_BOTH) == SHARK_BATT_MASK_NONE) { return CB_BAT_NO; } if (operate == CB_BAT_NO) { return CB_BAT_NO; } if (!battery_wait_voltage_parallel()) { return CB_BAT_NO; } if (shark_battery_is_normal_power_on(&sub_bms_info_1) == SHARK_BATT_EXIT_SUCCESS) { if (shark_battery_is_normal_power_on(&sub_bms_info_2) == SHARK_BATT_EXIT_SUCCESS) { if (shark_battery_check_series(operate)) { operate = shark_battery_switch_series(); if (operate == CB_BAT1_BAT2_SERIES) { shark_battery_series_times = 0; } else if (shark_battery_series_times < 0xFF) { shark_battery_series_times++; } return operate; } else if (shark_battery_check_parrallel(operate)) { return shark_battery_switch_parrallel(); } else if (IS_CHARGE_IN()) { return shark_battery_switch_charge(); } else { return shark_battery_switch_single(); } } else { return shark_battery_switch_bat1(SHARK_BATT_MASK_BAT1); } } else if (shark_battery_is_normal_power_on(&sub_bms_info_2) == SHARK_BATT_EXIT_SUCCESS) { return shark_battery_switch_bat2(SHARK_BATT_MASK_BAT2); } else { return CB_BAT_NO; } } int8_t Battery_CB_Switch(uint8_t cb_operate) { println("switch: %d -> %d", cb_operate_state, cb_operate); #if 1 shark_battery_switch_busy = shark_true; cb_operate_state = shark_battery_switch_auto(cb_operate); sub_bms_info_1.exit_times = 0; sub_bms_info_2.exit_times = 0; shark_battery_switch_busy = shark_false; println("switch: %d", cb_operate_state); return cb_operate_state; #else #define COM_TIMEOUT (15) switch(cb_operate) { case CB_BAT1_BAT2_AUTO: cb_operate = shark_battery_switch_auto(shark_false); println("single auto: %d", cb_operate); break; case CB_BAT1: shark_bms_set_mos_close(); if(!battery_wait_voltage_down(SELECT_ONE_BATTERY_VOL)) { goto SWITCH_ERROR; } switch(cb_operate_state) { case CB_BAT_NO: // if(sub_bms_info_2.conn_state == SUB_BMS_CONT_HV485) { i = 0; while(i++ < COM_TIMEOUT && RS485_busy_2) delay_1ms(10); if(RS485_busy_2) goto SWITCH_ERROR; if(Operate_Sub_BMS_2_CD(0) == 0) goto SWITCH_ERROR; } else if(sub_bms_info_2.conn_state == SUB_BMS_DISC_NO485) { if(Check_Battery_2_On()) goto SWITCH_ERROR; } else { goto SWITCH_ERROR; } // i = 0; while(i++ < COM_TIMEOUT && RS485_busy_1) delay_1ms(10); if(RS485_busy_1) goto SWITCH_ERROR; if(one_bat_initial == 0) { if(Operate_Sub_BMS_1_CD(2) == 0) goto SWITCH_ERROR; delay_1ms(200); } if(Operate_Sub_BMS_1_CD(1) == 0) goto SWITCH_ERROR; break; case CB_BAT1: break; case CB_BAT2: i = 0; while(i++ < COM_TIMEOUT && RS485_busy_1) delay_1ms(10); if(RS485_busy_1) goto SWITCH_ERROR; if(Operate_Sub_BMS_1_CD(1) == 0) goto SWITCH_ERROR; // i = 0; while(i++ < COM_TIMEOUT && RS485_busy_2) delay_1ms(10); if(RS485_busy_2) goto SWITCH_ERROR; if(Operate_Sub_BMS_2_CD(0) == 0) goto SWITCH_ERROR; break; case CB_BAT1_BAT2_PARRALLEL: // i = 0; while(i++ < COM_TIMEOUT && RS485_busy_2) delay_1ms(10); if(RS485_busy_2) goto SWITCH_ERROR; if(Operate_Sub_BMS_2_CD(0) == 0) goto SWITCH_ERROR; break; case CB_BAT1_BAT2_SERIES: // if(sub_bms_info_2.conn_state == SUB_BMS_CONT_HV485) { i = 0; while(i++ < COM_TIMEOUT && RS485_busy_2) delay_1ms(10); //if(RS485_busy_2) // goto SWITCH_ERROR; if(Operate_Sub_BMS_2_CD(0) == 0) { // goto SWITCH_ERROR; } } else Operate_Sub_BMS_2_CD(0); break; default: goto SWITCH_ERROR; } shark_bms_set_mos_bat1(); sub_bms_info_1.state = SHARK_BATT_STATE_USED; sub_bms_info_2.state = SHARK_BATT_STATE_IDLE; break; case CB_BAT2: shark_bms_set_mos_close(); if(!battery_wait_voltage_down(SELECT_ONE_BATTERY_VOL)) { goto SWITCH_ERROR; } switch(cb_operate_state) { case CB_BAT_NO: // if(sub_bms_info_1.conn_state == SUB_BMS_CONT_HV485) { i = 0; while(i++ < COM_TIMEOUT && RS485_busy_1) delay_1ms(10); if(RS485_busy_1) goto SWITCH_ERROR; if(Operate_Sub_BMS_1_CD(0) == 0) goto SWITCH_ERROR; } else if(sub_bms_info_1.conn_state == SUB_BMS_DISC_NO485) { if(Check_Battery_1_On()) goto SWITCH_ERROR; } else { goto SWITCH_ERROR; } // i = 0; while(i++ < COM_TIMEOUT && RS485_busy_2) delay_1ms(10); if(RS485_busy_2) goto SWITCH_ERROR; if(one_bat_initial == 0) { if(Operate_Sub_BMS_2_CD(2) == 0) goto SWITCH_ERROR; delay_1ms(200); } if(Operate_Sub_BMS_2_CD(1) == 0) goto SWITCH_ERROR; break; case CB_BAT1: // i = 0; while(i++ < COM_TIMEOUT && RS485_busy_2) delay_1ms(10); if(RS485_busy_2) goto SWITCH_ERROR; if(Operate_Sub_BMS_2_CD(1) == 0) goto SWITCH_ERROR; // i = 0; while(i++ < COM_TIMEOUT && RS485_busy_1) delay_1ms(10); if(RS485_busy_1) goto SWITCH_ERROR; if(Operate_Sub_BMS_1_CD(0) == 0) goto SWITCH_ERROR; break; case CB_BAT2: break; case CB_BAT1_BAT2_PARRALLEL: // i = 0; while(i++ < COM_TIMEOUT && RS485_busy_1) delay_1ms(10); if(RS485_busy_1) goto SWITCH_ERROR; if(Operate_Sub_BMS_1_CD(0) == 0) goto SWITCH_ERROR; break; case CB_BAT1_BAT2_SERIES: // if(sub_bms_info_1.conn_state == SUB_BMS_CONT_HV485) { i = 0; while(i++ < COM_TIMEOUT && RS485_busy_1) delay_1ms(10); //if(RS485_busy_1) // goto SWITCH_ERROR; if(Operate_Sub_BMS_1_CD(0) == 0) { //goto SWITCH_ERROR; } } else Operate_Sub_BMS_1_CD(0); break; default: goto SWITCH_ERROR; } shark_bms_set_mos_bat2(); sub_bms_info_1.state = SHARK_BATT_STATE_IDLE; sub_bms_info_2.state = SHARK_BATT_STATE_USED; break; case CB_BAT1_BAT2_PARRALLEL: shark_bms_set_mos_close(); if(!battery_wait_voltage_down(SELECT_ONE_BATTERY_VOL)) { goto SWITCH_ERROR; } switch(cb_operate_state) { case CB_BAT_NO: goto SWITCH_ERROR; case CB_BAT1: // i = 0; while(i++ < COM_TIMEOUT && RS485_busy_2) delay_1ms(10); if(RS485_busy_2) goto SWITCH_ERROR; if(Operate_Sub_BMS_2_CD(1) == 0) goto SWITCH_ERROR; break; case CB_BAT2: // i = 0; while(i++ < COM_TIMEOUT && RS485_busy_1) delay_1ms(10); if(RS485_busy_1) goto SWITCH_ERROR; if(Operate_Sub_BMS_1_CD(1) == 0) goto SWITCH_ERROR; break; case CB_BAT1_BAT2_PARRALLEL: break; case CB_BAT1_BAT2_SERIES: delay_1ms(10); break; default: goto SWITCH_ERROR; } shark_bms_set_mos_parrallel(); sub_bms_info_1.state = SHARK_BATT_STATE_USED; sub_bms_info_2.state = SHARK_BATT_STATE_USED; break; case CB_BAT1_BAT2_SERIES: #if 1 cb_operate = shark_battery_switch_auto(shark_true); println("series auto: %d", cb_operate); #else Power_On_Normal(0,2); shark_bms_set_mos_close(); //delay_1ms(2000); //serise_low_qd_status = QD_Dect(); //Power_On_Normal(0,2); switch(cb_operate_state) { case CB_BAT_NO: goto SWITCH_ERROR; case CB_BAT1: delay_1ms(10); shark_bms_set_mos_series(); // i = 0; while(i++ < COM_TIMEOUT && RS485_busy_2) delay_1ms(10); if(RS485_busy_2) goto SWITCH_ERROR; if(Operate_Sub_BMS_2_CD(2) == 0) goto SWITCH_ERROR; /*for(uint16_t i = 0;i < 20;i++) { if(Handle_Can_Data() == 1) { // output fail ; } delay_1ms(10); }*/ delay_1ms(200); if(Operate_Sub_BMS_2_CD(1) == 0) goto SWITCH_ERROR; break; case CB_BAT2: delay_1ms(10); shark_bms_set_mos_series(); // i = 0; while(i++ < COM_TIMEOUT && RS485_busy_1) delay_1ms(10); if(RS485_busy_1) goto SWITCH_ERROR; if(Operate_Sub_BMS_1_CD(2) == 0) goto SWITCH_ERROR; /*for(uint16_t i = 0;i < 20;i++) { if(Handle_Can_Data() == 1) { // output fail ; } delay_1ms(10); }*/ delay_1ms(200); if(Operate_Sub_BMS_1_CD(1) == 0) goto SWITCH_ERROR; break; case CB_BAT1_BAT2_PARRALLEL: if(sub_bms_info_1.packet_common.m_total_vol < sub_bms_info_2.packet_common.m_total_vol) { // i = 0; while(i++ < COM_TIMEOUT && RS485_busy_1) delay_1ms(10); if(RS485_busy_1) goto SWITCH_ERROR; if(Operate_Sub_BMS_1_CD(0) == 0) goto SWITCH_ERROR; delay_1ms(50); delay_1ms(10); shark_bms_set_mos_series(); if(Operate_Sub_BMS_1_CD(2) == 0) goto SWITCH_ERROR; /*for(uint16_t i = 0;i < 20;i++) { if(Handle_Can_Data() == 1) { // output fail ; } delay_1ms(10); }*/ delay_1ms(200); if(Operate_Sub_BMS_1_CD(1) == 0) goto SWITCH_ERROR; } else { // i = 0; while(i++ < COM_TIMEOUT && RS485_busy_2) delay_1ms(10); if(RS485_busy_2) goto SWITCH_ERROR; if(Operate_Sub_BMS_2_CD(0) == 0) goto SWITCH_ERROR; delay_1ms(50); delay_1ms(10); shark_bms_set_mos_series(); if(Operate_Sub_BMS_2_CD(2) == 0) goto SWITCH_ERROR; /*for(uint16_t i = 0;i < 20;i++) { if(Handle_Can_Data() == 1) { // output fail ; } delay_1ms(10); }*/ delay_1ms(200); if(Operate_Sub_BMS_2_CD(1) == 0) goto SWITCH_ERROR; } break; case CB_BAT1_BAT2_SERIES: break; default: goto SWITCH_ERROR; } delay_1ms(10); shark_bms_set_mos_series(); sub_bms_info_1.state = SHARK_BATT_STATE_USED; sub_bms_info_2.state = SHARK_BATT_STATE_USED; #endif break; case CB_BAT_NO: default: ACC2_Enable(0); shark_bms_set_mos_close(); sub_bms_info_1.state = SHARK_BATT_STATE_IDLE; sub_bms_info_2.state = SHARK_BATT_STATE_IDLE; cb_operate = CB_BAT_NO; if(Is_Soak()) { sub_bms_info_1.sub_bms_cmd.operate = OP_OPEN_FET; sub_bms_info_1.sub_bms_cmd.param = 0x00; sub_bms_info_2.sub_bms_cmd.operate = OP_OPEN_FET; sub_bms_info_2.sub_bms_cmd.param = 0x00; } break; } // cb_val_last = cb_val_temp; cb_operate_state = cb_operate; return cb_operate; SWITCH_ERROR: println("switch err"); shark_bms_set_mos_close(); cb_operate_state = CB_BAT_NO; return cb_operate_state; #undef COM_TIMEOUT #endif } void test_io(void) { volatile uint8_t a,b; a = BAT1_IS_OPEN(); b = BAT2_IS_OPEN(); a++; b++; } uint8_t Select_One_BAT(void) { #if 0 uint8_t temp_op = CB_BAT_NO; println("select one"); sub_bms_info_1.state = SHARK_BATT_STATE_IDLE; sub_bms_info_2.state = SHARK_BATT_STATE_IDLE; if(Is_Sub_BMS_1_Normal() == SHARK_BATT_EXIT_SUCCESS) { if(Is_Sub_BMS_2_Normal() == SHARK_BATT_EXIT_SUCCESS) { if(sub_bms_info_1.packet_common.m_total_vol >= sub_bms_info_2.packet_common.m_total_vol) { if(IS_CHARGE_IN()) { temp_op = CB_BAT2; } else { temp_op = CB_BAT1; } } else { if(IS_CHARGE_IN()) { temp_op = CB_BAT1; } else { temp_op = CB_BAT2; } } } else { temp_op = CB_BAT1; } } else if(Is_Sub_BMS_2_Normal() == SHARK_BATT_EXIT_SUCCESS) { temp_op = CB_BAT2; } return temp_op; #else if (sub_bms_info_1.connected) { return CB_BAT1_BAT2_AUTO; } if (sub_bms_info_2.connected) { return CB_BAT1_BAT2_AUTO; } if (work_normal) { if (Measure_Vol() > 20000) { return CB_BAT1_BAT2_AUTO; } if (shark_battery_ping(10) != SHARK_BATT_MASK_NONE) { return CB_BAT1_BAT2_AUTO; } } return CB_BAT_NO; #endif } uint8_t Check_CB_BAT_1(void) { uint8_t temp_op = CB_MAX; if(Is_Sub_BMS_1_Normal() == SHARK_BATT_EXIT_SUCCESS) { if((sub_bms_info_1.packet_common.bms_status & (BMS_STA_D_OPEN | BMS_STA_C_OPEN)) != (BMS_STA_D_OPEN | BMS_STA_C_OPEN)) { //sub_bms_info_1.sub_bms_cmd.operate = OP_OPEN_FET; //sub_bms_info_1.sub_bms_cmd.param = 0x03; if((sub_bms_info_1.packet_common.work_status &(ST_OVRDISCHRG_VOL|ST_PDOWN)) != 0) ; else temp_op = CB_BAT_NO; } // if((sub_bms_info_2.packet_common.bms_status & (BMS_STA_D_OPEN | BMS_STA_S_OPEN)) != 0) { sub_bms_info_2.sub_bms_cmd.operate = OP_OPEN_FET; sub_bms_info_2.sub_bms_cmd.param = 0x00; } } else { /*if(Is_Sub_BMS_2_Normal()) temp_op = CB_BAT2; else*/ temp_op = CB_BAT_NO; } return temp_op; } uint8_t Check_CB_BAT_2(void) { uint8_t temp_op = CB_MAX; if(Is_Sub_BMS_2_Normal() == SHARK_BATT_EXIT_SUCCESS) { if((sub_bms_info_2.packet_common.bms_status & (BMS_STA_D_OPEN | BMS_STA_C_OPEN)) != (BMS_STA_D_OPEN | BMS_STA_C_OPEN)) { //sub_bms_info_2.sub_bms_cmd.operate = OP_OPEN_FET; //sub_bms_info_2.sub_bms_cmd.param = 0x03; if((sub_bms_info_2.packet_common.work_status &(ST_OVRDISCHRG_VOL|ST_PDOWN)) != 0) ; else temp_op = CB_BAT_NO; } // if((sub_bms_info_1.packet_common.bms_status & (BMS_STA_D_OPEN | BMS_STA_S_OPEN)) != 0) { sub_bms_info_1.sub_bms_cmd.operate = OP_OPEN_FET; sub_bms_info_1.sub_bms_cmd.param = 0x00; } } else { /*if(Is_Sub_BMS_1_Normal()) temp_op = CB_BAT1; else*/ temp_op = CB_BAT_NO; } return temp_op; } uint8_t Check_CB_BAT1_BAT2_PARRALLEL(void) { uint8_t temp_op = CB_MAX; if(is_intelligent && CB_OPERATE_PRECEDENCE_PARRALLEL != PRE_PARRALLEL) { temp_op = Select_One_BAT(); return temp_op; } // if(Is_Sub_BMS_1_Normal() == SHARK_BATT_EXIT_SUCCESS && Is_Sub_BMS_2_Normal() == SHARK_BATT_EXIT_SUCCESS) { if((sub_bms_info_1.packet_common.bms_status & (BMS_STA_D_OPEN | BMS_STA_C_OPEN)) != (BMS_STA_D_OPEN | BMS_STA_C_OPEN)) { sub_bms_info_1.sub_bms_cmd.operate = OP_OPEN_FET; sub_bms_info_1.sub_bms_cmd.param = 0x03; } if((sub_bms_info_2.packet_common.bms_status & (BMS_STA_D_OPEN | BMS_STA_C_OPEN)) != (BMS_STA_D_OPEN | BMS_STA_C_OPEN)) { sub_bms_info_2.sub_bms_cmd.operate = OP_OPEN_FET; sub_bms_info_2.sub_bms_cmd.param = 0x03; } } else { temp_op = Select_One_BAT(); return temp_op; } // if(sub_bms_info_1.packet_common.m_current > 20000 || sub_bms_info_2.packet_common.m_current > 20000) { temp_op = Select_One_BAT(); return temp_op; } if (shark_battery_get_voltage_delta() > PARRALLEL_DELTA_VOL) { temp_op = Select_One_BAT(); return temp_op; } return temp_op; } void Series_Delay_Timeout(void) { if(Series_delay.set) { Series_delay.count++; } } #ifdef HAN_GUO_VERSION uint8_t Select_One_BAT_Han_Guo(void) { uint8_t temp_op = CB_BAT_NO; if(Is_Sub_BMS_1_Normal()) { if(Is_Sub_BMS_2_Normal()) { if(sub_bms_info_1.packet_common.m_total_vol >= sub_bms_info_2.packet_common.m_total_vol) { if(IS_CHARGE_IN()) { temp_op = CB_BAT2; } else { temp_op = CB_BAT1; } } else { if(IS_CHARGE_IN()) { temp_op = CB_BAT1; } else { temp_op = CB_BAT2; } } } else { temp_op = CB_BAT1; } } else if(Is_Sub_BMS_2_Normal()) { temp_op = CB_BAT2; } else { if(sub_bms_info_1.packet_common.m_total_vol < sub_bms_info_2.packet_common.m_total_vol) temp_op = CB_BAT2; else temp_op = CB_BAT1; } return temp_op; } #endif static u8 shark_battery_get_series_error(void) { if (Is_Sub_BMS_1_Normal() != SHARK_BATT_EXIT_SUCCESS) { return 1; } if (Is_Sub_BMS_2_Normal() != SHARK_BATT_EXIT_SUCCESS) { return 2; } if (!shark_battery_check_power(&sub_bms_info_1, SHARK_BATT_POWER_FULL)) { return 3; } if (!shark_battery_check_power(&sub_bms_info_2, SHARK_BATT_POWER_FULL)) { return 4; } return 0; } uint8_t Check_CB_BAT1_BAT2_SERIES(void) { uint8_t temp_op = CB_MAX; if(is_intelligent && CB_OPERATE_PRECEDENCE_PARRALLEL != PRE_SERIES) { temp_op = Select_One_BAT(); return temp_op; } #ifndef HAN_GUO_VERSION if (shark_battery_series_locked) { temp_op = Select_One_BAT(); return temp_op; } #endif if(IS_CHARGE_IN()) { temp_op = Select_One_BAT(); return temp_op; } if (shark_battery_get_series_error() != 0) { if (shark_xl_check() && QD_Dect()) { shark_battery_series_locked = shark_true; println("series locked"); } else { println("no xl"); } #ifdef HAN_GUO_VERSION temp_op = Select_One_BAT_Han_Guo(); #else temp_op = Select_One_BAT(); #endif return temp_op; } /*if(Measure_Vol() <= CHECK_SERIES_VOL) { temp_op = Select_One_BAT(); return temp_op; }*/ if (shark_battery_get_voltage1() < CHECK_SERIES_PROTECT_VOL || shark_battery_get_voltage2() < CHECK_SERIES_PROTECT_VOL) { if(Series_delay.set == 0) { Series_delay.set = 1; Series_delay.count = 0; } } else { memset(&Series_delay,0x00,sizeof(Series_delay)); } if(Series_delay.set&&Series_delay.count >= SERIES_UNDER_VOL_TIME_OUT) { memset(&Series_delay,0x00,sizeof(Series_delay)); shark_battery_series_locked = shark_true; return Select_One_BAT(); } if(sub_bms_info_1.packet_common.m_percent < SERIES_EXIT_PERCENT || sub_bms_info_2.packet_common.m_percent < SERIES_EXIT_PERCENT) { temp_op = Select_One_BAT(); return temp_op; } return temp_op; } uint8_t power_switch_from = 0; void Power_On_Normal(uint8_t enable,uint8_t from) { if(enable) { //FL_Enable(1); //ACC2_Enable(1); Can_Power_Enable(1); Enable_12V(1); one_bat_initial = 0; Reset_Enter_Sleep_Delay(); /*if(serise_low_qd_status == 1) { QD_Enable(1); serise_low_qd_status = 0; }*/ } else { #if 0 NVIC_SystemReset(); #else // FL_Enable(0); ACC2_Enable(0); Can_Power_Enable(0); Can_Stop_Send(); //QD_Enable(0); QD_Enable_From(0,1); ADAS_Enable(0); Enable_12V(0); Set_Enter_Sleep_Delay(); #endif } work_normal = enable; power_switch_from = from; } void Check_CB_Operate_State(void) { uint8_t temp_op = CB_MAX; switch(cb_operate_state) { case CB_BAT_NO: temp_op = Select_One_BAT(); break; case CB_BAT1: temp_op = Check_CB_BAT_1(); break; case CB_BAT2: temp_op = Check_CB_BAT_2(); break; case CB_BAT1_BAT2_PARRALLEL: temp_op = Check_CB_BAT1_BAT2_PARRALLEL(); break; case CB_BAT1_BAT2_SERIES: temp_op = Check_CB_BAT1_BAT2_SERIES(); break; default: return; } #if CONFIG_SOAK_ENABLE if (Is_Soak()) { temp_op = CB_BAT_NO; } #endif if(temp_op >= CB_MAX) { //test-start if(work_normal == 0) { Power_On_Normal(1,3); } //test-end return; } else if(temp_op == CB_BAT_NO) { if(work_normal == 1) { Power_On_Normal(0,1); } } else { /*if(work_normal == 1) { Power_On_Normal(0); }*/ } Battery_CB_Switch(temp_op); } uint8_t Is_BAT1_Lock(void) { return 0; } uint8_t Is_BAT2_Lock(void) { return 0; } void Charger_Out(void) { Set_Charger_In(0); if(sub_bms_info_1.packet_common.m_percent >= 100 && sub_bms_info_2.packet_common.m_percent >= 100) battery_charged_full = 1; } void Check_Charge_In(void) { if(sub_bms_info_1.packet_common.m_percent < 97 || sub_bms_info_2.packet_common.m_percent < 97) battery_charged_full = 0; //if(gpio_input_bit_get(GPIOC,GPIO_PIN_4) == 0) { // Set_Charger_In(1); } if(IS_CHARGE_IN()) { if(is_intelligent) { CB_OPERATE_PRECEDENCE_PARRALLEL = PRE_PARRALLEL; if(cb_operate_state == CB_BAT1_BAT2_SERIES) { if(Battery_Change_Mode(CFG_BAT1_BAT2_PARRALLEL) == CB_BAT1_BAT2_PARRALLEL) CHARG_PROTECT_OPEN(1); } else { CHARG_PROTECT_OPEN(1); } } else { if(cb_operate_state == CB_BAT1_BAT2_SERIES) { ; } else CHARG_PROTECT_OPEN(1); } if(IS_CHARGER_ON()) { if(sub_bms_info_1.packet_common.charge_flag == 0 && sub_bms_info_2.packet_common.charge_flag == 0) { if(charge_delay.set == 0) { charge_delay.set = 1; charge_delay.count = 0; } else { if(charge_delay.count >= CHARGE_DELAY_TIME_OUT_COUNT) { memset(&charge_delay,0x00,sizeof(charge_delay)); Charger_Out(); } } } else { memset(&charge_delay,0x00,sizeof(charge_delay)); } if(cb_operate_state == CB_BAT1_BAT2_PARRALLEL) { if(sub_bms_info_1.packet_common.charge_flag) { if((sub_bms_info_2.packet_common.work_status&ST_DISCHRG_CUR)!= 0) { if(sub_bms_info_1.packet_common.m_current + sub_bms_info_2.packet_common.m_current\ < 5000) Charger_Out(); } } else if(sub_bms_info_2.packet_common.charge_flag) { if((sub_bms_info_1.packet_common.work_status&ST_DISCHRG_CUR)!= 0) { if(sub_bms_info_1.packet_common.m_current + sub_bms_info_2.packet_common.m_current\ < 5000) Charger_Out(); } } } } } else { CHARG_PROTECT_OPEN(0); if(is_intelligent) { CB_OPERATE_PRECEDENCE_PARRALLEL = CB_OPERATE_PRECEDENCE_Config; } } } uint8_t Change_Mode_Sub_BMS_1_Normal(void) { return Is_Sub_BMS_1_Normal() == SHARK_BATT_EXIT_SUCCESS; } uint8_t Change_Mode_Sub_BMS_2_Normal(void) { return Is_Sub_BMS_2_Normal() == SHARK_BATT_EXIT_SUCCESS; } uint8_t Change_Mode_Sub_BMS_PARRALLEL(void) { // if(cb_operate_state == CB_BAT_NO) return 0; if(is_intelligent && CB_OPERATE_PRECEDENCE_PARRALLEL != PRE_PARRALLEL) return 0; // if(Is_Sub_BMS_1_Normal() == SHARK_BATT_EXIT_SUCCESS && Is_Sub_BMS_2_Normal() == SHARK_BATT_EXIT_SUCCESS) ; else return 0; if (shark_battery_get_voltage_delta() > PARRALLEL_BL_DELTA_VOL) { return 0; } return 1; } uint8_t Change_Mode_Sub_BMS_SERIES(void) { if (!shark_battery_series_enabled()) { return 0; } #if 0 // if(!(cb_operate_state == CB_BAT1 || cb_operate_state == CB_BAT2)) return 0; #endif if(is_intelligent && CB_OPERATE_PRECEDENCE_PARRALLEL != PRE_SERIES) return 0; #if 0 if(IS_CHARGE_IN()) return 0; #endif if(!(Is_Sub_BMS_1_Normal() == SHARK_BATT_EXIT_SUCCESS && Is_Sub_BMS_2_Normal() == SHARK_BATT_EXIT_SUCCESS)) return 0; /*if(cb_operate_state == CB_BAT1) { if((sub_bms_info_2.packet_common.bms_status & BMS_STA_S_BAHU) != 0) { return 0; } } else if(cb_operate_state == CB_BAT2) { if((sub_bms_info_1.packet_common.bms_status & BMS_STA_S_BAHU) != 0) { return 0; } }*/ #ifdef HAN_GUO_VERSION if(sub_bms_info_1.packet_common.m_percent < 2\ || sub_bms_info_2.packet_common.m_percent < 2) return 0; #else if(shark_battery_get_voltage1() < SERIES_PROTECT_VOL || shark_battery_get_voltage2() < SERIES_PROTECT_VOL ) return 0; if(sub_bms_info_1.packet_common.m_percent < SERIES_ENTER_PERCENT || sub_bms_info_2.packet_common.m_percent < SERIES_ENTER_PERCENT) return 0; #endif return 1; } uint8_t Battery_Change_Mode(uint8_t cfg_mode) { uint8_t cb_operate = CB_MAX; if(!work_normal) return 0; switch(cfg_mode) { case CFG_BAT_NO: return 0; case CFG_BAT1: if(Change_Mode_Sub_BMS_1_Normal()) { cb_operate = CB_BAT1; } break; case CFG_BAT2: if(Change_Mode_Sub_BMS_2_Normal()) { cb_operate = CB_BAT2; } break; case CFG_BAT1_BAT2_PARRALLEL: if(Change_Mode_Sub_BMS_PARRALLEL()) { cb_operate = CB_BAT1_BAT2_PARRALLEL; } break; case CFG_BAT1_BAT2_SERIES: if(Change_Mode_Sub_BMS_SERIES()) { cb_operate = CB_BAT1_BAT2_SERIES; } break; case CFG_MAX: default: return 0; } if(cb_operate >= CB_MAX) return 0; return Battery_CB_Switch(cb_operate); } void Intelligent_Management_Battery(void) { if(is_intelligent) { if(CB_OPERATE_PRECEDENCE_PARRALLEL == PRE_PARRALLEL) { if(cb_operate_state == CB_BAT1_BAT2_PARRALLEL) return; else if(Battery_Change_Mode(CFG_BAT1_BAT2_PARRALLEL) == CB_BAT1_BAT2_PARRALLEL) return; } else { if(cb_operate_state == CB_BAT1_BAT2_SERIES) return; if(Battery_Change_Mode(CB_BAT1_BAT2_SERIES) == CB_BAT1_BAT2_SERIES) return; } switch(cb_operate_state) { case CB_BAT1: if(IS_CHARGER_ON()) { if (shark_battery_charge_complete1() || shark_battery_get_capacity2() + SHARK_CHARGE_CAPACITY_DELTA < shark_battery_get_capacity1()) { Battery_Change_Mode(CFG_BAT2); } } else { if((abs(sub_bms_info_1.packet_common.m_current) <= 1000)\ &&(shark_battery_get_voltage2() > shark_battery_get_voltage1()+ONE_BATTERY_DELTA_VOL)) { Battery_Change_Mode(CFG_BAT2); } } break; case CB_BAT2: if(IS_CHARGER_ON()) { if (shark_battery_charge_complete2() || shark_battery_get_capacity1() + SHARK_CHARGE_CAPACITY_DELTA < shark_battery_get_capacity2()) { Battery_Change_Mode(CFG_BAT1); } } else { if((abs(sub_bms_info_2.packet_common.m_current) <= 1000)\ &&(shark_battery_get_voltage1() > shark_battery_get_voltage2()+ONE_BATTERY_DELTA_VOL)) { Battery_Change_Mode(CFG_BAT1); } } break; case CB_BAT_NO: case CB_BAT1_BAT2_SERIES: default: break; } } } void Check_Battery_Small_Current(void) { switch(cb_operate_state) { case CB_BAT1: if((sub_bms_info_2.packet_common.bms_status & BMS_STA_S_OPEN) == BMS_STA_S_OPEN) { sub_bms_info_2.sub_bms_cmd.operate = OP_OPEN_FET; sub_bms_info_2.sub_bms_cmd.param = 0x00; } break; case CB_BAT2: if((sub_bms_info_1.packet_common.bms_status & BMS_STA_S_OPEN) == BMS_STA_S_OPEN) { sub_bms_info_1.sub_bms_cmd.operate = OP_OPEN_FET; sub_bms_info_1.sub_bms_cmd.param = 0x00; } break; case CB_BAT_NO: case CB_BAT1_BAT2_PARRALLEL: case CB_BAT1_BAT2_SERIES: default: break; } } void Save_Neng_Hao_Bi(uint8_t *data,uint16_t len) { uint32_t capacity = (REG32(0x1FFFF7E0) & 0xFFFF) << 10; uint32_t address = 0x08000000 + (capacity - SYLC_FLASH_ADDRESS); uint8_t i = 0; uint32_t df_value = 0x0325; fmc_unlock(); Flash_flag_clear(); fmc_page_erase(address); Flash_flag_clear(); fmc_lock(); fmc_unlock(); i = 0; while(i 600) { save_param_delay.count = 0; g_event |= SAVE_PARAM_EVENT; } } } void Initial_Neng_Hao_Bi(void) { uint32_t capacity = (REG32(0x1FFFF7E0) & 0xFFFF) << 10; uint32_t address = 0x08000000 + (capacity - SYLC_FLASH_ADDRESS); SYLC_SAVE_PARM *sylc_temp = (SYLC_SAVE_PARM *)address; memset(&sheng_yu_li_cheng,0x00,sizeof(sheng_yu_li_cheng)); if(sylc_temp->sy_valid_flag != SY_VALID_FLAG_KEY) { sheng_yu_li_cheng.sy_ss_parm.sy_valid_flag = SY_VALID_FLAG_KEY; sheng_yu_li_cheng.sy_ss_parm.neng_hao_bi = nhb_default; Save_Neng_Hao_Bi((uint8_t *)&sheng_yu_li_cheng.sy_ss_parm,sizeof(sheng_yu_li_cheng.sy_ss_parm)); } else { sheng_yu_li_cheng.sy_ss_parm = *sylc_temp; if(sheng_yu_li_cheng.sy_ss_parm.neng_hao_bi < NENG_HAO_BI_MIN) { sheng_yu_li_cheng.sy_ss_parm.neng_hao_bi = NENG_HAO_BI_MIN; Save_Neng_Hao_Bi((uint8_t *)&sheng_yu_li_cheng.sy_ss_parm,sizeof(sheng_yu_li_cheng.sy_ss_parm)); } if(sheng_yu_li_cheng.sy_ss_parm.neng_hao_bi > NENG_HAO_BI_MAX) { sheng_yu_li_cheng.sy_ss_parm.neng_hao_bi = NENG_HAO_BI_MAX; Save_Neng_Hao_Bi((uint8_t *)&sheng_yu_li_cheng.sy_ss_parm,sizeof(sheng_yu_li_cheng.sy_ss_parm)); } } save_param_delay.set = 1; save_param_delay.count = 0; } extern uint8_t Get_QD_State(void); uint8_t Reset_Cal(void) { if(Get_QD_State() == 0) return 1; if(sheng_yu_li_cheng.sy_dan_ci_li_cheng_temp < sheng_yu_li_cheng.sy_dan_ci_li_cheng) return 1; if(sheng_yu_li_cheng.sy_percent_dlta && sheng_yu_li_cheng.sy_dan_ci_li_cheng <= 50) return 1; return 0; } void Cal_Sheng_Yu_Li_Cheng(void) { uint8_t dlta = 0; uint32_t lc_temp; if(Reset_Cal()) { sheng_yu_li_cheng.sy_percent_1 = sub_bms_info_1.packet_common.m_percent; sheng_yu_li_cheng.sy_percent_2 = sub_bms_info_2.packet_common.m_percent; sheng_yu_li_cheng.sy_percent_dlta = 0; //Left_Light_Enable(1); } sheng_yu_li_cheng.sy_dan_ci_li_cheng = sheng_yu_li_cheng.sy_dan_ci_li_cheng_temp; if(sub_bms_info_1.connected && sub_bms_info_1.packet_common.m_percent != 0) { if(sheng_yu_li_cheng.sy_percent_1 > sub_bms_info_1.packet_common.m_percent) { dlta = sheng_yu_li_cheng.sy_percent_1 - sub_bms_info_1.packet_common.m_percent; sheng_yu_li_cheng.sy_percent_dlta += dlta; } } sheng_yu_li_cheng.sy_percent_1 = sub_bms_info_1.packet_common.m_percent; if(sub_bms_info_2.connected && sub_bms_info_2.packet_common.m_percent != 0) { if(sheng_yu_li_cheng.sy_percent_2 > sub_bms_info_2.packet_common.m_percent) { dlta = sheng_yu_li_cheng.sy_percent_2 - sub_bms_info_2.packet_common.m_percent; sheng_yu_li_cheng.sy_percent_dlta += dlta; } } sheng_yu_li_cheng.sy_percent_2 = sub_bms_info_2.packet_common.m_percent; sheng_yu_li_cheng.sy_percent_total = sub_bms_info_1.packet_common.m_percent + sub_bms_info_2.packet_common.m_percent; if(dlta && sheng_yu_li_cheng.sy_percent_dlta >= 7 && sheng_yu_li_cheng.sy_dan_ci_li_cheng > 700 ) { double nhb_temp = (double)(sheng_yu_li_cheng.sy_dan_ci_li_cheng)/sheng_yu_li_cheng.sy_percent_dlta; if(nhb_temp < NENG_HAO_BI_MIN) nhb_temp = NENG_HAO_BI_MIN; if(nhb_temp > NENG_HAO_BI_MAX) nhb_temp = NENG_HAO_BI_MAX; sheng_yu_li_cheng.sy_ss_parm.neng_hao_bi = sheng_yu_li_cheng.sy_ss_parm.neng_hao_bi*0.8 + nhb_temp*0.2; } else { } lc_temp = (uint32_t)(sheng_yu_li_cheng.sy_percent_total*sheng_yu_li_cheng.sy_ss_parm.neng_hao_bi/1000); if(lc_temp > 200) lc_temp = 200; #if 0 //bang zi ce shi start sheng_yu_li_cheng.sy_yu_ji_ke_xing_shi_li_cheng = (uint8_t)(lc_temp*2); //bang zi ce shi end #else sheng_yu_li_cheng.sy_yu_ji_ke_xing_shi_li_cheng = (uint8_t)lc_temp; #endif if(sheng_yu_li_cheng.sy_yu_ji_ke_xing_shi_li_cheng == 0\ || (sub_bms_info_1.packet_common.bms_status & BMS_STA_JIAO_YAN)\ || (sub_bms_info_2.packet_common.bms_status & BMS_STA_JIAO_YAN)) { sheng_yu_li_cheng.sy_yu_ji_ke_xing_shi_li_cheng = sub_bms_info_1.packet_common.yjkxslc\ + sub_bms_info_2.packet_common.yjkxslc; } } void Save_Param(void) { Save_Neng_Hao_Bi((uint8_t *)&sheng_yu_li_cheng.sy_ss_parm,sizeof(sheng_yu_li_cheng.sy_ss_parm)); }