#include "common.h" #include "drv_usart.h" #include "app_rs485_1.h" #include "app.h" #include "hardware_test.h" #include "app_end_ctr.h" #include "drv_io.h" #include "measure_vol.h" #include "shark_xl.h" #include "shark_charge.h" SUB_BMS_INFO sub_bms_info_1 = { .uart = USART0, .address = SUB_BMS_ADDRESS_1, }; TEST_INFO test_info; static int8_t Get_Check_Sum_1(uint16_t*value, const uint8_t*data,uint16_t size) { uint32_t checksum; if((NULL==value)||(NULL==data)||(0==size)) { return 0; } // checksum = 0; while(size>1) { checksum += *(uint16_t*)data; data += 2; size -= 2; } // if(size>0) { checksum += *data; } // while(checksum>>16) { checksum = (checksum&0xFFFF)+(checksum>>16); } // *value = (uint16_t)~checksum; return 1; } void shark_battery_clear(SUB_BMS_INFO *info) { shark_battery_full = shark_false; info->update_mask = 0xFF; info->sub_bms_cmd.operate = OP_READ_INFO; memset(&info->packet_common, 0x00, sizeof(info->packet_common)); memset(&info->bat_dev_info, 0x00, sizeof(info->bat_dev_info)); memset(&info->bat_times, 0x00, sizeof(info->bat_times)); memset(&info->cell_vol, 0x00, sizeof(info->cell_vol)); memset(&info->temp_other, 0x00, sizeof(info->temp_other)); memset(&info->sub_bms_cmd, 0x00, sizeof(info->sub_bms_cmd)); } static int8_t Handle_Sub_BMS_CMD_1(SUB_BMS_INFO *info, const u8 *buff, u8 length) { COMMAND_BODY *bms = (COMMAND_BODY *) buff; int8_t bStatus; uint16_t count; do { if(bms->type != info->address || bms->dir != BMS_DIR || bms->bStatus == 0) break; //CRC count = bms->checksum; bms->checksum = 0; bStatus = Get_Check_Sum_1((void*)&bms->checksum, buff, bms->size); if(1!=bStatus || count != bms->checksum) { break; } //handle frame count = sizeof(COMMAND_BODY); memcpy(&info->packet_common, buff + count,sizeof(info->packet_common)); count += sizeof(info->packet_common); info->connected = CONFIG_UART_GOOD; info->send_state = SHARK_SEND_SUCCESS; //bang zi ce shi start //temp_bms ->packet_common.m_percent /= 2; //bang zi ce shi end if((info->packet_common.operate_result&0x01) != 0x01) break; switch((info->packet_common.operate_result&0xF0)>>4) { case OP_NONE: break; case OP_BOND: break; case OP_WRITE_SN: break; case OP_PAIR: break; case OP_UPDATE_PAIR: break; case OP_READ_INFO: memcpy(&info->bat_dev_info, buff + count,sizeof(info->bat_dev_info)); count += sizeof(info->bat_dev_info); info->update_mask &= ~SHARK_BATT_INFO_VERTION; break; case OP_ALARM_TIMES: memcpy(&info->bat_times, buff + count, sizeof(info->bat_times)); count += sizeof(info->bat_times); info->update_mask &= ~SHARK_BATT_INFO_TIMES; break; case OP_CELL_VOL: memcpy(&info->cell_vol, buff + count, sizeof(info->cell_vol)); count += sizeof(info->cell_vol); info->update_mask &= ~SHARK_BATT_INFO_CELL_VOL; break; case OP_TEMP_OTHER: memcpy(&info->temp_other, buff + count, sizeof(info->temp_other)); count += sizeof(info->temp_other); info->update_mask &= ~SHARK_BATT_INFO_TEMP; break; case OP_OPEN_FET: break; case OP_CLEAR_PAIR: break; case OP_UPDATE_SOFTWARE_REQ: break; case OP_UPDATE_SOFTWARE: break; default:break; } if(((info->packet_common.operate_result&0xF0)>>4) == info->sub_bms_cmd.operate) { memset(&info->sub_bms_cmd,0x00,sizeof(info->sub_bms_cmd)); if (info->update_mask != 0) { if ((info->update_mask & SHARK_BATT_INFO_VERTION) != 0) { info->sub_bms_cmd.operate = OP_READ_INFO; } else if ((info->update_mask & SHARK_BATT_INFO_TIMES) != 0) { info->sub_bms_cmd.operate = OP_ALARM_TIMES; } else if ((info->update_mask & SHARK_BATT_INFO_CELL_VOL) != 0) { info->sub_bms_cmd.operate = OP_CELL_VOL; } else if ((info->update_mask & SHARK_BATT_INFO_TEMP) != 0) { info->sub_bms_cmd.operate = OP_TEMP_OTHER; } else { info->sub_bms_cmd.operate = OP_NONE; info->update_mask = 0; } info->tx_pending = shark_true; } else { info->sub_bms_cmd.operate = OP_NONE; } } return 1; }while(0); return 0; } shark_bool shark_battery_send_command(SUB_BMS_INFO *info) { int8_t bStatus;// 默认需要回复 COMMAND_BODY*body = (COMMAND_BODY *) info->tx_buff; uint8_t *buf = info->tx_buff; if (info->send_state == SHARK_SEND_PENDING) { return shark_false; } // 填帧头 body->size = sizeof(COMMAND_BODY); body->type = info->address; body->protocol = 'B'; body->cmd = SET_COMMAND; body->dir = BMS_DIR; body->checksum = 0; body->bStatus = 0; // 填帧数据 //实时转速 buf[body->size++] = 0; //本次电门打开已经行驶的里程 buf[body->size++] = 0; buf[body->size++] = 0; buf[body->size++] = 0; buf[body->size++] = 0; //电门开关信号 buf[body->size++] = 0; //操作 buf[body->size++] = info->sub_bms_cmd.operate; //对码 buf[body->size++] = shark_charger_state == SHARK_CHG_INSERT ? CW_CHE_SHANG_CHARGER : CW_CHE_SHANG_NO_CHARGER; buf[body->size++] = 0; buf[body->size++] = 0; buf[body->size++] = 0; //更换对码,新对码 buf[body->size++] = 0; buf[body->size++] = 0; buf[body->size++] = 0; buf[body->size++] = 0; switch(info->sub_bms_cmd.operate) { case OP_NONE: break; case OP_BOND: break; case OP_WRITE_SN: switch(info->sub_bms_cmd.param) { case 3: buf[body->size++] = (uint8_t)(info->sub_bms_cmd.param); break; case 4: buf[body->size++] = (uint8_t)(info->sub_bms_cmd.param); break; } break; case OP_PAIR: break; case OP_UPDATE_PAIR: break; case OP_READ_INFO: break; case OP_ALARM_TIMES: break; case OP_CELL_VOL: break; case OP_OPEN_FET: buf[body->size++] = (uint8_t)(info->sub_bms_cmd.param); break; case OP_UPDATE_SOFTWARE_REQ: break; case OP_UPDATE_SOFTWARE: break; case OP_CLEAR_PAIR: break; default:break; } bStatus = Get_Check_Sum_1((void*)&body->checksum,(void*)body,body->size); if(1!=bStatus) { return shark_false; } info->send_state = SHARK_SEND_PENDING; shark_uart_write(info, body->size); return shark_true; } shark_bool shark_battery_send_command1(void) { if (sub_bms_info_1.send_state != SHARK_SEND_PENDING) { return shark_false; } return shark_battery_send_command(&sub_bms_info_1); } shark_bool shark_battery_send_command2(void) { if (sub_bms_info_2.send_state != SHARK_SEND_PENDING) { return shark_false; } return shark_battery_send_command(&sub_bms_info_2); } shark_bool shark_battery_process(SUB_BMS_INFO *info, const u8 *buff, u8 length) { if (length != buff[0]) { if(memcmp(buff, "zhengjiceshi",12) == 0 && ht_mode == 0) { Writer_HT_Flash(1); __set_FAULTMASK(1); NVIC_SystemReset(); } return 0; } if (length > sizeof(COMMAND_BODY)) { if(!Handle_Sub_BMS_CMD_1(info, buff, length)) { return 0; } } return 1; } void Sub_BMS_1_Initial(void) { shark_uart_init(); sub_bms_info_1.sub_bms_cmd.operate = OP_READ_INFO; sub_bms_info_2.sub_bms_cmd.operate = OP_READ_INFO; } static shark_battery_exit_t shark_battery_is_normal_raw(SUB_BMS_INFO *info, shark_battery_power_t power) { u16 work_status; u16 work_mask; if (info->define_error != D_BMS_ERROR_NO) { return SHARK_BATT_EXIT_ERROR; } if (info->test_error != D_BMS_ERROR_NO) { return SHARK_BATT_EXIT_ERROR; } if (shark_charger_state == SHARK_CHG_INSERT) { work_mask = BATT_CHARGE_ERRORS; } else { work_mask = BATT_DISCHARGE_ERRORS; } work_status = info->packet_common.work_status & work_mask; if (work_status != 0) { info->work_error = work_status; return SHARK_BATT_EXIT_ERROR; } if (info->connected == 0) { if (info->used == shark_false) { return SHARK_BATT_EXIT_485; } if (shark_xl_check_with_qd() == shark_false) { return SHARK_BATT_EXIT_485; } if (cb_operate_state == CB_BAT1_BAT2_SERIES) { if (Measure_Vol() < SERIES_VOLTAGE_MIN) { return SHARK_BATT_EXIT_485; } } else if (Measure_Vol() < SINGLE_VOLTAGE_MIN) { return SHARK_BATT_EXIT_485; } } if (!shark_battery_check_power(info, power)) { return SHARK_BATT_EXIT_POWER; } return SHARK_BATT_EXIT_SUCCESS; } shark_battery_exit_t shark_battery_is_normal(SUB_BMS_INFO *info, shark_battery_power_t power) { shark_battery_exit_t code = shark_battery_is_normal_raw(info, power); if (code != SHARK_BATT_EXIT_SUCCESS) { info->exit_code = code; info->exit_times++; } return code; } shark_battery_exit_t Is_Sub_BMS_1_Normal(void) { return shark_battery_is_normal(&sub_bms_info_1, SHARK_BATT_POWER_ANY); } u32 shark_battery_get_voltage(SUB_BMS_INFO *info) { return info->packet_common.m_total_vol - (info->packet_common.m_current / 30); } u32 shark_battery_get_voltage_delta(void) { u32 voltage1 = shark_battery_get_voltage1(); u32 voltage2 = shark_battery_get_voltage2(); if (voltage1 > voltage2) { return voltage1 - voltage2; } else { return voltage2 - voltage1; } } u32 shark_battery_get_voltage_min(void) { u32 voltage1 = shark_battery_get_voltage1(); u32 voltage2 = shark_battery_get_voltage2(); if (voltage1 < voltage2) { return voltage1; } else { return voltage2; } } u32 shark_battery_get_voltage_max(void) { u32 voltage1 = shark_battery_get_voltage1(); u32 voltage2 = shark_battery_get_voltage2(); if (voltage1 > voltage2) { return voltage1; } else { return voltage2; } } static u8 shark_battery_get_power_param(shark_battery_power_t power) { switch (power) { case SHARK_BATT_POWER_SMALL: return 0x04; case SHARK_BATT_POWER_FULL: return 0x03; default: return 0x00; } } static void shark_battery_set_power_param(SUB_BMS_INFO *info, shark_battery_power_t power) { info->sub_bms_cmd.operate = OP_OPEN_FET; info->sub_bms_cmd.param = shark_battery_get_power_param(power); } shark_battery_power_t shark_battery_get_power(SUB_BMS_INFO *info) { if (info->connected != CONFIG_UART_GOOD) { return SHARK_BATT_POWER_FAULT; } if ((info->packet_common.bms_status & BMS_POWER_ALL) == BMS_POWER_ALL) { return SHARK_BATT_POWER_ALL; } if ((info->packet_common.bms_status & BMS_POWER_FULL) == BMS_POWER_FULL) { return SHARK_BATT_POWER_FULL; } if ((info->packet_common.bms_status & BMS_POWER_SMALL) == BMS_POWER_SMALL) { return SHARK_BATT_POWER_SMALL; } return SHARK_BATT_POWER_OFF; } shark_bool shark_battery_check_power(SUB_BMS_INFO *info, shark_battery_power_t power) { switch (power) { case SHARK_BATT_POWER_SMALL: return (info->packet_common.bms_status & BMS_POWER_SMALL) == BMS_POWER_SMALL; case SHARK_BATT_POWER_FULL: return(info->packet_common.bms_status & BMS_POWER_FULL) == BMS_POWER_FULL; case SHARK_BATT_POWER_ALL: return (info->packet_common.bms_status & BMS_POWER_ALL) == BMS_POWER_ALL; case SHARK_BATT_POWER_ANY: return shark_true; default: return (info->packet_common.bms_status & BMS_POWER_ALL) == 0; } } static void shark_battery_serial_wait_ready(void) { u64 time = shark_get_mseconds() + 200; while (sub_bms_info_1.send_state == SHARK_SEND_PENDING && time > shark_get_time_safe()); while (sub_bms_info_2.send_state == SHARK_SEND_PENDING && time > shark_get_time_safe()); if (sub_bms_info_1.connected > CONFIG_UART_PING) { sub_bms_info_1.connected = CONFIG_UART_PING; } if (sub_bms_info_2.connected > CONFIG_UART_PING) { sub_bms_info_2.connected = CONFIG_UART_PING; } } static void shark_battery_send_commands(void) { shark_battery_send_command(&sub_bms_info_1); shark_battery_send_command(&sub_bms_info_2); } static shark_battery_mask_t shark_battery_wait_response(void) { shark_battery_mask_t success = SHARK_BATT_MASK_NONE; while (shark_battery_send_pending(&sub_bms_info_1)) { shark_uart_poll_safe(); } while (shark_battery_send_pending(&sub_bms_info_2)) { shark_uart_poll_safe(); } if (shark_battery_send_success(&sub_bms_info_1)) { success |= SHARK_BATT_MASK_BAT1; } if (shark_battery_send_success(&sub_bms_info_2)) { success |= SHARK_BATT_MASK_BAT2; } return success; } shark_battery_mask_t shark_battery_set_power(shark_battery_power_t power1, shark_battery_power_t power2, shark_battery_mask_t mask) { shark_battery_mask_t success = SHARK_BATT_MASK_NONE; u8 times; shark_battery_serial_wait_ready(); for (times = 0; times < 3; times++) { shark_battery_mask_t response; shark_battery_set_power_param(&sub_bms_info_1, power1); shark_battery_set_power_param(&sub_bms_info_2, power2); shark_battery_send_commands(); response = shark_battery_wait_response(); if ((response & SHARK_BATT_MASK_BAT1) != 0 && shark_battery_check_power(&sub_bms_info_1, power1)) { success |= SHARK_BATT_MASK_BAT1; } if ((response & SHARK_BATT_MASK_BAT2) != 0 && shark_battery_check_power(&sub_bms_info_2, power2)) { success |= SHARK_BATT_MASK_BAT2; } if ((success & mask) == mask) { return mask; } } return success; } shark_battery_mask_t shark_battery_detect(u8 times) { shark_battery_mask_t success; shark_battery_serial_wait_ready(); for (success = SHARK_BATT_MASK_NONE; times > 0; times--) { sub_bms_info_1.sub_bms_cmd.operate = OP_READ_INFO; sub_bms_info_2.sub_bms_cmd.operate = OP_READ_INFO; shark_battery_send_commands(); success |= shark_battery_wait_response(); if (success == SHARK_BATT_MASK_BOTH) { break; } } return success; } shark_bool shark_battery_ping(u8 times) { while (shark_true) { if (shark_battery_detect(1) != SHARK_BATT_MASK_NONE) { return shark_true; } if (times > 0) { times--; } else { break; } } return shark_false; } shark_bool shark_battery_over_discharge(void) { if (shark_charger_state == SHARK_CHG_INSERT) { return shark_false; } if (sub_bms_info_1.connected && (sub_bms_info_1.packet_common.work_status & ST_OVRDISCHRG_VOL) == 0) { return shark_false; } if (sub_bms_info_2.connected && (sub_bms_info_2.packet_common.work_status & ST_OVRDISCHRG_VOL) == 0) { return shark_false; } return shark_true; } void Save_Test_Info_To_Flash(uint8_t *data,uint16_t len) { uint32_t capacity = (REG32(0x1FFFF7E0) & 0xFFFF) << 10; uint32_t address = 0x08000000 + (capacity - TEST_INFO_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(iti_flag != TI_VALID_FLAG_KEY) { test_info.ti_flag = TI_VALID_FLAG_KEY; Save_Test_Info_To_Flash((uint8_t *)&test_info,sizeof(test_info)); } else { test_info = *temp_test_info; test_info.ti_set = 0; } } void Save_Test_Info(void) { //if(test_info.ti_set == 0) // return; Save_Test_Info_To_Flash((uint8_t*)&test_info, sizeof(test_info)); } void Ca_Chu_Test_Info(void) { memset(&test_info, 0x00,sizeof(test_info)); test_info.ti_flag = TI_VALID_FLAG_KEY; Save_Test_Info_To_Flash((uint8_t *)&test_info,sizeof(test_info)); } void Check_Enable_Test_Info(void) { if(cb_operate_state == CB_BAT1_BAT2_SERIES) test_info.ti_set = 1; else test_info.ti_set = 0; } void shark_bms_set_vgs(shark_bms_vgs_t mask, uint8_t enable) { static uint8_t shark_bms_vgs_mask; if (enable) { if (shark_bms_vgs_mask == 0) { println("FL Enable"); } shark_bms_vgs_mask |= mask; gpio_bit_reset(GPIO_PORT_FL, GPIO_PIN_FL); } else { shark_bms_vgs_mask &= ~mask; if (shark_bms_vgs_mask == 0) { gpio_bit_set(GPIO_PORT_FL, GPIO_PIN_FL); println("FL Disable"); } } } void shark_bms_set_mos(shark_bool ss, shark_bool s11, shark_bool s21) { println("S11:%d, S21:%d, SS:%d", s11, s21, ss); shark_bms_set_vgs(SHARK_BMS_VGS_FV, s11); if (ss == 0) { gpio_bit_reset(GPIO_PORT_SS, GPIO_PIN_SS); } if (s11 == 0) { gpio_bit_reset(GPIO_PORT_S11, GPIO_PIN_S11); } if (s21 == 0) { gpio_bit_reset(GPIO_PORT_S21, GPIO_PIN_S21); } if (ss != 0) { gpio_bit_set(GPIO_PORT_SS, GPIO_PIN_SS); } if (s11 != 0) { gpio_bit_set(GPIO_PORT_S11, GPIO_PIN_S11); } if (s21 != 0) { gpio_bit_set(GPIO_PORT_S21, GPIO_PIN_S21); } }