#include "common.h" #include "drv_usart_2.h" #include "app_rs485_2.h" #include "app.h" #include "hardware_test.h" #include "app_end_ctr.h" //uart2 static uint8_t app_rs485_buf[TX_2_BUFFER_SIZE]; static uint8_t bms_addr = SUB_BMS_ADDRESS_2; SUB_BMS_COM sub_rs485_time_out_2; SUB_BMS_INFO sub_bms_info_2; uint8_t RS485_busy_2 = 0; uint8_t sub_bms_2_lt_state = SUB_BMS_INVALID_STATUS; uint8_t sub_bms_2_connect = 0; uint16_t bms_2_work_status = 0; uint8_t bms_2_test_define_error = 0; static int8_t Get_Check_Sum_2(uint16_t*value,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; } uint8_t SUB_BMS_2_DEC(void) { return sub_bms_2_connect; } void RS485_Communication_Time_Out_2(void) { if(sub_bms_info_2.rs485_connect) { sub_bms_2_lt_state = SUB_BMS_CONT_NO485; } else { sub_bms_2_lt_state = SUB_BMS_DISC_NO485; } if(sub_bms_info_2.rs485_time_out) return; memset(&sub_bms_info_2.packet_common,0x00,sizeof(sub_bms_info_2.packet_common)); memset(&sub_bms_info_2.bat_dev_info,0x00,sizeof(sub_bms_info_2.bat_dev_info)); memset(&sub_bms_info_2.bat_times,0x00,sizeof(sub_bms_info_2.bat_times)); memset(&sub_bms_info_2.cell_vol,0x00,sizeof(sub_bms_info_2.cell_vol)); memset(&sub_bms_info_2.temp_other,0x00,sizeof(sub_bms_info_2.temp_other)); memset(&sub_bms_info_2.sub_bms_cmd,0x00,sizeof(sub_bms_info_2.sub_bms_cmd)); sub_bms_info_2.rs485_time_out = 1; sub_bms_info_2.sub_bms_cmd.operate = OP_READ_INFO; // sub_bms_2_connect = 0; } static int8_t Handle_Sub_BMS_CMD_2(uint8_t *data) { static uint8_t send_times = 0; COMMAND_BODY *bms = (COMMAND_BODY *)data; int8_t bStatus; uint16_t count; SUB_BMS_INFO *temp_bms; do { if(bms->type != bms_addr || bms->dir != BMS_DIR || bms->bStatus == 0) break; memset(&sub_rs485_time_out_2,0x00,sizeof(sub_rs485_time_out_2)); g_event &= ~SUB_BMS_2_RS485_DISC_EVENT; temp_bms = &sub_bms_info_2; temp_bms->rs485_time_out = 0; // sub_bms_2_connect = 1; RS485_busy_2 = 0; if(sub_bms_info_2.rs485_connect) { sub_bms_2_lt_state = SUB_BMS_CONT_HV485; } else { sub_bms_2_lt_state = SUB_BMS_DISC_HV485; } //CRC count = bms->checksum; bms->checksum = 0; bStatus = Get_Check_Sum_2((void*)&bms->checksum,data,bms->size); if(1!=bStatus || count != bms->checksum) { break; } //handle frame count = sizeof(COMMAND_BODY); memcpy(&temp_bms->packet_common,&data[count],sizeof(temp_bms->packet_common)); count += sizeof(temp_bms->packet_common); //bang zi ce shi start //temp_bms ->packet_common.m_percent /= 2; //bang zi ce shi end if((temp_bms->packet_common.operate_result&0x01) != 0x01) break; switch((temp_bms->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(&temp_bms->bat_dev_info,&data[count],sizeof(temp_bms->bat_dev_info)); count += sizeof(temp_bms->bat_dev_info); break; case OP_ALARM_TIMES: memcpy(&temp_bms->bat_times,&data[count],sizeof(temp_bms->bat_times)); count += sizeof(temp_bms->bat_times); break; case OP_CELL_VOL: memcpy(&temp_bms->cell_vol,&data[count],sizeof(temp_bms->cell_vol)); count += sizeof(temp_bms->cell_vol); break; case OP_TEMP_OTHER: memcpy(&temp_bms->temp_other,&data[count],sizeof(temp_bms->temp_other)); count += sizeof(temp_bms->temp_other); 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(((temp_bms->packet_common.operate_result&0xF0)>>4) == temp_bms->sub_bms_cmd.operate) { memset(&temp_bms->sub_bms_cmd,0x00,sizeof(temp_bms->sub_bms_cmd)); ++send_times; if(send_times > 90) { temp_bms->sub_bms_cmd.operate = OP_ALARM_TIMES; send_times = 0; } else if(send_times > 60) { temp_bms->sub_bms_cmd.operate = OP_CELL_VOL; } else if(send_times > 30) { temp_bms->sub_bms_cmd.operate = OP_TEMP_OTHER; } else temp_bms->sub_bms_cmd.operate = OP_NONE; } return 1; }while(0); return 0; } static int8_t Send_Sub_BMS_CMD_2(void) { int8_t bStatus;// 默认需要回复 COMMAND_BODY*body = (COMMAND_BODY*)app_rs485_buf; uint8_t *buf = app_rs485_buf; SUB_BMS_INFO *temp_bms; temp_bms = &sub_bms_info_2; // 填帧头 body->size = sizeof(COMMAND_BODY); body->type = bms_addr; 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++] = temp_bms->sub_bms_cmd.operate; //对码 buf[body->size++] = cang_wei; 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(temp_bms->sub_bms_cmd.operate) { case OP_NONE: break; case OP_BOND: break; case OP_WRITE_SN: switch(temp_bms->sub_bms_cmd.param) { case 3: buf[body->size++] = (uint8_t)(temp_bms->sub_bms_cmd.param); break; case 4: buf[body->size++] = (uint8_t)(temp_bms->sub_bms_cmd.param); buf[body->size++] = (uint8_t)(update_bat.ub_total>>0); buf[body->size++] = (uint8_t)(update_bat.ub_total>>8); buf[body->size++] = 0; buf[body->size++] = 0; buf[body->size++] = (uint8_t)(update_bat.ub_sq>>0); buf[body->size++] = (uint8_t)(update_bat.ub_sq>>8); buf[body->size++] = 0; buf[body->size++] = 0; memcpy(&buf[body->size],update_bat.ub_data,update_bat.ub_len); body->size += update_bat.ub_len; 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)(temp_bms->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_2((void*)&body->checksum,(void*)body,body->size); if(1!=bStatus) { return 0; } Send_Data_2_RS485(buf,body->size); sub_rs485_time_out_2.set = 1; sub_rs485_time_out_2.count = 0; RS485_busy_2 = 1; return 1; } void Send_Sub_BMS_2_CMD(void) { if(RS485_busy_2) return; Send_Sub_BMS_CMD_2(); } void Check_Sub_BMS_2(void) { if(SUB_BMS_2_DEC()) { if(sub_bms_info_2.rs485_connect == 0) { sub_bms_info_2.rs485_connect = 1; sub_bms_info_2.sub_bms_cmd.operate = OP_READ_INFO; } } else { if(sub_bms_info_2.rs485_connect) { memset(&sub_bms_info_2,0x00,sizeof(sub_bms_info_2)); memset(&sub_rs485_time_out_2,0x00,sizeof(sub_rs485_time_out_2)); RS485_busy_2 = 0; //sub_bms_2_lt_state = SUB_BMS_DISC_NO485; sub_bms_info_2.sub_bms_cmd.operate = OP_READ_INFO; if(cb_operate_state == CB_BAT2) { //Power_On_Normal(0); } } } } int8_t Handle_RS485_2_Data(void) { uint16_t len = Get_RS485_2_Data(app_rs485_buf,sizeof(app_rs485_buf)); if(len != app_rs485_buf[0]) { if(memcmp(app_rs485_buf,"zhengjiceshi",12) == 0 && ht_mode == 0) { Writer_HT_Flash(1); __set_FAULTMASK(1); NVIC_SystemReset(); } //idra-test-start RS485_Print(0x23,app_rs485_buf,len); //idra-test-end return 0; } if((app_rs485_buf[0] > sizeof(COMMAND_BODY))) { if(!Handle_Sub_BMS_CMD_2(app_rs485_buf)) { //idra-test-start RS485_Print(0x23,app_rs485_buf,len); //idra-test-end return 0; } } return 1; } void Sub_BMS_2_Initial(void) { Usart2_Initial(); memset(&sub_rs485_time_out_2,0x00,sizeof(sub_rs485_time_out_2)); memset(&sub_bms_info_2,0x00,sizeof(sub_bms_info_2)); sub_bms_info_2.sub_bms_cmd.operate = OP_READ_INFO; } void Sub_BMS_2_lt_State(void) { switch(sub_bms_2_lt_state) { case SUB_BMS_INVALID_STATUS: break; case SUB_BMS_DISC_NO485: break; case SUB_BMS_DISC_HV485: break; case SUB_BMS_CONT_HV485: break; case SUB_BMS_CONT_NO485: break; } } uint8_t Is_Sub_BMS_2_Normal(void) { uint16_t work_sta = sub_bms_info_2.packet_common.work_status; work_sta &= ~ST_CHRG_CUR; work_sta &= ~ST_DISCHRG_CUR; work_sta &= ~ST_OVRDISCHRG_CUR; work_sta &= ~ST_SMALL_CURRENT_OVER; if(IS_CHARGER_ON()) //if(IS_CHARGE_IN()) { work_sta &= ~ST_OVRDISCHRG_VOL; work_sta &= ~ST_PDOWN; work_sta &= ~ST_UDR_TEMPE_DISCHRG; work_sta &= ~ST_OVR_TEMPE_DISCHRG; } else { work_sta &= ~ST_OVRCHRG_VOL; work_sta &= ~ST_OVR_TEMPE_CHRG; work_sta &= ~ST_UDR_TEMPE_CHRG; } if(update_bat.ub_bat == UPDATE_BAT_2) { return SHARK_BMS_EXIT_UPGRADE; } if(define_bms_2_error != D_BMS_ERROR_NO) { return SHARK_BMS_EXIT_ERROR; } if(Is_Soak()) { return SHARK_BMS_EXIT_SOAK; } if(work_sta) { bms_2_work_status = sub_bms_info_2.packet_common.work_status; return SHARK_BMS_EXIT_ERROR; } if(sub_bms_2_lt_state != SUB_BMS_CONT_HV485) { return SHARK_BMS_EXIT_485; } if(bms_2_test_define_error != 0) { return SHARK_BMS_EXIT_ERROR; } return SHARK_BMS_EXIT_SUCCESS; } int8_t Operate_Sub_BMS_2_CD(uint8_t on) { uint8_t cd_fet,rtn; uint16_t i,timeout = RS485_COM_TIMEOUT; sub_bms_info_2.sub_bms_cmd.operate = OP_OPEN_FET; switch(on) { case 1: cd_fet = 0x03; break; case 0: cd_fet = 0x00; break; case 2: cd_fet = 0x04; timeout = 2000; break; default: cd_fet = 0x00; break; } sub_bms_info_2.sub_bms_cmd.param = cd_fet; g_event &= ~RS485_2_RECEIVE_END_EVENT; Send_Sub_BMS_CMD_2(); cd_fet <<= 1; rtn = 0; for(i = 0; i < timeout/10;i++) { delay_1ms(10); if(g_event & RS485_2_RECEIVE_END_EVENT) { g_event &= ~RS485_2_RECEIVE_END_EVENT; Handle_RS485_2_Data(); if(on != 2) { if((sub_bms_info_2.packet_common.bms_status & cd_fet) == cd_fet) { rtn = 1; } } else { rtn = 1; } break; } } return rtn; } int8_t Update_Sub_BMS_2_Software(uint8_t step) { uint8_t rtn; uint16_t i,timeout = RS485_COM_UPDATE_TIMEOUT; switch(step) { case UPDATE_STEP_NO: return 0; case UPDATE_STEP_REQ: sub_bms_info_2.sub_bms_cmd.operate = OP_UPDATE_SOFTWARE_REQ; break; case UPDATE_STEP_DATA: sub_bms_info_2.sub_bms_cmd.operate = OP_UPDATE_SOFTWARE; break; default: return 0; } g_event &= ~RS485_2_RECEIVE_END_EVENT; Send_Sub_BMS_CMD_2(); rtn = 0; for(i = 0; i < timeout/10;i++) { delay_1ms(10); if(g_event & RS485_2_RECEIVE_END_EVENT) { g_event &= ~RS485_2_RECEIVE_END_EVENT; rtn = Handle_RS485_2_Data(); break; } } return rtn; } uint8_t Sub_BMS_2_COM_Finish(void) { return sub_bms_2_lt_state; }