#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 "app/nv_storage.h" #include "libs/logger.h" #include "protocol.h" #include "bms_message.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; switch(frame->key) { case CAN_KEY_BMS_SET_POWER: if (len != sizeof(pwr_cmd_t)){ 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; bresp.energy = get_soc()->energy; bresp.pack_current = measure_value()->load_current; bresp.pack_voltage = bms_state_get()->pack_voltage; bresp.max_temp = 0; 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 = *((uint32_t *)bms_health()); 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; 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; uint32_t *h = (uint32_t *)(bms_health()); sresp.health = (*h != 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/36.0f; soc.c_max = get_soc()->coulomb_max/36.0f; soc.c_now = get_soc()->coulomb_now/36.0f; soc.c_discharger = get_soc()->dischrger_coulomb/36.0f; soc.c_charger = get_soc()->charger_coulomb/36.0f; 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(); data_len = sizeof(*bms_health()); 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, len); 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 = 21; } 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 != 2) { result = 1; }else { set_log_level(frame->data[0], frame->data[1]); } protocol_send_ack(frame->head.can_addr, frame->key, result); break; case CAN_KEY_START_CALI: //measure_start_cali(); protocol_send_ack(frame->head.can_addr, frame->key, 1); break; } }