#include #include "app/sox/soc.h" #include "app/sox/measure.h" #include "app/sox/measure_task.h" #include "app/sox/health.h" #include "app/sox/state.h" #include "bsp/gpio.h" #include "bsp/ml5238.h" #include "bsp/fmc_flash.h" #include "bsp/cs1180.h" #include "app/nv_storage.h" #include "libs/logger.h" #include "protocol.h" #include "bms_message.h" #include "event_record.h" extern char* bsp_get_fversion(void); static uint8_t bms_insert = 0; static uint8_t bms_insert_ack = 0; //主要用来告知PSxxx是否刚插入,PSxxx答复后需要清除 void bms_message_update_insert(int is_hall_detect){ if (!is_hall_detect){ bms_insert = 0; bms_insert_ack = 0; }else { if (!bms_insert_ack) { bms_insert = 1; } } } void process_bms_message(can_frame_t *frame, int len){ int result = 0; uint8_t *data = NULL; int data_len = 0; // set_log_all(L_debug); switch(frame->key) { case CAN_KEY_BMS_SET_POWER: if (len != sizeof(pwr_cmd_t) || frame->head.can_addr != 0x42){//开关大电必须42发过来 result = 1; }else { pwr_cmd_t *cmd = (pwr_cmd_t *)frame->data; uint32_t user_request = USER_REQUEST_PENDING; if (cmd->charger_mask) { if (cmd->charger_fet){ user_request |= USER_REQUEST_CHARGER_ON; }else { user_request |= USER_REQUEST_CHARGER_OFF; } } if (cmd->discharger_mask) { if (cmd->discharger_fet){ user_request |= USER_REQUEST_DISCHARGER_ON; }else { user_request |= USER_REQUEST_DISCHARGER_OFF; } } if (cmd->small_mask) { if (cmd->small_power){ user_request |= USER_REQUEST_SMALLCURRENT_ON; }else { user_request |= USER_REQUEST_SMALLCURRENT_OFF; } } bms_state_get()->user_request = user_request; } protocol_send_ack(frame->head.can_addr, frame->key, result); break; case CAN_KEY_BMS_BASE_INFO:{ binfo_cmd_resp_t bresp; bresp.capacity = get_soc()->capacity; if (get_soc()->coulomb_now >= get_soc()->coulomb_min) { bresp.energy = get_soc()->coulomb_now - get_soc()->coulomb_min; }else{ bresp.energy = 0; } bresp.pack_current = measure_value()->load_current; bresp.pack_voltage = bms_state_get()->pack_voltage; bresp.max_temp = -100; for (int i = 0; i < PACK_TEMPS_NUM; i ++){ if (bresp.max_temp < measure_value()->pack_temp[i]){ bresp.max_temp = measure_value()->pack_temp[i]; } } bresp.health = bms_health()->i_status; if (bms_is_ps_charger_in()) {/*如果在底座或者车上(有充电器),提前置位过高/低温充电标志*/ bresp.health |= (bms_health()->lower_temp_deny_charger << 12 | bms_health()->over_temp_deny_charger << 14); } bresp.health &= ~(1 << 8); bresp.health |= ((get_soc()->flags & SOC_FLAG_CALIBRATED) != 0) << 8; stat_cmd_resp_t sresp; sresp.insert = bms_insert; sresp.is_charging = bms_state_get()->charging; sresp.discharger_fet = ml5238_is_discharging(); sresp.charger_fet = ml5238_is_charging(); sresp.small_power = AUX_VOL_IS_OPEN(); sresp.is_balancing = bms_state_get()->pack_balancing; bresp.state = *((uint8_t*)&sresp); data = (uint8_t *)&bresp; data_len = sizeof(bresp); protocol_send_bms_info(frame->head.can_addr, frame->key, data, data_len); break; } case CAN_KEY_BMS_CHARG_INFO:{ cinfo_cmd_resp_t cresp; cresp.charge_current = measure_value()->load_current; cresp.charge_remain_time = soc_get_charger_remain_time(); data = (uint8_t *)&cresp; data_len = sizeof(cresp); protocol_send_bms_info(frame->head.can_addr, frame->key, data, data_len); break; } case CAN_KEY_BMS_CLEAR: bms_insert_ack = 1; bms_insert = 0; bms_work_mode_set(WORK_MODE_AGING_TEST, 0); protocol_send_ack(frame->head.can_addr, frame->key, result); break; case CAN_KEY_BMS_GET_TIME:{ uint32_t time = shark_get_seconds(); data = (uint8_t *)&time; data_len = sizeof(time); protocol_send_bms_info(frame->head.can_addr, frame->key, data, data_len); break; } case CAN_KEY_BMS_GET_STAT: { stat_cmd_resp_t sresp; sresp.insert = bms_insert; sresp.is_charging = bms_state_get()->charging; sresp.discharger_fet = ml5238_is_discharging(); sresp.charger_fet = ml5238_is_charging(); sresp.small_power = AUX_VOL_IS_OPEN(); sresp.is_balancing = bms_state_get()->pack_balancing; sresp.health = (((uint16_t )(bms_health()->i_status)) != 0); data = (uint8_t *)&sresp; data_len = sizeof(sresp); protocol_send_bms_info(frame->head.can_addr, frame->key, data, data_len); break; } case CAN_KEY_BMS_TEMPS: { u8 temps[PACK_TEMPS_NUM * sizeof(int) + 1]; temps[0] = PACK_TEMPS_NUM; memcpy(temps+1, measure_value()->pack_temp, PACK_TEMPS_NUM * sizeof(int)); data = temps; data_len = PACK_TEMPS_NUM * sizeof(int) + 1; protocol_send_bms_info(frame->head.can_addr, frame->key, data, data_len); break; } case CAN_KEY_BMS_GET_CELLS: { cell_cmd_resp_t cells; cells.cell_num = CELLS_NUM; for (int i = 0; i < CELLS_NUM; i++){ cells.voltages[i] = measure_value()->cell_vol[i]; } data = (uint8_t *)&cells; data_len = sizeof(cells); protocol_send_bms_info(frame->head.can_addr, frame->key, data, data_len); break; } case CAN_KEY_GET_SOC_INFO: { soc_info_t soc; soc.c_min = get_soc()->coulomb_min; soc.c_max = get_soc()->coulomb_max; soc.c_now = get_soc()->coulomb_now; soc.c_discharger = get_soc()->dischrger_coulomb; soc.c_charger = get_soc()->charger_coulomb; soc.cycle = soc_get_cycle(); soc.calibrated = (get_soc()->flags & SOC_FLAG_CALIBRATED) != 0; data = (uint8_t *)&soc; data_len = sizeof(soc); protocol_send_bms_info(frame->head.can_addr, frame->key, data, data_len); break; } case CAN_KEY_BMS_GET_HEALTH_STAT: data = (uint8_t *)(&bms_health()->i_status); data_len = sizeof(bms_health()->i_status); protocol_send_bms_info(frame->head.can_addr, frame->key, data, data_len); break; case CAN_KEY_BMS_SET_WORK_MODE: if (len != 2) { result = 1; }else { result = bms_work_mode_set(frame->data[0], frame->data[1]); } protocol_send_ack(frame->head.can_addr, frame->key, result); break; case CAN_KEY_SET_SN: nv_save_sn((uint8_t *)frame->data+1, len-2); protocol_send_ack(frame->head.can_addr, frame->key, result); break; case CAN_KEY_GET_SN: { uint8_t sn[32]; int sn_len = nv_read_sn(sn, sizeof(sn)); if (sn_len <= 0){ sn[0] = 'B'; memset(sn + 1, '0', sizeof(sn) - 1); sn_len = 18; } data = (u8 *)sn; data_len = sn_len; protocol_send_bms_info(frame->head.can_addr, frame->key, data, data_len); break; } case CAN_KEY_GET_VERSION: { data = (u8*)bsp_get_fversion(); data_len = strlen((char *)data); protocol_send_bms_info(frame->head.can_addr, frame->key, data, data_len); break; } case CAN_KEY_SET_LOGGER: if (len < 1) { set_log_all(L_debug); ml5238_reg_log(); //just for debug cs1180_log(); health_log(); soc_log(); bms_state_log(); result = 1; } else if (len < 2) { set_log_all(frame->data[0]); ml5238_reg_log(); //just for debug cs1180_log(); health_log(); soc_log(); bms_state_log(); } else if (len < 3){ set_log_level(frame->data[0], frame->data[1]); } protocol_send_ack(frame->head.can_addr, frame->key, result); break; case CAN_KEY_RESTORE_NV: { restore_nv_cmd_t *nv = (restore_nv_cmd_t *)frame->data; nv_save_sn(nv->sn, nv->sn_len); soc_restore_by_iap(nv->flags, nv->capacity); protocol_send_ack(frame->head.can_addr, frame->key, 1); break; } case CAN_KEY_MIN_SOC: get_soc()->coulomb_min = (u32)frame->data[0] * 3600.0f; nv_save_all_soc(); protocol_send_ack(frame->head.can_addr, frame->key, 1); break; case CAN_KEY_GET_EVENT: { u8 event[sizeof(event_record_t) * 8 + 1]; u16 offset = DECODE_U16(frame->data); int num = get_event(8, offset, event + 1); *event = (u8)num; protocol_send_bms_info(frame->head.can_addr, frame->key, event, sizeof(event_record_t) * num + 1); break; } default: break; } }