#include "bms/bms_task.h" #include "app_init/app_init.h" #include "app_init/task_lock.h" #include "mylog/mylog.h" #include "publicdata/publicdata.h" #include "wdt_task/wdt_task.h" #define BMS_TASK_ID (TASK_ID_BmsComm) #define BMS_SLEEP_TIME_MS() (MY_GET_SLEEP_TIME(BMS_TASK_ID)) #define BMS_LOCK_INIT() (u8_task_lock_ctrl(BMS_TASK_ID, TASK_LOCK_OP_INIT)) #define BMS_LOCK_TAKE() (u8_task_lock_ctrl(BMS_TASK_ID, TASK_LOCK_OP_TAKE)) #define BMS_LOCK_GIVE() (u8_task_lock_ctrl(BMS_TASK_ID, TASK_LOCK_OP_GIVE)) #define BMS_FEED_DOG() (v_wdt_setFlag(BMS_TASK_ID)) #define BMS_LOG(fmt, ...) MYLOG_MSG(BMS_TASK_ID, (fmt), ##__VA_ARGS__) S_BMS_DATA s_bms_data; //BMS数据 /****************************************************************************系统集成改动部分-开始******************************************************/ /*线程初始化及线程锁操作函数*/ #if 1 /**************************************************** *功能说明: 获取遥信遥测变量控制锁 *参数说明: * 输入参数: void * 输出参数: U8_T 1成功或者0失败 *备注: ****************************************************/ static U8_T u8_bms_get_lock() { BMS_LOCK_TAKE(); return 1; } /**************************************************** *函数名称: void u8_free_yxyc_lock() *功能说明: 释放bms变量控制锁 *参数说明: * 输入参数: void * 输出参数: void *备注: ****************************************************/ static void u8_bms_free_lock() { BMS_LOCK_GIVE(); } #endif #if 1 //can数据收发接口 static U32_T u32_bms1_can_tx(CAN_DATA *pt_msg) { v_can_tx(BMS_CAN_ID_1, pt_msg); return 0; } static U32_T u32_bms1_can_rx(CAN_DATA *pt_msg) { U32_T u32_rcvCnt=0; u32_rcvCnt = u8_can_rx(BMS_CAN_ID_1,pt_msg); return u32_rcvCnt; } static U32_T u32_bms2_can_tx(CAN_DATA *pt_msg) { v_can_tx(BMS_CAN_ID_2, pt_msg); return 0; } static U32_T u32_bms2_can_rx(CAN_DATA *pt_msg) { U32_T u32_rcvCnt=0; u32_rcvCnt = u8_can_rx(BMS_CAN_ID_2,pt_msg); return u32_rcvCnt; } #endif #if 1 //周期计数控制 /**************************************************** *函数名称: U8_T u8_tim_ret(U8_T gunNo,E_BMS_TIM e_flag,U16_T cnt_tim) *功能说明: 获取是否到达对应定时时间 *参数说明: * 输入参数: U8_T gunNo,E_BMS_TIM e_flag,U16_T cnt_tim * 输出参数: void *最后修改时间: 20230228 *修改内容: 20230228 第一次创建子函数 ****************************************************/ static U8_T u8_tim_ret(U8_T gunNo,E_BMS_TIM e_flag,U16_T cnt_tim) { U8_T ret = 0; T_BMS_TIM *t_bms_tim = &s_bms_data.t_bms_tim[gunNo]; switch (e_flag) { case cnt50ms: if(t_bms_tim->cnt50ms >= cnt_tim) { t_bms_tim->cnt50ms = 0; ret = 1; } break; case cnt250ms: if(t_bms_tim->cnt250ms >= cnt_tim) { t_bms_tim->cnt250ms = 0; ret = 1; } break; case cnt500ms: if(t_bms_tim->cnt500ms >= cnt_tim) { t_bms_tim->cnt500ms = 0; ret = 1; } break; case cnt_global: if(t_bms_tim->u16_global_timerCnt >= cnt_tim) { t_bms_tim->u16_global_timerCnt = 0; ret = 1; } break; case cnt_bcl: if(t_bms_tim->u16_bcl_timerCnt >= cnt_tim) { t_bms_tim->u16_bcl_timerCnt = 0; ret = 1; } break; case cnt_bro_aa: if(t_bms_tim->u16_bro_timerCnt >= cnt_tim) { t_bms_tim->u16_bro_timerCnt = 0; ret = 1; } break; default: break; } return ret; } /**************************************************** *函数名称: U8_T u8_tim_reset(U8_T gunNo,E_BMS_TIM e_flag) *功能说明: 重置对应定时计数 *参数说明: * 输入参数: U8_T gunNo,E_BMS_TIM e_flag * 输出参数: void *最后修改时间: 20230228 *修改内容: 20230228 第一次创建子函数 ****************************************************/ static U8_T u8_tim_reset(U8_T gunNo,E_BMS_TIM e_flag) { T_BMS_TIM *t_bms_tim = &s_bms_data.t_bms_tim[gunNo]; switch (e_flag) { case cnt50ms: t_bms_tim->cnt50ms = 0; break; case cnt250ms: t_bms_tim->cnt250ms = 0; break; case cnt500ms: t_bms_tim->cnt500ms = 0; break; case cnt_global: t_bms_tim->u16_global_timerCnt = 0; break; case cnt_bcl: t_bms_tim->u16_bcl_timerCnt = 0; break; case cnt_bro_aa: t_bms_tim->u16_bro_timerCnt = 0; break; default: break; } return 1; } /**************************************************** *功能说明: bms 发送周期计数累加 10ms *参数说明: * 输入参数: * 输出参数: ****************************************************/ void v_bms_add_timer(void) { U8_T i; T_BMS_TIM *t_bms_tim = NULL; for(i=0;i<2;i++) { t_bms_tim = &s_bms_data.t_bms_tim[i]; //bms发送周期计数 if(t_bms_tim->cnt50ms < BMS_TIM_50MS) t_bms_tim->cnt50ms++; if(t_bms_tim->cnt250ms < BMS_TIM_250MS) t_bms_tim->cnt250ms++; if(t_bms_tim->cnt500ms < BMS_TIM_500MS) t_bms_tim->cnt500ms++; //bms超时周期计数 if(t_bms_tim->u16_global_timerCnt < BMS_TIM_60S) t_bms_tim->u16_global_timerCnt ++; if(t_bms_tim->u16_bcl_timerCnt < BMS_TIM_60S) //BSD报文超时复用该变量 所以扩展到10秒 t_bms_tim->u16_bcl_timerCnt ++; if(t_bms_tim->u16_bro_timerCnt < BMS_TIM_60S) t_bms_tim->u16_bro_timerCnt ++; } } #endif #if 1 //公共使用函数u /**************************************************** *函数名称: void v_set_rt_state(U8_T gunNo) *功能说明: 设置对外实时状态 *参数说明: * 输入参数: U8_T gunNo 枪号 * 输出参数: void *最后修改时间: 20230605 *修改内容: 20230605 第一次创建子函数 ****************************************************/ static void v_set_rt_state(U8_T gunNo,BMS_STATE_E state) { //外侧已经申请锁了 这里不需要再申请了 if(state == s_bms_data.s_bms_rt_data[gunNo].e_real_state) return; BMS_LOG("gun %d set rt state %d --> %d\n",gunNo,s_bms_data.s_bms_rt_data[gunNo].e_real_state,state); s_bms_data.s_bms_rt_data[gunNo].e_real_state = state; } static void v_set_bms_stop_info(U8_T gunNo ,E_BMS_STOP_INFO e_stop_reason) { S_BMS_RT_DATA *pt_bms = &s_bms_data.s_bms_rt_data[gunNo]; if(pt_bms->e_stop_info == 0) pt_bms->e_stop_info = e_stop_reason; //充电停止原因 v_set_rt_state(gunNo, BMS_STATE_STOP); //对外状态 停止 } /**************************************************** *功能说明: 设置BMS控制流程状态 *参数说明: * 输入参数: U8_T gunNo 枪号 * 输出参数: void *最后修改时间: 20230605 *修改内容: 20230605 第一次创建子函数 ****************************************************/ static void v_set_flow_state(U8_T gunNo,GB_BMS_STATE_E state) { if(state == s_bms_data.s_bms_rt_data[gunNo].e_state) return; BMS_LOG("gun %d set flow state %d --> %d\n",gunNo,s_bms_data.s_bms_rt_data[gunNo].e_state,state); u8_bms_get_lock();//申请锁 s_bms_data.s_bms_rt_data[gunNo].e_state = state; u8_bms_free_lock();//释放锁 } #endif #if 1 //超时判断 /**************************************************** *功能说明: bms超时处理 *参数说明: * 输入参数: U8_T type_flag类型 U8_T gunNo 枪号 reconn_flag 重连标志 0不重连 1重连 timeout_flag超时报文标志 * 输出参数: U8_T 0赋值失败 1赋值成功 ****************************************************/ static U8_T u8_bms_timeout(U8_T type_flag,U8_T gunNo, U8_T reconn_flag , U8_T timeout_flag) { U8_T ret = 0; S_BMS_RT_DATA *pt_bms = &s_bms_data.s_bms_rt_data[gunNo]; if((pt_bms->u16_timeout_flag & timeout_flag) != 0) //已经存在 则不动作 return ret; if ((s_bms_data.u8_gun_type[gunNo] == 0)) pt_bms->u8_reconn_flag = 0; //欧标:通信超时 不重连 else pt_bms->u8_reconn_flag = reconn_flag; //国标:重新进行握手连接 pt_bms->u16_timeout_flag |= timeout_flag; //CEM if(timeout_flag == GB_BRM_TIMEOUT_FLAG){ if(pt_bms->e_stop_info == 0) pt_bms->e_stop_info = E_BMS_STOP_15011; //充电停止原因 } else if(timeout_flag == GB_BCP_TIMEOUT_FLAG){ if(pt_bms->e_stop_info == 0) pt_bms->e_stop_info = E_BMS_STOP_15003; //充电停止原因 } else if(timeout_flag == GB_BRO_TIMEOUT_FLAG){ if(pt_bms->e_stop_info == 0) { if(type_flag == 0x00) pt_bms->e_stop_info = E_BMS_STOP_15009; //BRO00 超时 充电停止原因 else if(type_flag == 0x01) pt_bms->e_stop_info = E_BMS_STOP_15010; //BROAA超时 充电停止原因 else if(type_flag == 0x02) pt_bms->e_stop_info = E_BMS_STOP_15004; //充电停止原因 } } else if(timeout_flag == GB_BCS_TIMEOUT_FLAG){ if(pt_bms->e_stop_info == 0) pt_bms->e_stop_info = E_BMS_STOP_15005; //充电停止原因 } else if(timeout_flag == GB_BCL_TIMEOUT_FLAG){ if(pt_bms->e_stop_info == 0) pt_bms->e_stop_info = E_BMS_STOP_15006; //充电停止原因 } else if(timeout_flag == GB_BST_TIMEOUT_FLAG){ if(pt_bms->e_stop_info == 0) pt_bms->e_stop_info = E_BMS_STOP_15007; //充电停止原因 } else if(timeout_flag == GB_BSD_TIMEOUT_FLAG){ if(pt_bms->e_stop_info == 0) pt_bms->e_stop_info = E_BMS_STOP_15011; //充电停止原因 } v_set_rt_state(gunNo, BMS_STATE_TIMEOUT); //bms状态 = 超时, flow任务检测到后停止此次充电任务 v_set_flow_state(gunNo,GB_BMS_TX_CEM); //发送BEM ret = 1; return ret ; } /**************************************************** *功能说明: bms超时处理 bhm测试 *参数说明: * 输入参数: U8_T gunNo 枪号 * 输出参数: void *最后修改时间: 20230210 *修改内容: 20230210 第一次创建子函数 ****************************************************/ static void v_bms_timeout_bhm(U8_T gunNo) { S_BMS_RT_DATA *rt_bms = &s_bms_data.s_bms_rt_data[gunNo]; v_set_rt_state(gunNo, BMS_STATE_HANDSHAKE_FAIL); BMS_LOG("BMS HS TO\n"); //清除底层的多包状态 v_sae1393_clear_multi_pacet(&s_bms_data.s_gb_bms_can[gunNo].pt_dll); rt_bms->e_bms_standard = BMS_2011; } /**************************************************** *功能说明: bms超时处理 brm超时 *参数说明: * 输入参数: U8_T gunNo 枪号 * 输出参数: void *最后修改时间: 20230228 *修改内容: 20230228 第一次创建子函数 ****************************************************/ static void v_bms_timeout_brm(U8_T gunNo) { U8_T ret ; //山东省电动优化:取消重连机制 if(u16_bms_get_sys_para(0,E_BMS_GET_PARA_GB_EN) == 1) //国标 ret = u8_bms_timeout(0,gunNo,1,GB_BRM_TIMEOUT_FLAG); else ret = u8_bms_timeout(0,gunNo,0,GB_BRM_TIMEOUT_FLAG); //第一次赋值 if(ret == 1) { BMS_LOG("BMS HS BRM TO\n"); } } /**************************************************** *功能说明: bms超时处理 bcp超时 *参数说明: * 输入参数: U8_T gunNo 枪号 * 输出参数: void *最后修改时间: 20230228 *修改内容: 20230228 第一次创建子函数 ****************************************************/ static void v_bms_timeout_bcp(U8_T gunNo) { U8_T ret ; ret = u8_bms_timeout(0,gunNo,1,GB_BCP_TIMEOUT_FLAG); //第一次赋值 if(ret == 1) { BMS_LOG("BMS BCP TO\n"); } } /**************************************************** *功能说明: bms超时处理 bro超时 *参数说明: * 输入参数: U8_T gunNo 枪号 * 输出参数: void *最后修改时间: 20230228 *修改内容: 20230228 第一次创建子函数 ****************************************************/ static void v_bms_timeout_bro(U8_T gunNo,U8_T u8_flag) { U8_T ret ; ret = u8_bms_timeout(u8_flag,gunNo,1,GB_BRO_TIMEOUT_FLAG); //第一次赋值 if(ret == 1) { if(u8_flag == 0x00) BMS_LOG("BMS BRO 0x00 RX TO(5s)\n"); else if(u8_flag == 0x01) BMS_LOG("BMS BRO 0xAA RX TO(60s)\n"); else if(u8_flag == 0x02) BMS_LOG("BMS BRO RX TO(5s)\n"); } } /**************************************************** *功能说明: bms超时处理 bcs超时 *参数说明: * 输入参数: U8_T gunNo 枪号 * 输出参数: void *最后修改时间: 20230228 *修改内容: 20230228 第一次创建子函数 ****************************************************/ static void v_bms_timeout_bcs(U8_T gunNo,U8_T u8_flag) { U8_T ret ; ret = u8_bms_timeout(0,gunNo,1,GB_BCS_TIMEOUT_FLAG); //第一次赋值 if(ret == 1) { if(u8_flag == 00) BMS_LOG("BMS BCS TO\n"); else BMS_LOG("BMS CHG BCS TO\n"); } } /**************************************************** *功能说明: bms超时处理 bcl超时 *参数说明: * 输入参数: U8_T gunNo 枪号 * 输出参数: void *最后修改时间: 20230228 *修改内容: 20230228 第一次创建子函数 ****************************************************/ static void v_bms_timeout_bcl(U8_T gunNo,U8_T u8_flag) { U8_T ret ; ret = u8_bms_timeout(0,gunNo,1,GB_BCL_TIMEOUT_FLAG); //第一次赋值 if(ret == 1) { if(u8_flag == 00) { BMS_LOG("BMS BCL TO\n"); } else BMS_LOG("BMS CHG BCL TO\n"); } } /**************************************************** *功能说明: bms超时处理 bst超时 *参数说明: * 输入参数: U8_T gunNo 枪号 * 输出参数: void *最后修改时间: 20230228 *修改内容: 20230228 第一次创建子函数 ****************************************************/ static void v_bms_timeout_bst(U8_T gunNo) { U8_T ret ; ret = u8_bms_timeout(0,gunNo,0,GB_BST_TIMEOUT_FLAG); //第一次赋值 if(ret == 1) { BMS_LOG("BMS END BST RX TO\n"); } } /**************************************************** *功能说明: bms超时处理 bsd超时 *参数说明: * 输入参数: U8_T gunNo 枪号 * 输出参数: void *最后修改时间: 20230228 *修改内容: 20230228 第一次创建子函数 ****************************************************/ static void v_bms_timeout_bsd(U8_T gunNo,U8_T u8_flag) { U8_T ret ; ret = u8_bms_timeout(0,gunNo,0,GB_BSD_TIMEOUT_FLAG); //第一次赋值 if(ret == 1) { BMS_LOG("BMS END BSD RX TO\n"); } } //超时处理 void v_bms_timeout_handle(U8_T gunNo) { S_BMS_RT_DATA *pt_bms; S_BMS_RT_DATA *gb_data; // U16_T u16_OTcnt_5s_BHM = 500; //超时计数基准 5s=10ms*500 // U16_T u16_OTcnt_5s_BRM = 3000; //超时计数基准 5s=10ms*500 国标5s,省电动优化为30s,取消重连机制 // U16_T u16_OTcnt_5s_BCP = 520; //超时计数基准 5s=10ms*500 // U16_T u16_OTcnt_5s_BRO = 500; //超时计数基准 5s=10ms*500 // U16_T u16_OTcnt_60s_BRO_0xAA = 6000; //超时计数基准 60s=10ms*6000 // U16_T u16_OTcnt_5s_BCS_1 = 520; //超时计数基准 5s=10ms*500 // U16_T u16_OTcnt_1s_BCL_1 = 120; //超时计数基准 1s=10ms*100 // U16_T u16_OTcnt_5s_BCS_2 = 500; //超时计数基准 5s=10ms*500 // U16_T u16_OTcnt_1s_BCL_2 = 100; //超时计数基准 1s=10ms*100 // U16_T u16_OTcnt_5s_BST = 520; //超时计数基准 5s=10ms*500 -- 充电结束阶段的暂不延长 // U16_T u16_OTcnt_10s_BSD = 1000; //超时计数基准 10s=10ms*1000 U8_T brm_outTime_k = 1; //BRM报文接收超时判定系数 1为不延长,5秒 6为30秒 U8_T bhm_outTime_k = 1; //BhM报文接收超时判定系数 1为不延长,5秒 2为10秒 U8_T bcl_outTime_k = 1; //BCL报文接收超时判定系数 1为不延长,1秒 2为2秒 U8_T bcs_outTime_k = 1; //BCS报文接收超时判定系数 1为不延长,5秒 2为10秒 if(u16_bms_get_sys_para(0,E_BMS_GET_PARA_GB_EN) == 0) { //非国标下 BRM超时判定时间延长至30秒 brm_outTime_k = 6; bhm_outTime_k = 2; bcl_outTime_k = 2; bcs_outTime_k = 2; //BMS_LOG("非国标,超时时间延长\n"); } pt_bms = &(s_bms_data.s_bms_rt_data[gunNo]); gb_data = &(s_bms_data.s_bms_rt_data[gunNo]); if(pt_bms->u8_reconn_flag == 1) //如果正在进行重连,则不再做超时判定 return; switch(gb_data->e_state) { case GB_BMS_STOP: //停止充电 { break; } case GB_BMS_HANDSHAKE_TX_CHM: //握手阶段,发送充电机握手CHM,等待接收车辆握手BHM - 自辅源闭合起经过5s if(u8_tim_ret(gunNo,cnt_global,BMS_TIM_5S*bhm_outTime_k) == 0) break; #if CAN_PLC_FLAG //欧标 CAN转PLC使能 if (!(s_bms_data.u8_gun_type[gunNo] == 0)) v_bms_timeout_bhm(gunNo); #endif break; case GB_BMS_HANDSHAKE_TX_CRM_00: //握手阶段,发送CRM_00,等待接收BMS和车辆辨识报文BRM #if CAN_PLC_FLAG //欧标 CAN转PLC使能 if ((s_bms_data.u8_gun_type[gunNo] == 0)) { if(u8_tim_ret(gunNo,cnt_global,BMS_TIM_10S*brm_outTime_k) == 0) break; } else #endif { if(u8_tim_ret(gunNo,cnt_global,BMS_TIM_5S*brm_outTime_k) == 0) break; } v_bms_timeout_brm(gunNo); break; case GB_BMS_HANDSHAKE_TX_CRM_AA: //握手阶段,己收到BMS和车辆辨识报文BRM,发送CRM_AA,等待接收电池充电参数报文BCP #if CAN_PLC_FLAG //欧标 CAN转PLC使能 if ((s_bms_data.u8_gun_type[gunNo] == 0)) { if(u8_tim_ret(gunNo,cnt_global,BMS_TIM_60S) == 0) break; } else #endif { if(u8_tim_ret(gunNo,cnt_global,BMS_TIM_5S) == 0) break; } v_bms_timeout_bcp(gunNo); break; case GB_BMS_CFG_TX_CTS_CML: //充电参数配置阶段,己收到电池充电参数报文BCP,发送CTS和CML,等待接收BMS完成充电准备报文BRO if(u8_tim_ret(gunNo,cnt_global,BMS_TIM_5S) == 0) break; v_bms_timeout_bro(gunNo,0x00); break; case GB_BMS_CFG_RX_BRO_AA: //充电参数配置阶段,己收到电池充电参数报文BRO_00,发送CTS和CML,等待接收BMS完成充电准备报文BRO_AA if(u8_tim_ret(gunNo,cnt_bro_aa,BMS_TIM_60S) == 1) { v_bms_timeout_bro(gunNo,0x01); } if(u8_tim_ret(gunNo,cnt_global,BMS_TIM_5S) == 1) { v_bms_timeout_bro(gunNo,0x02); } break; case GB_BMS_CFG_TX_CRO_00: //充电参数配置阶段,接收BMS完成充电准备报文BRO_AA,发送充电机充电准备完成报文CRO_00 if(u8_tim_ret(gunNo,cnt_global,BMS_TIM_5S) == 1) { v_bms_timeout_bro(gunNo,0x01); } break; case GB_BMS_CFG_TX_CRO_AA: //充电参数配置阶段,接收BMS完成充电准备报文BRO,发送充电机充电准备完成报文CRO_AA,等待接收电池总充电状态BCS/BCL #if 1 //if((t_gb_bms_data.u8_bcs_rx_flag == 1) || (t_gb_bms_data.u8_bcl_rx_flag == 1)) { if(u8_tim_ret(gunNo,cnt_global,BMS_TIM_5S*bcs_outTime_k) == 1) { v_bms_timeout_bcs(gunNo,0x00); } if(u8_tim_ret(gunNo,cnt_bcl,BMS_TIM_1S*bcl_outTime_k) == 1) { v_bms_timeout_bcl(gunNo,0x00); } } #endif break; case GB_BMS_CHARGE_STAGE: //充电阶段,接收报文BCS和BCL // if(g_t_share_data.t_sys_cfg.u8_GBenable == 0) // break; #if 1 if(u8_tim_ret(gunNo,cnt_global,BMS_TIM_5S*bcs_outTime_k) == 1) { v_bms_timeout_bcs(gunNo,0x01); } if(u8_tim_ret(gunNo,cnt_bcl,BMS_TIM_1S*bcl_outTime_k) == 1) { v_bms_timeout_bcl(gunNo,0x01); } #endif break; case GB_BMS_CHARGE_TX_CST: //充电结束阶段,发送充电机中止充电报文CST,等待接收BMS中止充电报文BST if(pt_bms->u8_bms_rx_flag[9] == 0) //bst未接收到 { if(u8_tim_ret(gunNo,cnt_global,BMS_TIM_5S) == 1) { v_bms_timeout_bst(gunNo); } } if(pt_bms->u8_bms_rx_flag[10] == 0) //BSD未收到 { if(u8_tim_ret(gunNo,cnt_bcl,BMS_TIM_10S) == 1) v_bms_timeout_bsd(gunNo,0); //-- bms协议一致性测试使用 } break; case GB_BMS_FINISH_RX_BSD: //充电结束阶段,已收到BSD,发送CSD if(pt_bms->u8_bms_rx_flag[10] == 0) //BSD未收到 { if(u8_tim_ret(gunNo,cnt_bcl,BMS_TIM_10S) == 1) v_bms_timeout_bsd(gunNo,0); //-- bms协议一致性测试使用 } break; default: break; } } #endif #if 1 //接收相关 /**************************************************** *函数名称: v_bms_err_data() *功能说明: 判断电流数据是否在有效范围内 *参数说明: * 输入参数: U8_T gunNo * 输出参数: ****************************************************/ void v_bms_err_data(U8_T gunNo ) { S_BMS_RT_DATA *pt_bms = &s_bms_data.s_bms_rt_data[gunNo]; if(pt_bms->t_bcp_data.f32_batt_charge_max_curr < 0.0f && pt_bms->t_bcp_data.f32_batt_charge_max_curr > 2000.0f) //如果电流不在0-2000A范围内则停止充电 { BMS_LOG("BMS Imax=%.2f\n", pt_bms->t_bcp_data.f32_batt_charge_max_curr); pt_bms->e_state = GB_BMS_STOP; v_set_rt_state(gunNo, BMS_STATE_ERR); //bms状态转数据异常 } } /**************************************************** *功能说明: BHM数据接收解析函数 *参数说明: * 输入参数: U8_T gunNo 枪号 ,CAN_DATA_T *pt_msg 接收can数据 * 输出参数: void *最后修改时间: 20230210 *修改内容: 20230210 第一次创建子函数 ****************************************************/ static void v_bms_bhm_rx(U8_T gunNo,CAN_DATA_T *pt_msg) { S_BMS_RT_DATA *pt_bms = &s_bms_data.s_bms_rt_data[gunNo]; F32_T f32_data; #if CAN_PLC_FLAG //欧标 CAN转PLC使能 if ((s_bms_data.u8_gun_type[gunNo] == 0)) { /* 1.1 2.8 CR_Plc_EvPermissibleMaxVolt Max permissible voltage (not supported at this stage in CCS) 0.1 0 0~6553.5 V 不支持 不判断 车最高允许充电电压 最高允许充电总电压 3.1 3.8 CR_Plc_Aagvalue Average Attenuation Gain, at start: 00  end of SLAC:≠ 0 1 0 0 ~ 255 添加项 判断 信号衰减值 开始时的平均衰减增益:00 ;SLAC计算结果:≠ 0 4.1 4.2 CR_Plc_CpStatus See reference 1 0 0 ~ 7 添加项 判断 CP状态 0:12v未插枪;1:9v已插枪;2:9v占空比状态;3:6v占空比准备充电状态 4.5 4.6 CR_Plc_CommStart 0: PLC_Comm did not start; 1: Start PLC_Comm 1 0 0 ~ 7 添加项 判断 通信启动 0:通信未启动;1:启动PLC通信 5.1 6.8 SECC固件版本编译日期-年 "例 5.1~8.8( 22 20 01 06 ) 例 22 20;2022年 例 01 ;1月 例 06 ;6日" 添加项 不判断 7.1 7.8 SECC固件版本编译日期-月 添加项 不判断 8.1 8.8 SECC固件版本编译日期-日 添加项 不判断 */ if ((pt_msg->u16_len >= 2) /*&& (pt_msg->u8_pri == 6)*/) //收到BHM { //最大允许充电电压 f32_data = GetU16Data(pt_msg->u8_data[1],pt_msg->u8_data[0]) / 10.0; #if CAN_PLC_FLAG pt_bms->t_bhm_data.u8_CR_Plc_Aagvalue = pt_msg->u8_data[2]; // 信号衰减值 pt_bms->t_bhm_data.u8_CR_Plc_CpStatus = (pt_msg->u8_data[3]&0x03); // CP状态 0:12v未插枪;1:9v已插枪;2:9v占空比状态;3:6v占空比准备充电状态 pt_bms->t_bhm_data.u8_CR_Plc_CommStart= (pt_msg->u8_data[3]>>4)&0x03; // 通信启动 0:通信未启动;1:启动PLC通信 #define BMS_GUNLINK_KEEP_EN (1) //枪连接防抖使能 #if BMS_GUNLINK_KEEP_EN #define BMS_GUNLINK_KEEP_TIME (3) //枪连接防抖次数 static U8_T u8_preGunLink[GUN_MAX_CNT] = {0},u8_keepTimes[GUN_MAX_CNT] = {0}; U8_T u8_gunLink = (pt_bms->t_bhm_data.u8_CR_Plc_CpStatus == 0)?0:1; #endif /* CAN_PLC_FLAG */ if(u8_gunLink != u8_preGunLink[gunNo]) { if(++u8_keepTimes[gunNo] >= BMS_GUNLINK_KEEP_TIME) //连续3次变位 则更新 { u8_preGunLink[gunNo] = u8_gunLink; } } else { u8_keepTimes[gunNo] = 0; } s_bms_data.u8_gun_linkState[gunNo] = u8_preGunLink[gunNo]; #else if(pt_bms->t_bhm_data.u8_CR_Plc_CpStatus == 0) s_bms_data.u8_gun_linkState[gunNo] = 0; else s_bms_data.u8_gun_linkState[gunNo] = 1; #endif snprintf((char*)pt_bms->t_bhm_data.u8_SECC_ver, sizeof(pt_bms->t_bhm_data.u8_SECC_ver), "%02d%02d-%02d-%02d", bcd_to_dec(pt_msg->u8_data[5]), bcd_to_dec(pt_msg->u8_data[4]), bcd_to_dec(pt_msg->u8_data[6]), bcd_to_dec(pt_msg->u8_data[7])); //SECC固件版本编译日期-年月日 u8_tim_reset(gunNo,cnt_global); //清空计时 pt_bms->e_bms_standard = BMS_PLC; } } else /* 国标 */ #endif { if(pt_bms->e_state != GB_BMS_HANDSHAKE_TX_CHM) //只有在发送chm阶段接收 return; if ((pt_msg->u16_len >= 2) /*&& (pt_msg->u8_pri == 6)*/) //收到BHM { //最大允许充电电压 f32_data = (((U16_T)(pt_msg->u8_data[1])<<8) | pt_msg->u8_data[0]) / 10.0; //BHM最高允许充电电压 低于200 认定为错误数据 if(f32_data < 200) return; pt_bms->t_bhm_data.f32_max_charge_volt = f32_data; if(pt_bms->u8_bms_rx_flag[0] == 0) { pt_bms->u8_bms_rx_flag[0] = 1; //bms报文接收标志 BMS_LOG("BHM Vmax=%.2f\n", pt_bms->t_bhm_data.f32_max_charge_volt); } u8_tim_reset(gunNo,cnt_global); //清空计时 pt_bms->e_bms_standard = BMS_2015; if(pt_bms->e_state == GB_BMS_HANDSHAKE_TX_CHM) { //bms实时数据-更新状态-握手启动成功 v_set_rt_state(gunNo, BMS_STATE_HANDSHAKE_START_OK); //bms状态 } } } } /**************************************************** *功能说明: BRM数据接收解析函数 *参数说明: * 输入参数: U8_T gunNo 枪号,CAN_DATA_T *pt_msg 接收can数据 * 输出参数: void *最后修改时间: 20230210 *修改内容: 20230210 第一次创建子函数 ****************************************************/ static void v_bms_brm_rx(U8_T gunNo,CAN_DATA_T *pt_msg) { U8_T i; S_BMS_RT_DATA *pt_bms = &s_bms_data.s_bms_rt_data[gunNo]; if(pt_bms->e_state != GB_BMS_HANDSHAKE_TX_CRM_00) //只在此阶段阶段接收 return; #if CAN_PLC_FLAG //欧标 CAN转PLC使能 if ((s_bms_data.u8_gun_type[gunNo] == 0)) { /* 1.1 1.8 CR_Plc_VersionMinor GBT-1, PLC-1 1 0~1 1->1 版本 版本,国标:1;PLC:1 2.1 2.8 无含义 填:00 3.1 8.8 EVCC MAC 地址 */ if (pt_msg->u16_len >= 8) { pt_bms->u8_bms_rx_flag[1] = 1; //bms报文接收标志 pt_bms->t_brm_data.u8_batt_type = pt_msg->u8_data[3]; pt_bms->t_brm_data.f32_batt_rated_c10 = (((U16_T)(pt_msg->u8_data[5])<<8) | pt_msg->u8_data[4]) / 10.0; pt_bms->t_brm_data.f32_batt_rated_volt = (((U16_T)(pt_msg->u8_data[7])<<8) | pt_msg->u8_data[6]) / 10.0; //暂不做内容接收 u8_tim_reset(gunNo,cnt_global); //清空计时 if(s_bms_data.s_bms_rt_data[gunNo].e_state == GB_BMS_HANDSHAKE_TX_CRM_00) s_bms_data.s_bms_rt_data[gunNo].e_state = GB_BMS_HANDSHAKE_TX_CRM_AA; //状态转4 } } else #endif { if ((pt_msg->u16_len >= 41) /*&& (pt_msg->u8_pri == 7)*/) { pt_bms->u8_bms_rx_flag[1] = 1; //bms报文接收标志 pt_bms->t_brm_data.u32_bms_version = ((U32_T)(pt_msg->u8_data[2])<<16) | ((U32_T)(pt_msg->u8_data[1])<<8) | pt_msg->u8_data[0]; pt_bms->t_brm_data.u8_batt_type = pt_msg->u8_data[3]; pt_bms->t_brm_data.f32_batt_rated_c10 = (((U16_T)(pt_msg->u8_data[5])<<8) | pt_msg->u8_data[4]) / 10.0; pt_bms->t_brm_data.f32_batt_rated_volt = (((U16_T)(pt_msg->u8_data[7])<<8) | pt_msg->u8_data[6]) / 10.0; memcpy((char *)(pt_bms->t_brm_data.u8_batt_vender), (char *)(&(pt_msg->u8_data[8])), 4); pt_bms->t_brm_data.u32_batt_serial = ((U32_T)(pt_msg->u8_data[15])<<24) | ((U32_T)(pt_msg->u8_data[14])<<16) | ((U32_T)(pt_msg->u8_data[13])<<8) | pt_msg->u8_data[12]; pt_bms->t_brm_data.u8_batt_make[0] = pt_msg->u8_data[16]; pt_bms->t_brm_data.u8_batt_make[1] = pt_msg->u8_data[17]; pt_bms->t_brm_data.u8_batt_make[2] = pt_msg->u8_data[18]; pt_bms->t_brm_data.u32_batt_charge_times = ((U32_T)(pt_msg->u8_data[21])<<16) | ((U32_T)(pt_msg->u8_data[20])<<8) | pt_msg->u8_data[19]; pt_bms->t_brm_data.u8_batt_belong = pt_msg->u8_data[22]; pt_bms->t_brm_data.u8_Bms_edition = pt_msg->u8_data[23]; //增加充电机通信协议版本解读(兼容2015+团标) memcpy((char *)(pt_bms->t_brm_data.u8_car_vin), (char *)(&(pt_msg->u8_data[24])), 17); // 车架号校验 每一位必须为字母或数字 否则置为全0 for (i = 0; i < 17; i ++) { if(((pt_bms->t_brm_data.u8_car_vin[i] >= '0') && (pt_bms->t_brm_data.u8_car_vin[i] <= '9')) || ((pt_bms->t_brm_data.u8_car_vin[i] >= 'A') && (pt_bms->t_brm_data.u8_car_vin[i] <= 'Z')) || ((pt_bms->t_brm_data.u8_car_vin[i] >= 'a') && (pt_bms->t_brm_data.u8_car_vin[i] <= 'z'))) { ;//数据有效 } else { memset(&pt_bms->t_brm_data.u8_car_vin[0], 0x30, 17);//如果收到的VIN无效,赋值为0 break; } } memcpy((char *)(pt_bms->t_brm_data.u8_bms_soft_version),(char *)(&(pt_msg->u8_data[41])),8); if (pt_bms->e_bms_standard == BMS_2011) { if (pt_bms->t_brm_data.u32_bms_version == 0x00000101) pt_bms->e_bms_standard = BMS_2015; else pt_bms->e_bms_standard = BMS_2011; } u8_tim_reset(gunNo,cnt_global); //清空计时 if(s_bms_data.s_bms_rt_data[gunNo].e_state == GB_BMS_HANDSHAKE_TX_CRM_00) s_bms_data.s_bms_rt_data[gunNo].e_state = GB_BMS_HANDSHAKE_TX_CRM_AA; //状态转4 // BMS_LOG("BMS版本号:%d\n", pt_bms->u32_bms_version); // BMS_LOG("电池类型:%x\n", pt_bms->u8_batt_type); // BMS_LOG("整车动力蓄电池系统额定容量:%d\n", (U32_T)(pt_bms->f32_batt_rated_c10*10)); // BMS_LOG("整车动力蓄电池系统额定总电压:%f\n", (U32_T)(pt_bms->f32_batt_rated_volt*10)); BMS_LOG("vin_len=%d, VIN=%s\n",strlen((const char*)(pt_bms->t_brm_data.u8_car_vin)), pt_bms->t_brm_data.u8_car_vin); } } } /**************************************************** *功能说明: BCP数据接收解析函数 *参数说明: * 输入参数: U8_T gunNo 枪号,CAN_DATA_T *pt_msg 接收can数据 * 输出参数: void *最后修改时间: 20230210 *修改内容: 20230210 第一次创建子函数 ****************************************************/ static void v_bms_bcp_rx(U8_T gunNo,CAN_DATA_T *pt_msg) { S_BMS_RT_DATA *pt_bms = &s_bms_data.s_bms_rt_data[gunNo]; if(pt_bms->e_state != GB_BMS_HANDSHAKE_TX_CRM_AA) //只在此阶段阶段接收 return; #if CAN_PLC_FLAG //欧标 CAN转PLC使能 if ((s_bms_data.u8_gun_type[gunNo] == 0)) { /* 1.1 2.8 CR_Plc_MaxVoltSingleBattery 0 (no value with CCS) 0.01 0 0~24 V 单体电池最大电压 默认0x00 3.1 4.7 CR_Plc_EvmaxCurrent EV Maximum permissible charging current 0.1 -400 A 最高容许充电电流 车辆最高容许充电电流 4.8 4.8 CR_Plc_EvmaxCurrent EV Maximum permissible charging current 1 0 0~1 A 最高容许充电电流大于400A标志位 "0:小于400A电流计算:400A - 3.1~4.7的电流值; 1:大于400A电流计算:3.1~4.7的电流值 + 400A" 5.1 6.8 CR_Plc_EvNormialEnergy 0 (no value with CCS) 0.1 0 0~1000 KWh 动力蓄电池标称总能量 默认0x00 7.1 8.8 CR_Plc_EvmaxVolt Total max permissible charging voltage 0.1 0 V 最高容许充电总电压 车辆最高容许充电总电压(绝缘检测电压) 9.1 9.8 CR_Plc_EvAvailableTemp 0 (no value with CCS) Maximum permissible temperature 1 -50 负50至200 ℃ 总高容许温度 默认0x00 10.1 11.8 CR_Plc_EvRessSOC Status Of Charge 0.1 0 0~100 % 整车动力蓄电池荷电状态电量 默认0x00 12.1 13.8 CR_Plc_EvCurrentVolt 0 (no value with CCS) 0.1 0 V 整车动力蓄电池当前电池电压 默认0x00 14.1 14.4 CR_Plc_EvTransferType Supported Energy Type (default 3, see appendix) 1 0 电动车传输协议能量类型 默认0x03,支持的能量传输类型 */ if ((pt_msg->u16_len >= 13) /*&& (pt_msg->u8_pri == 7)*/) { pt_bms->u8_bms_rx_flag[2] = 1; //bms报文接收标志 pt_bms->t_bcp_data.f32_cell_charge_max_volt = (((U16_T)(pt_msg->u8_data[1])<<8) | pt_msg->u8_data[0]) / 100.0; if((pt_msg->u8_data[3]&0x80) == 0x80) //最高容许充电电流大于400A标志位 { pt_bms->t_bcp_data.f32_batt_charge_max_curr = -(((((U16_T)(pt_msg->u8_data[3])<<8) | pt_msg->u8_data[2]) & 0x7FFF) / 10.0 + 400); }else pt_bms->t_bcp_data.f32_batt_charge_max_curr = -((((U16_T)(pt_msg->u8_data[3])<<8) | pt_msg->u8_data[2]) / 10.0 - 400); pt_bms->t_bcp_data.f32_batt_rated_enery = (((U16_T)(pt_msg->u8_data[5])<<8) | pt_msg->u8_data[4]) / 10.0; pt_bms->t_bcp_data.f32_batt_charge_max_volt = (((U16_T)(pt_msg->u8_data[7])<<8) | pt_msg->u8_data[6]) / 10.0; pt_bms->t_bcp_data.s16_batt_allow_max_temp = (S16_T)(pt_msg->u8_data[8]) - 50; pt_bms->t_bcp_data.f32_batt_start_soc = (((U16_T)(pt_msg->u8_data[10])<<8) | pt_msg->u8_data[9]) / 10.0; pt_bms->t_bcp_data.f32_batt_volt = (((U16_T)(pt_msg->u8_data[12])<<8) | pt_msg->u8_data[11]) / 10.0; pt_bms->t_bcp_data.u8_CR_Plc_EvTransferType = pt_msg->u8_data[13]; //电动车传输协议能量类型 默认0x03,支持的能量传输类型 // BMS_LOG("单体动力蓄电池最高允许充电电压=%d\n", (U32_T)(pt_bms->f32_cell_charge_max_volt*100)); // BMS_LOG("最高允许充电电流=%d\n", (U32_T)(pt_bms->f32_batt_charge_max_curr*10)); // BMS_LOG("动力蓄电池标称总能量=%d\n", (U32_T)(pt_bms->f32_batt_rated_enery*10)); // BMS_LOG("最高允许充电电压=%d\n", (U32_T)(pt_bms->f32_batt_charge_max_volt_judge*10)); // BMS_LOG("最高允许温度=%d\n", (U32_T)(pt_bms->s16_batt_allow_max_temp*10)); // BMS_LOG("整车动力蓄电池荷电状态=%d\n", (U32_T)(pt_bms->f32_batt_start_soc*10)); BMS_LOG("BMS battV=%.2f\n", pt_bms->t_bcp_data.f32_batt_volt); v_bms_err_data(gunNo );//电流数据不在有效数据范围内停止充电 if(pt_bms->e_state == GB_BMS_HANDSHAKE_TX_CRM_AA) pt_bms->e_state = GB_BMS_CFG_TX_CTS_CML; //跳转5 u8_tim_reset(gunNo,cnt_global); //清空计时 } } else #endif { if ((pt_msg->u16_len >= 13) /*&& (pt_msg->u8_pri == 7)*/) { pt_bms->u8_bms_rx_flag[2] = 1; //bms报文接收标志 pt_bms->t_bcp_data.f32_cell_charge_max_volt = (((U16_T)(pt_msg->u8_data[1])<<8) | pt_msg->u8_data[0]) / 100.0; if(pt_bms->t_brm_data.u8_Bms_edition == 0x5A) //接收到2015+协议标识 5A电流偏移量改为3000A { pt_bms->t_bcp_data.f32_batt_charge_max_curr = -((((U16_T)(pt_msg->u8_data[3])<<8) | pt_msg->u8_data[2]) / 10.0 - 3000); } else pt_bms->t_bcp_data.f32_batt_charge_max_curr = -((((U16_T)(pt_msg->u8_data[3])<<8) | pt_msg->u8_data[2]) / 10.0 - 400); pt_bms->t_bcp_data.f32_batt_rated_enery = (((U16_T)(pt_msg->u8_data[5])<<8) | pt_msg->u8_data[4]) / 10.0; pt_bms->t_bcp_data.f32_batt_charge_max_volt = (((U16_T)(pt_msg->u8_data[7])<<8) | pt_msg->u8_data[6]) / 10.0; pt_bms->t_bcp_data.s16_batt_allow_max_temp = (S16_T)(pt_msg->u8_data[8]) - 50; pt_bms->t_bcp_data.f32_batt_start_soc = (((U16_T)(pt_msg->u8_data[10])<<8) | pt_msg->u8_data[9]) / 10.0; pt_bms->t_bcp_data.f32_batt_volt = (((U16_T)(pt_msg->u8_data[12])<<8) | pt_msg->u8_data[11]) / 10.0; // BMS_LOG("单体动力蓄电池最高允许充电电压=%d\n", (U32_T)(pt_bms->f32_cell_charge_max_volt*100)); // BMS_LOG("最高允许充电电流=%d\n", (U32_T)(pt_bms->f32_batt_charge_max_curr*10)); // BMS_LOG("动力蓄电池标称总能量=%d\n", (U32_T)(pt_bms->f32_batt_rated_enery*10)); // BMS_LOG("最高允许充电电压=%d\n", (U32_T)(pt_bms->f32_batt_charge_max_volt_judge*10)); // BMS_LOG("最高允许温度=%d\n", (U32_T)(pt_bms->s16_batt_allow_max_temp*10)); // BMS_LOG("整车动力蓄电池荷电状态=%d\n", (U32_T)(pt_bms->f32_batt_start_soc*10)); BMS_LOG("BMS battV=%.2f\n", pt_bms->t_bcp_data.f32_batt_volt); v_bms_err_data(gunNo );//电流数据不在有效数据范围内停止充电 if(pt_bms->e_state == GB_BMS_HANDSHAKE_TX_CRM_AA) pt_bms->e_state = GB_BMS_CFG_TX_CTS_CML; //跳转5 u8_tim_reset(gunNo,cnt_global); //清空计时 } } } /**************************************************** *功能说明: BRO数据接收解析函数 *参数说明: * 输入参数: U8_T gunNo 枪号,CAN_DATA_T *pt_msg 接收can数据 * 输出参数: void *最后修改时间: 20230210 *修改内容: 20230210 第一次创建子函数 ****************************************************/ static void v_bms_bro_rx(U8_T gunNo,CAN_DATA_T *pt_msg) { S_BMS_RT_DATA *pt_bms = &s_bms_data.s_bms_rt_data[gunNo]; if(pt_bms->e_state < GB_BMS_CFG_TX_CTS_CML && pt_bms->e_state > GB_BMS_CFG_TX_CRO_AA) //只在此阶段阶段接收 return; if ((pt_msg->u16_len >= 1) /*&& (pt_msg->u8_pri == 4)*/) { pt_bms->u8_bms_rx_flag[3] = 1; //bms报文接收标志 if ((pt_msg->u8_data[0] == 0x00) || (pt_msg->u8_data[0] == 0xFF)) //bms未完成准备 { if(pt_bms->e_state == GB_BMS_CFG_TX_CTS_CML) { BMS_LOG("BMS BRO 0x00 not ready\n"); pt_bms->e_state = GB_BMS_CFG_RX_BRO_AA; //跳转6 u8_tim_reset(gunNo,cnt_bro_aa); //broAA 接收清零 } else if(pt_bms->e_state == GB_BMS_CFG_TX_CRO_00 || pt_bms->e_state == GB_BMS_CFG_TX_CRO_AA)//bms出现问题,不是准备就绪状态了,充电机1s内停止通信,断开K3K4,电子锁解锁,按故障处理方式b处理 { pt_bms->e_state = GB_BMS_STOP; v_set_rt_state(gunNo, BMS_STATE_ERR); //bms状态转数据异常 BMS_LOG("BMS BRO 0xAA data err st=%d\n",pt_bms->e_state); } } else if (pt_msg->u8_data[0] == 0xAA) //充电机完成准备 { if(pt_bms->e_state == GB_BMS_CFG_TX_CTS_CML || pt_bms->e_state == GB_BMS_CFG_RX_BRO_AA) { BMS_LOG("BMS BRO 0xAA ready\n"); pt_bms->e_state = GB_BMS_CFG_TX_CRO_00; //跳转7 #if CAN_PLC_FLAG //欧标 CAN转PLC使能 if ((s_bms_data.u8_gun_type[gunNo] == 0)) v_set_rt_state(gunNo, BMS_STATE_HANDSHAKE_START_OK); //欧标:BMS状态-开始预充电 else #endif v_set_rt_state(gunNo, BMS_STATE_PRECHARGE); //国标:BMS状态-开始预充电 } u8_tim_reset(gunNo,cnt_bro_aa); //broAA 接收清零 } u8_tim_reset(gunNo,cnt_global); //清空计时 } } /**************************************************** *功能说明: BCS数据接收解析函数 *参数说明: * 输入参数: U8_T gunNo 枪号,CAN_DATA_T *pt_msg 接收can数据 * 输出参数: void *最后修改时间: 20230210 *修改内容: 20230210 第一次创建子函数 ****************************************************/ static void v_bms_bcs_rx(U8_T gunNo,CAN_DATA_T *pt_msg) { S_BMS_RT_DATA *pt_bms = &s_bms_data.s_bms_rt_data[gunNo]; if(pt_bms->e_state != GB_BMS_CFG_TX_CRO_AA && pt_bms->e_state != GB_BMS_CHARGE_STAGE) //只在此阶段阶段接收 return; pt_bms->u8_bms_rx_flag[4] = 1; //bms报文接收标志 pt_bms->t_bcs_data.f32_charge_volt = (((U16_T)(pt_msg->u8_data[1])<<8) | pt_msg->u8_data[0]) / 10.0; if(pt_bms->t_brm_data.u8_Bms_edition == 0x5A) { pt_bms->t_bcs_data.f32_charge_curr = -((((U16_T)(pt_msg->u8_data[3])<<8) | pt_msg->u8_data[2]) / 10.0 - 3000); }else pt_bms->t_bcs_data.f32_charge_curr = -((((U16_T)(pt_msg->u8_data[3])<<8) | pt_msg->u8_data[2]) / 10.0 - 400); pt_bms->t_bcs_data.f32_cell_max_volt = ((((U16_T)(pt_msg->u8_data[5])<<8) | pt_msg->u8_data[4]) & 0x0FFF) / 100.0; pt_bms->t_bcs_data.u8_cell_max_volt_group_num = (pt_msg->u8_data[5]>>4); pt_bms->t_bcs_data.u8_batt_soc = pt_msg->u8_data[6]; pt_bms->t_bcs_data.u16_remain_charge_time = ((U16_T)(pt_msg->u8_data[8])<<8) | pt_msg->u8_data[7]; u8_tim_reset(gunNo,cnt_global); //清空计时 //BMS_LOG("bms--启动中--收到BCS\n"); // BMS_LOG("111充电电压测量值=%d\n", (U32_T)(pt_bms->f32_charge_volt*10) ); // BMS_LOG("充电电流测量值=%d\n", (U32_T)(pt_bms->f32_charge_curr*10)); // BMS_LOG("最高单体动力蓄电池电压 = %d , 组号=%d\n", (U32_T)(pt_bms->f32_cell_max_volt*100), pt_bms->u8_cell_max_volt_group_num); // BMS_LOG("当前荷电状态SOC% =%d\n", pt_bms->u8_batt_soc); //BMS_LOG("估算剩余充电时间=%d\n", pt_bms->t_bcs_data.u16_remain_charge_time); } /**************************************************** *功能说明: BCL数据接收解析函数 *参数说明: * 输入参数: U8_T gunNo 枪号,CAN_DATA_T *pt_msg 接收can数据 * 输出参数: void *最后修改时间: 20230210 *修改内容: 20230210 第一次创建子函数 ****************************************************/ static void v_bms_bcl_rx(U8_T gunNo,CAN_DATA_T *pt_msg) { S_BMS_RT_DATA *pt_bms = &s_bms_data.s_bms_rt_data[gunNo]; if(pt_bms->e_state != GB_BMS_CFG_TX_CRO_AA && pt_bms->e_state != GB_BMS_CHARGE_STAGE) //只在此阶段阶段接收 return; #if CAN_PLC_FLAG //欧标 CAN转PLC使能 if ((s_bms_data.u8_gun_type[gunNo] == 0)) { /* 1.1 2.8 CR_Plc_EvTargetVolt Charging Target Voltage 0.1 0 0~6553.5 V 电压需求 充电目标电压 3.1 4.7 CR_Plc_EvTargetCurrent Charging Target Current 0.1 -400 A 电流需求 充电目标电流 4.8 4.8 CR_Plc_EvTargetCurrent Charging Target Current 1 0 0~1 A 电流需求电流大于400A标志位 "0:小于400A电流需求计算:400A - 3.1~4.7的电流值; 1:大于400A电流需求计算:3.1~4.7的电流值 + 400A" 5.1 5.8 CR_Plc_ChargingMode 0x2(no value with CCS, however almost EV adopt CC), 1: CV, 2: CC 1 1~2 充电模式 充电模式(0x01:恒压充电;0x02恒流充电) 6.1 7.8 CR_Plc_EvMaxVoltLimit EV Maximum Voltage Limit value 0.1 0 0~6553.5 V 最高允许充电电压 最高允许充电电压 8.1 8.8 CR_Plc_PreCharge_Stauts 1: PreCharge Status : 0: No PreCharge Status 1 0 0~2 预充电状态 1:预充电状态: 0:无预充电状态 */ if ((pt_msg->u16_len >= 5) /*&& (pt_msg->u8_pri == 6)*/) { pt_bms->u8_bms_rx_flag[5] = 1; //bms报文接收标志 pt_bms->t_bcl_data.f32_batt_need_volt = (((U16_T)(pt_msg->u8_data[1])<<8) | pt_msg->u8_data[0]) / 10.0; if((pt_msg->u8_data[3] & 0x80) == 0x80) { pt_bms->t_bcl_data.f32_batt_need_curr = (((((U16_T)(pt_msg->u8_data[3])<<8) | pt_msg->u8_data[2]) & 0x7FFF) / 10.0 + 400); } else pt_bms->t_bcl_data.f32_batt_need_curr = -((((U16_T)(pt_msg->u8_data[3])<<8) | pt_msg->u8_data[2]) / 10.0 - 400); pt_bms->t_bcl_data.u8_charge_mode = pt_msg->u8_data[4]; pt_bms->t_bcl_data.f32_batt_charge_max_volt = (((U16_T)(pt_msg->u8_data[6])<<8) | pt_msg->u8_data[5]) / 10.0; pt_bms->t_bcl_data.u8_preCharge = pt_msg->u8_data[7]; v_bms_err_data(gunNo );//电流数据不在有效数据范围内停止充电 u8_tim_reset(gunNo,cnt_bcl); //清空计时 if(pt_bms->e_real_state < BMS_STATE_PRECHARGE) { v_set_rt_state(gunNo, BMS_STATE_PRECHARGE); //BMS状态-开始预充电 } //BMS_LOG("bms--启动中--收到BCL\n"); //BMS_LOG("111电压需求=%d\n", (U32_T)(pt_bms->f32_batt_need_volt*10) ); //BMS_LOG("电流需求=%d\n", (U32_T)(pt_bms->f32_batt_need_curr*10)); //BMS_LOG("充电模式 = %d\n", pt_bms->u8_charge_mode); } } else #endif { if ((pt_msg->u16_len >= 5) /*&& (pt_msg->u8_pri == 6)*/) { pt_bms->u8_bms_rx_flag[5] = 1; //bms报文接收标志 pt_bms->t_bcl_data.f32_batt_need_volt = (((U16_T)(pt_msg->u8_data[1])<<8) | pt_msg->u8_data[0]) / 10.0; if(pt_bms->t_brm_data.u8_Bms_edition == 0x5A) //该表示为5A { pt_bms->t_bcl_data.f32_batt_need_curr = -((((U16_T)(pt_msg->u8_data[3])<<8) | pt_msg->u8_data[2]) / 10.0 - 3000); }else pt_bms->t_bcl_data.f32_batt_need_curr = -((((U16_T)(pt_msg->u8_data[3])<<8) | pt_msg->u8_data[2]) / 10.0 - 400); pt_bms->t_bcl_data.u8_charge_mode = pt_msg->u8_data[4]; v_bms_err_data(gunNo );//电流数据不在有效数据范围内停止充电 u8_tim_reset(gunNo,cnt_bcl); //清空计时 //BMS_LOG("bms--启动中--收到BCL\n"); //BMS_LOG("111电压需求=%d\n", (U32_T)(pt_bms->f32_batt_need_volt*10) ); //BMS_LOG("电流需求=%d\n", (U32_T)(pt_bms->f32_batt_need_curr*10)); //BMS_LOG("充电模式 = %d\n", pt_bms->u8_charge_mode); } } } /**************************************************** *功能说明: BSM数据接收解析函数 *参数说明: * 输入参数: U8_T gunNo 枪号,CAN_DATA_T *pt_msg 接收can数据 * 输出参数: void *最后修改时间: 20230210 *修改内容: 20230210 第一次创建子函数 ****************************************************/ static void v_bms_bsm_rx(U8_T gunNo,CAN_DATA_T *pt_msg) { U16_T u16_batt_new_state,u16_batt_old_state; S_BMS_RT_DATA *pt_bms = &s_bms_data.s_bms_rt_data[gunNo]; if(pt_bms->e_state != GB_BMS_CHARGE_STAGE) //只在此阶段阶段接收 return; if ((pt_msg->u16_len >= 7) /*&& (pt_msg->u8_pri == 6)*/) { pt_bms->u8_bms_rx_flag[6] = 1; //bms报文接收标志 pt_bms->t_bsm_data.u8_cell_max_volt_id = pt_msg->u8_data[0]; pt_bms->t_bsm_data.s16_batt_max_temp = (S16_T)(pt_msg->u8_data[1]) - 50; pt_bms->t_bsm_data.u8_max_temp_id = pt_msg->u8_data[2]; pt_bms->t_bsm_data.s16_batt_min_temp = (S16_T)(pt_msg->u8_data[3]) - 50; pt_bms->t_bsm_data.u8_min_temp_id = pt_msg->u8_data[4]; u16_batt_new_state = 0; //电池状态 if ((pt_msg->u8_data[5]&0x03) == 0x01) //单体动力蓄电池电压过高 { u16_batt_new_state |= 0x0001; v_set_bms_stop_info(gunNo , E_BMS_STOP_15012); } else if ((pt_msg->u8_data[5]&0x03) == 0x02) //单体动力蓄电池电压过低 { u16_batt_new_state |= 0x0002; v_set_bms_stop_info(gunNo , E_BMS_STOP_15013); } else { u16_batt_new_state &= ~0x0003; } if ((pt_msg->u8_data[5]&0x0C) == 0x04) //整车动力蓄电池荷电状态SOC过高 { u16_batt_new_state |= 0x0004; v_set_bms_stop_info(gunNo , E_BMS_STOP_15014); } else if ((pt_msg->u8_data[5]&0x0C) == 0x08) //整车动力蓄电池荷电状态SOC过低 { u16_batt_new_state |= 0x0008; v_set_bms_stop_info(gunNo , E_BMS_STOP_15015); } else { u16_batt_new_state &= ~0x000C; } if ((pt_msg->u8_data[5]&0x30) == 0x10) //动力蓄电池充电过流 { u16_batt_new_state |= 0x0010; v_set_bms_stop_info(gunNo , E_BMS_STOP_15016); } else { u16_batt_new_state &= ~0x0010; } if ((pt_msg->u8_data[5]&0xC0) == 0x40) //动力蓄电池温度过高 { u16_batt_new_state |= 0x0020; v_set_bms_stop_info(gunNo , E_BMS_STOP_15017); } else { u16_batt_new_state &= ~0x0020; } if ((pt_msg->u8_data[6]&0x03) == 0x01) //动力蓄电池绝缘状态不正常 { u16_batt_new_state |= 0x0040; v_set_bms_stop_info(gunNo , E_BMS_STOP_15018); } else { u16_batt_new_state &= ~0x0040; } if ((pt_msg->u8_data[6]&0x0C) == 0x04) //动力蓄电池组输出连接器连接状态不正常 { u16_batt_new_state |= 0x0080; v_set_bms_stop_info(gunNo , E_BMS_STOP_15019); } else { u16_batt_new_state &= ~0x0080; } if ((pt_msg->u8_data[6]&0x30) == 0x10) //充电允许,00禁止,01允许 u16_batt_new_state |= 0x0100; //允许则置1 else u16_batt_new_state &= ~0x0100; //禁止 u16_batt_old_state = pt_bms->t_bsm_data.u16_batt_state; pt_bms->t_bsm_data.u16_batt_state = u16_batt_new_state; if((u16_batt_new_state & 0x00FF) != 0) //bsm异常 { pt_bms->e_state = GB_BMS_CHARGE_TX_CST; //; //跳转 GB_BMS_STOP u8_tim_reset(gunNo,cnt_bcl); u8_tim_reset(gunNo,cnt_bro_aa); //broAA 接收清零 BMS_LOG("BMS BSM abn stop\n"); } //BMS_LOG("BSM,允许充电状态,原=%x,新=%x\n", u16_batt_old_state, u16_batt_new_state); if (((u16_batt_old_state & 0xFF00) == 0x0100) && ((u16_batt_new_state & 0xFF00) == 0)) //原来允许,现在禁止充电 { v_set_rt_state(gunNo, BMS_STATE_BSM_FORBID); //bms:充电禁止状态 //pt_bms->ulong_BSM_forbit_timer = get_current_seconds(); BMS_LOG("BMS BSM forbid chg\n"); } else if(((u16_batt_old_state & 0xFF00) == 0) && ((u16_batt_new_state & 0xFF00) == 0x0100)) //((u16_batt_new_state & 0xFF00) == 1) //现在允许充电 { v_set_rt_state(gunNo, BMS_STATE_CHARGING); //bms状态转10,充电中 //pt_bms->ulong_BSM_forbit_timer = 0; BMS_LOG("BMS BSM allow chg\n"); } } } /**************************************************** *函数名称: void v_bms_bmv_send(U8_T gunNo,CAN_DATA_T *pt_msg) *功能说明: BMV数据接收解析函数 *参数说明: * 输入参数: U8_T gunNo 枪号,CAN_DATA_T *pt_msg 接收can数据 * 输出参数: void *最后修改时间: 20230210 *修改内容: 20230210 第一次创建子函数 ****************************************************/ static void v_bms_bmv_rx(U8_T gunNo,CAN_DATA_T *pt_msg) { U16_T i; S_BMS_RT_DATA *pt_bms = &s_bms_data.s_bms_rt_data[gunNo]; if(pt_bms->e_state != GB_BMS_CHARGE_STAGE) //只在此阶段阶段接收 return; if ((pt_msg->u16_len <= 512) /*&& (pt_msg->u8_pri == 7)*/) { pt_bms->u8_bms_rx_flag[7] = 1; //bms报文接收标志 for (i=0; iu16_len/2; i++) { pt_bms->t_bmv_data.u_data[i].s_bit.bit_cell_volt = ((((U16_T)(pt_msg->u8_data[2*i+1])<<8) | pt_msg->u8_data[2*i]) & 0x0FFF) / 100.0; pt_bms->t_bmv_data.u_data[i].s_bit.bit_cell_group_numt = (pt_msg->u8_data[2*i+1]>>4); } } } /**************************************************** *函数名称: void v_bms_bmt_send(U8_T gunNo,CAN_DATA_T *pt_msg) *功能说明: BMT数据接收解析函数 *参数说明: * 输入参数: U8_T gunNo 枪号,CAN_DATA_T *pt_msg 接收can数据 * 输出参数: void *最后修改时间: 20230210 *修改内容: 20230210 第一次创建子函数 ****************************************************/ static void v_bms_bmt_rx(U8_T gunNo,CAN_DATA_T *pt_msg) { U8_T i; S_BMS_RT_DATA *pt_bms = &s_bms_data.s_bms_rt_data[gunNo]; if(pt_bms->e_state != GB_BMS_CHARGE_STAGE) //只在此阶段阶段接收 return; if ((pt_msg->u16_len <= 128) /*&& (pt_msg->u8_pri == 7)*/) { pt_bms->u8_bms_rx_flag[8] = 1; //bms报文接收标志 for (i=0; iu16_len; i++) { pt_bms->t_bmt_data.u8_batt_temp[i] = (pt_msg->u8_data[i]); } } } /**************************************************** *函数名称: void v_bms_bst_send(U8_T gunNo,CAN_DATA_T *pt_msg) *功能说明: BST数据接收解析函数 *参数说明: * 输入参数: U8_T gunNo 枪号,CAN_DATA_T *pt_msg 接收can数据 * 输出参数: void *最后修改时间: 20230210 *修改内容: 20230210 第一次创建子函数 ****************************************************/ static void v_bms_bst_rx(U8_T gunNo,CAN_DATA_T *pt_msg) { S_BMS_RT_DATA *pt_bms = &s_bms_data.s_bms_rt_data[gunNo]; if(pt_bms->e_state == GB_BMS_STOP) //空闲是不接收 return; #if CAN_PLC_FLAG //欧标 CAN转PLC使能 if ((s_bms_data.u8_gun_type[gunNo] == 0)) { /* 1.1 1.2 CF_Plc_ReachSoC 0: fail, 1: reach , 2:unknown 1 0 0~2 不支持 不判断 达到所需的SOC目标值 0:未到达,1:到达,2:未知 1.3 1.4 CF_Plc_ReachTotalVolt 0: fail, 1: reach , 2:unknown 1 0 0~2 不支持 不判断 达到总电压设定值 0:未到达,1:到达,2:未知 1.5 1.6 CF_Plc_ReachSingleVolt 0: fail, 1: reach , 2:unknown 1 0 0~2 不支持 不判断 到达单体电压设定值 0:未到达,1:到达,2:未知 1.7 1.8 CF_Plc_ChargerSuspend 0: normal, 1: suspension, 2:unknown 1 0 0~2 判断 充电机主动中止 0:正常,1:暂停,2:未知 2.1 2.2 CF_Plc_InstationFault 0: normal, 1: fault, 2:unknown 1 0 0~2 不支持 不判断 绝缘故障 0:正常,1:故障,2:未知 2.3 2.4 CF_Plc_ConnectorHighTemp 0: normal, 1: fault, 2:unknown 1 0 0~2 不支持 不判断 输出连接器过温故障 0:正常,1:故障,2:未知 2.5 2.6 CF_Plc_BmsOverTemp 0: normal, 1: fault, 2:unknown 1 0 0~2 不支持 不判断 BMS元件、输出连接线过温 0:正常,1:故障,2:未知 2.7 2.8 CF_Plc_ConnectorFault 0: normal, 1: fault, 2:unknown 1 0 0~2 不支持 不判断 充电连接器故障 0:正常,1:故障,2:未知 3.1 3.2 CF_Plc_BatOverTemp 0: normal, 1: overtemp, 2:unknown 1 0 0~2 不支持 不判断 电池组温度过高故障 0:正常,1:过热,2:未知 3.3 3.4 CF_Plc_HighVoltRelay 0: normal, 1: fault, 2:unknown 1 0 0~2 不支持 不判断 高压继电器故障 0:正常,1:故障,2:未知 3.5 3.6 CF_Plc_ErrCheckPoint2 0: normal, 1: fault, 2:unknown 1 0 0~2 不支持 不判断 检测点2电压检测故障 0:正常,1:故障,2:未知 3.7 3.8 CF_Plc_OtherFault 0: normal, 1: fault, 2:unknown 1 0 0~2 不支持 不判断 其他故障 0:正常,1:故障,2:未知 4.1 4.2 CF_Plc_CurrOver 0: curren, 1: current exceed, 2:unknown 1 0 0~2 不支持 不判断 电流过大 0:当前,1:电流超出,2:未知 4.3 4.4 CF_Plc_AbnormalVolt 0: normal, 1: abnormal, 2:unknown 1 0 0~2 不支持 不判断 电压异常 0:正常,1:异常,2:未知 4.7 4.7 CF_Plc_FullChgComplete 0: not Full 1: full charging complete 1 0 0~1 添加项 判断 车充电是否完成 0:未满1:完全充电完成 4.8 4.8 CF_Plc_ChgFinished_ 0: charging, 1: charging stop request 1 0 0~1 添加项 判断 桩充电状态 0:充电,1:充电停止请求 5.1 5.8 Message_Sequence 1 0x01~0x30 添加项 不判断 通信流程消息序列 通信流程消息序列 6.1 6.8 CR_Plc_ErrorCodeII 0x01~0xA6 添加项 不判断 错误代码II 错误代码,见附录 7.1 7.8 CR_Plc_ErrorCode ErrorCode 0x01~0xE5 添加项 不判断 错误代码 错误代码,见附录 8.1 8.3 ErrorCode by CP or PP state 0x01~0x05 添加项 不判断 CP或PP状态的错误代码 错误代码,见附录 8.4 8.7 CR_PLc_EvErrCode 0x01~0x11 添加项 不判断 EV车辆发送的错误代码 错误代码,见附录 */ if ((pt_msg->u16_len >= 4) /*&& (pt_msg->u8_pri == 4)*/) { pt_bms->u8_bms_rx_flag[9] = 1; //bms报文接收标志 if(pt_bms->e_state != GB_BMS_CHARGE_TX_CST && // pt_bms->e_state != GB_BMS_FINISH_RX_BSD) { pt_bms->e_state = GB_BMS_CHARGE_TX_CST; BMS_LOG("BMS BST rx stop\n"); u8_tim_reset(gunNo,cnt_bcl); } u8_tim_reset(gunNo,cnt_global); //保存充电停止原因,用于发送充电机停止充电报文时回复 memcpy(pt_bms->t_bst_data.u8_bst_data,pt_msg->u8_data,8); pt_bms->t_cst_data.u8_cst_data[0] = 0x40; //车辆主动中止 pt_bms->t_cst_data.u8_cst_data[1] = 0; pt_bms->t_cst_data.u8_cst_data[2] = 0xF0; pt_bms->t_cst_data.u8_cst_data[3] = 0xF0; } } else #endif { if ((pt_msg->u16_len >= 4) /*&& (pt_msg->u8_pri == 4)*/) { pt_bms->u8_bms_rx_flag[9] = 1; //bms报文接收标志 if(pt_bms->e_state != GB_BMS_CHARGE_TX_CST && // pt_bms->e_state != GB_BMS_FINISH_RX_BSD) { pt_bms->e_state = GB_BMS_CHARGE_TX_CST; u8_tim_reset(gunNo,cnt_bcl); } u8_tim_reset(gunNo,cnt_global); //保存充电停止原因,用于发送充电机停止充电报文时回复 memcpy(pt_bms->t_bst_data.u8_bst_data,pt_msg->u8_data,4); if (pt_bms->e_bms_standard == BMS_2015) pt_bms->t_cst_data.u8_cst_data[0] = 0x40; else pt_bms->t_cst_data.u8_cst_data[0] = 0xC0; pt_bms->t_cst_data.u8_cst_data[1] = 0; pt_bms->t_cst_data.u8_cst_data[2] = 0xF0; pt_bms->t_cst_data.u8_cst_data[3] = 0xF0; #if 1 //解释BMS停止充电原因 if ((pt_msg->u8_data[0]&0x03) == 0x01) //达到所需SOC目标值 v_set_bms_stop_info(gunNo , E_BMS_STOP_1000); if ((pt_msg->u8_data[0]&0x0C) == 0x04) //达到总电压设定值 v_set_bms_stop_info(gunNo , E_BMS_STOP_1000); if ((pt_msg->u8_data[0]&0x30) == 0x10) //达到单体电压设定值 v_set_bms_stop_info(gunNo , E_BMS_STOP_1000); if ((pt_msg->u8_data[1]&0x03) == 0x01) //绝缘故障 v_set_bms_stop_info(gunNo , E_BMS_STOP_15022); if ((pt_msg->u8_data[1]&0x0C) == 0x04) //输出连接器过温故障 v_set_bms_stop_info(gunNo , E_BMS_STOP_15023); if ((pt_msg->u8_data[1]&0x30) == 0x10) //BMS元件、输出连接器过温 v_set_bms_stop_info(gunNo , E_BMS_STOP_15024); if ((pt_msg->u8_data[1]&0xC0) == 0x40) //充电连接器故障 v_set_bms_stop_info(gunNo , E_BMS_STOP_15025); if ((pt_msg->u8_data[2]&0x03) == 0x01) //电池组温度过高故障 v_set_bms_stop_info(gunNo , E_BMS_STOP_15026); if (pt_bms->e_bms_standard == BMS_2015) { if ((pt_msg->u8_data[2]&0x0C) == 0x04) //高压继电器故障 v_set_bms_stop_info(gunNo , E_BMS_STOP_15029); if ((pt_msg->u8_data[2]&0x30) == 0x10) //检测点2电压检测故障 v_set_bms_stop_info(gunNo , E_BMS_STOP_15028); if ((pt_msg->u8_data[2]&0xC0) == 0x40) //其它故障 v_set_bms_stop_info(gunNo , E_BMS_STOP_15027); } else { if ((pt_msg->u8_data[2]&0x0C) == 0x04) //其它故障 v_set_bms_stop_info(gunNo , E_BMS_STOP_15021); } if ((pt_msg->u8_data[3]&0x03) == 0x01) //电流超过需求值 v_set_bms_stop_info(gunNo , E_BMS_STOP_15030); if ((pt_msg->u8_data[3]&0x0C) == 0x04) //电压异常 v_set_bms_stop_info(gunNo , E_BMS_STOP_15031); if(s_bms_data.s_bms_rt_data[gunNo].e_stop_info == E_BMS_STOP_NULL) v_set_bms_stop_info(gunNo , E_BMS_STOP_1000); //BMS_LOG("BMS - bst停止充电,停止原因 = %lld\n", pt_bms->t_bst_data.u8_bst_data);//g_t_share_data.t_rt_data.t_ctrl.u_stop_chag_reason[gunNo].u64_stopChag_reason); #endif } } } /**************************************************** *函数名称: void v_bms_bsd_send(U8_T gunNo,CAN_DATA_T *pt_msg) *功能说明: BSD数据接收解析函数 *参数说明: * 输入参数: U8_T gunNo 枪号,CAN_DATA_T *pt_msg 接收can数据 * 输出参数: void *最后修改时间: 20230210 *修改内容: 20230210 第一次创建子函数 ****************************************************/ static void v_bms_bsd_rx(U8_T gunNo,CAN_DATA_T *pt_msg) { S_BMS_RT_DATA *pt_bms = &s_bms_data.s_bms_rt_data[gunNo]; if(pt_bms->e_state < GB_BMS_CHARGE_TX_CST) //只在此阶段阶段接收 return; if (pt_msg->u32_pgn == GB_BMS_PGN_BSD) { if ((pt_msg->u16_len >= 7) /*&& (pt_msg->u8_pri == 6)*/) { pt_bms->u8_bms_rx_flag[10] = 1; //bms报文接收标志 pt_bms->t_bsd_data.u8_batt_end_soc = pt_msg->u8_data[0]; pt_bms->t_bsd_data.f32_cell_batt_min_volt = (((U16_T)(pt_msg->u8_data[2])<<8) | pt_msg->u8_data[1]) / 100.0; pt_bms->t_bsd_data.f32_cell_batt_max_volt = (((U16_T)(pt_msg->u8_data[4])<<8) | pt_msg->u8_data[3]) / 100.0; pt_bms->t_bsd_data.u8_batt_min_temp = (U8_T)(pt_msg->u8_data[5]) - 50; pt_bms->t_bsd_data.u8_batt_max_temp = (U8_T)(pt_msg->u8_data[6]) - 50; pt_bms->t_bsd_data.u8_batt_end_soc = pt_msg->u8_data[0]; #if CAN_PLC_FLAG //欧标 CAN转PLC使能 if ((s_bms_data.u8_gun_type[gunNo] == 0)) pt_bms->t_bsd_data.u8_CF_Plc_WeldDetectionReq = pt_msg->u8_data[0]&0x01; //欧标:粘连检测要求 #endif u8_tim_reset(gunNo,cnt_bcl); if(pt_bms->e_state != GB_BMS_FINISH_RX_BSD) { BMS_LOG("BSD rx, stop SOC=%d\n", pt_bms->t_bsd_data.u8_batt_end_soc); v_set_bms_stop_info(gunNo,E_BMS_STOP_1011); //bms停止 pt_bms->e_state = GB_BMS_FINISH_RX_BSD; //; //跳转 GB_BMS_STOP } } } } /**************************************************** *函数名称: void v_bms_bem_send(U8_T gunNo,CAN_DATA_T *pt_msg) *功能说明: BEM数据接收解析函数 *参数说明: * 输入参数: U8_T gunNo 枪号,CAN_DATA_T *pt_msg 接收can数据 * 输出参数: void *最后修改时间: 20230210 *修改内容: 20230210 第一次创建子函数 ****************************************************/ static void v_bms_bem_rx(U8_T gunNo,CAN_DATA_T *pt_msg) { S_BMS_RT_DATA *pt_bms = &s_bms_data.s_bms_rt_data[gunNo]; if ((pt_msg->u16_len >= 4) /*&& (pt_msg->u8_pri == 2)*/) { pt_bms->u8_bms_rx_flag[11] = 1; //bms报文接收标志 //只判定在【握手辨识,充电中】过程中的BEM,握手启动及充电结束阶段不管 if((s_bms_data.s_bms_rt_data[gunNo].e_state >= GB_BMS_HANDSHAKE_TX_CRM_00) && (s_bms_data.s_bms_rt_data[gunNo].e_state <= GB_BMS_CHARGE_STAGE)) { BMS_LOG("BEM rx, comm TO -> reconn x3\n"); #if CAN_PLC_FLAG //欧标 CAN转PLC使能 if ((s_bms_data.u8_gun_type[gunNo] == 0)) memcpy(pt_bms->t_bem_data.u8_bem_data,pt_msg->u8_data,8); else #endif memcpy(pt_bms->t_bem_data.u8_bem_data,pt_msg->u8_data,4); (void)u8_bms_timeout(0,gunNo,1,GB_BCP_TIMEOUT_FLAG); v_set_rt_state(gunNo, BMS_STATE_TIMEOUT); //bms.state=6 - 报文超时,flow任务除了检测ctr.cmd外,还应检测 } } } /**************************************************** *函数名称: void v_bmsComm_rx_handle(U8_T gunNo) *功能说明: bms 解帧函数 *参数说明: * 输入参数: U8_T gunNo, 枪号 * 输出参数: void *最后修改时间: 20230228 *修改内容: 20230228 第一次创建子函数 ****************************************************/ void v_bmsComm_rx_handle(U8_T gunNo) { CAN_DATA_T *pt_msg = &s_bms_data.s_gb_bms_can[gunNo].pt_msg; //待解析的报文 u8_bms_get_lock();//申请锁 // printf_hex("bms recv:",pt_msg->u8_data,pt_msg->u16_len); #if 1 switch(pt_msg->u32_pgn) { case GB_BMS_PGN_BHM: //BHM { v_bms_bhm_rx(gunNo,pt_msg); break; } case GB_BMS_PGN_BRM: { v_bms_brm_rx(gunNo,pt_msg); break; } case GB_BMS_PGN_BCP: { v_bms_bcp_rx(gunNo,pt_msg); break; } case GB_BMS_PGN_BRO: { v_bms_bro_rx(gunNo,pt_msg); break; } case GB_BMS_PGN_BCS: { v_bms_bcs_rx(gunNo,pt_msg); break; } case GB_BMS_PGN_BCL: { v_bms_bcl_rx(gunNo,pt_msg); break; } case GB_BMS_PGN_BSM: { v_bms_bsm_rx(gunNo,pt_msg); break; } case GB_BMS_PGN_BMV: { v_bms_bmv_rx(gunNo,pt_msg); break; } case GB_BMS_PGN_BMT: { v_bms_bmt_rx(gunNo,pt_msg); break; } case GB_BMS_PGN_BST: { v_bms_bst_rx(gunNo,pt_msg); break; } case GB_BMS_PGN_BSD: { v_bms_bsd_rx(gunNo,pt_msg); break; } case GB_BMS_PGN_BEM: { v_bms_bem_rx(gunNo,pt_msg); break; } default: break; } #endif u8_bms_free_lock();//释放锁 } /**************************************************** *函数名称: void v_bms_rx_data(U8_T gunNo) *功能说明: bms CAN数据接收函数 *参数说明: * 输入参数: U8_T gunNo, 枪号 * 输出参数: void *最后修改时间: 20230228 *修改内容: 20230228 第一次创建子函数 ****************************************************/ static void v_bms_rx_data(U8_T gunNo) { U8_T i,canRcvCnt = 0; //接收can报文数目 CAN_DATA rxMsg[CAN_RECV_BUF_SIZE] = {0}; S_GB_BMS_CAN *s_gb_bms_can = &s_bms_data.s_gb_bms_can[gunNo]; //接收数据并解析,实时数据/状态 //canRcvCnt = s_bms_data[gunNo].s_gb_bms_can.pt_dll->u32_can_rx(&rxMsg[0]); canRcvCnt = s_gb_bms_can->pt_dll.u32_can_rx(&rxMsg[0]); if(canRcvCnt > 0) { // printf("接收can1报文数 = %d\n", canRcvCnt); for(i=0; ipt_dll, &s_gb_bms_can->pt_msg, rxMsg[i]) == 1) //=1说明接收到完整帧,可解析 v_bmsComm_rx_handle(gunNo); } } } #endif #if 1 //发送相关 /**************************************************** *函数名称: void v_bms_tx( CAN_DATA_T *pt_can_data) *功能说明: BMS数据发送函数--发送can报文都是单包数据 *参数说明: * 输入参数: DLL_DATA_T *pt_dll_data, CAN_DATA_T *pt_can_data * 输出参数: void *最后修改时间: 20230210 *修改内容: 20230210 第一次创建子函数 ****************************************************/ static void v_bms_tx(U8_T gunNo,CAN_DATA_T *pt_msg) { u32_sae1393_tx(&s_bms_data.s_gb_bms_can[gunNo].pt_dll, pt_msg); } /**************************************************** *函数名称: void v_bms_chm_send(U8_T gunNo) *功能说明: CHM组帧发送函数 *参数说明: * 输入参数: U8_T gunNo 枪号 * 输出参数: void *最后修改时间: 20230210 *修改内容: 20230210 第一次创建子函数 ****************************************************/ static void v_bms_chm_send(U8_T gunNo) { CAN_DATA_T pt_msg; S_BMS_RT_DATA *pt_bms = &s_bms_data.s_bms_rt_data[gunNo]; #if CAN_PLC_FLAG //欧标 CAN转PLC使能 if ((s_bms_data.u8_gun_type[gunNo] == 0)) { /* 1.1 1.8 CR_Secc_VersionMinor 1:国标, 1:欧美标(默认值默认传递绝缘有限),2 (添加实时传递绝缘状态支持) 通信版本 2.1 2.8 CR_Secc_VersionMajorL 1:国标, 0:欧美标, 通信版本 3.1 3.8 CR_Secc_VersionMajorH 0:国标, 1:欧美标 通信版本 4.1 4.4 CR_Secc_EvseTransferType Supported Energy Type (default 3, see appendix) 供电设备传输类型 (默认值3,见附录)支持的能量类型 4.5 4.5 CF_Secc_StartPlc 0: PLC wait to start 1: PLC start chargeing seq. 启动Plc 0:PLC等待启动 1:PLC启动充电顺序。 5.1 6.8 CR_Secc_MaxPowerLimit Maximum Power Limit (mandatory) 最大功率限制 最大功率限制(强制) */ U16_T u16_sys_data[3] = {0}; u16_sys_data[0] = u16_bms_get_sys_para(gunNo , E_BMS_GET_PARA_MAX_VOL); //最大输出电压 精度0.1 u16_sys_data[1] = u16_bms_get_sys_para(gunNo , E_BMS_GET_PARA_MAX_CUR); //最大输出电流 精度0.1 u16_sys_data[2] = ((u16_sys_data[0]/10)*(u16_sys_data[1]/10))/1000; pt_msg.u32_pgn = GB_BMS_PGN_CHM; pt_msg.u8_pri = 6; pt_msg.u8_src_addr = GB_CHARGER_ADDR; pt_msg.u8_dest_addr = GB_BMS_ADDR; pt_msg.u16_len = 8; pt_msg.u8_data[0] = 0x01; pt_msg.u8_data[1] = 0x01; pt_msg.u8_data[2] = 0x00; if(s_bms_data.u8_gun_linkState[gunNo]) //抢连接 pt_msg.u8_data[3] = 0x13; else pt_msg.u8_data[3] = 0x03; //最大功率限值 pt_msg.u8_data[4] = u16_sys_data[2] & 0xff; pt_msg.u8_data[5] = (u16_sys_data[2] >> 8) & 0xff; } else #endif { pt_msg.u32_pgn = GB_BMS_PGN_CHM; pt_msg.u8_pri = 6; pt_msg.u8_src_addr = GB_CHARGER_ADDR; pt_msg.u8_dest_addr = GB_BMS_ADDR; pt_msg.u16_len = 3; if(u16_bms_get_sys_para(gunNo,E_BMS_GET_PARA_SC_EN) == 1 && pt_bms->u16_stoptimeflag<= (4*10)) //团标使能和启动前10S发送协议版本SC1 250ms周期 4周期为1秒 { pt_msg.u8_data[0] = 0x31; pt_msg.u8_data[1] = 0x43; pt_msg.u8_data[2] = 0x53; pt_bms->u16_stoptimeflag++; }else { pt_msg.u8_data[0] = 0x01; pt_msg.u8_data[1] = 0x01; pt_msg.u8_data[2] = 0x00; } } v_bms_tx(gunNo,&pt_msg); } /**************************************************** *函数名称: void v_bms_crm_send(U8_T gunNo,U8_T flag) *功能说明: CRM组帧发送函数 *参数说明: * 输入参数: U8_T gunNo 枪号 ,U8_T flag 准备就绪标志 * 输出参数: void *最后修改时间: 20230210 *修改内容: 20230210 第一次创建子函数 ****************************************************/ static void v_bms_crm_send(U8_T gunNo,U8_T flag) { CAN_DATA_T pt_msg; pt_msg.u32_pgn = GB_BMS_PGN_CRM; pt_msg.u8_pri = 6; pt_msg.u8_src_addr = GB_CHARGER_ADDR; pt_msg.u8_dest_addr = GB_BMS_ADDR; pt_msg.u16_len = 8; pt_msg.u8_data[0] = flag; //辨识结果,0x00-不能辨识,0xAA-bms能辨识 pt_msg.u8_data[1] = 1;//pile_num[0]; //充电机编号 0-0xffffffff pt_msg.u8_data[2] = 0;//pile_num[1]; pt_msg.u8_data[3] = 0;//pile_num[2]; pt_msg.u8_data[4] = 1;//pile_num[3]; pt_msg.u8_data[5] = 0; //所在区域编码,可选 pt_msg.u8_data[6] = 0; pt_msg.u8_data[7] = 0; v_bms_tx(gunNo,&pt_msg); } /**************************************************** *函数名称: void v_bms_cml_send(U8_T gunNo) *功能说明: CML组帧发送函数 *参数说明: * 输入参数: U8_T gunNo 枪号 * 输出参数: void *最后修改时间: 20230210 *修改内容: 20230210 第一次创建子函数 ****************************************************/ static void v_bms_cml_send(U8_T gunNo) { CAN_DATA_T pt_msg; U16_T u16_data; U16_T u16_sys_data[4]; S_BMS_RT_DATA *pt_bms = &s_bms_data.s_bms_rt_data[gunNo]; u16_sys_data[0] = u16_bms_get_sys_para(gunNo , E_BMS_GET_PARA_MAX_VOL); //最大输出电压 精度0.1 u16_sys_data[1] = u16_bms_get_sys_para(gunNo , E_BMS_GET_PARA_MIN_VOL); //最小输出电压 精度0.1 u16_sys_data[2] = u16_bms_get_sys_para(gunNo , E_BMS_GET_PARA_MAX_CUR); //最大输出电流 精度0.1 u16_sys_data[3] = u16_bms_get_sys_para(gunNo , E_BMS_GET_PARA_MIN_CUR); //最小输出电流 精度0.1 pt_msg.u32_pgn = GB_BMS_PGN_CML; pt_msg.u8_pri = 6; pt_msg.u8_src_addr = GB_CHARGER_ADDR; pt_msg.u8_dest_addr = GB_BMS_ADDR; u16_data = u16_sys_data[0]; //最高输出电压 pt_msg.u8_data[0] = (U8_T)u16_data; pt_msg.u8_data[1] = (U8_T)(u16_data>>8); u16_data = u16_sys_data[1]; //最低输出电压 pt_msg.u8_data[2] = (U8_T)u16_data; pt_msg.u8_data[3] = (U8_T)(u16_data>>8); #if CAN_PLC_FLAG //欧标 CAN转PLC使能 if ((s_bms_data.u8_gun_type[gunNo] == 0)) { pt_msg.u16_len = 8; if(u16_sys_data[2] > 4000) // { u16_data = (((U16_T)((u16_sys_data[2]/10-400)*10)) | 0x8000); //最大输出电流(按电流上限输出充电机最高电流) } else u16_data = (400 - u16_sys_data[2]/10)*10; //最大输出电流(按电流上限输出充电机最高电流) pt_msg.u8_data[4] = (U8_T)u16_data; pt_msg.u8_data[5] = (U8_T)(u16_data>>8); u16_data = (400 - u16_sys_data[3]/10)*10; //最小输出电流(按电流上限输出充电机最低电流) pt_msg.u8_data[6] = (U8_T)u16_data; pt_msg.u8_data[7] = (U8_T)(u16_data>>8); } else #endif { if(pt_bms->t_brm_data.u8_Bms_edition == 0x5A) //接收到2015+协议标识 5A 2015+团标协议 FF国标协议 { u16_data = (3000 - u16_sys_data[2]/10)*10; //最大输出电流(按电流上限输出充电机最高电流) }else u16_data = (400 - u16_sys_data[2]/10)*10; //最大输出电流(按电流上限输出充电机最高电流) pt_msg.u8_data[4] = (U8_T)u16_data; pt_msg.u8_data[5] = (U8_T)(u16_data>>8); if (pt_bms->e_bms_standard == BMS_2011) { pt_msg.u16_len = 6; } else { pt_msg.u16_len = 8; if(pt_bms->t_brm_data.u8_Bms_edition == 0x5A) //接收到2015+协议标识 5A 2015+团标协议 FF国标协议 { u16_data = (3000 - u16_sys_data[3]/10)*10; //最小输出电流(按电流上限输出充电机最低电流) }else u16_data = (400 - u16_sys_data[0]/10)*10; //最小输出电流(按电流上限输出充电机最低电流) pt_msg.u8_data[6] = (U8_T)u16_data; pt_msg.u8_data[7] = (U8_T)(u16_data>>8); } } v_bms_tx(gunNo,&pt_msg); } /**************************************************** *函数名称: void v_bms_cts_send(U8_T gunNo) *功能说明: CTS组帧发送函数 *参数说明: * 输入参数: U8_T gunNo 枪号 * 输出参数: void *最后修改时间: 20230210 *修改内容: 20230210 第一次创建子函数 ****************************************************/ static void v_bms_cts_send(U8_T gunNo) { CAN_DATA_T pt_msg; Comm_Time t_time; v_bms_get_rt_time(&t_time); //获取当前时间 pt_msg.u32_pgn = GB_BMS_PGN_CTS; pt_msg.u8_pri = 6; pt_msg.u8_src_addr = GB_CHARGER_ADDR; pt_msg.u8_dest_addr = GB_BMS_ADDR; pt_msg.u16_len = 7; pt_msg.u8_data[0] = dec_to_bcd(t_time.ucSec); pt_msg.u8_data[1] = dec_to_bcd(t_time.ucMin); pt_msg.u8_data[2] = dec_to_bcd(t_time.ucHour); pt_msg.u8_data[3] = dec_to_bcd(t_time.ucDay); pt_msg.u8_data[4] = dec_to_bcd(t_time.ucMonth); pt_msg.u8_data[5] = dec_to_bcd(t_time.iYear%100); pt_msg.u8_data[6] = dec_to_bcd(t_time.iYear/1000); v_bms_tx(gunNo,&pt_msg); } /**************************************************** *函数名称: void v_bms_cro_send(U8_T gunNo,U8_T flag) *功能说明: CRO组帧发送函数 *参数说明: * 输入参数: U8_T gunNo 枪号 ,U8_T flag 准备就绪标志 * 输出参数: void *最后修改时间: 20230210 *修改内容: 20230210 第一次创建子函数 ****************************************************/ static void v_bms_cro_send(U8_T gunNo,U8_T flag) { CAN_DATA_T pt_msg; pt_msg.u32_pgn = GB_BMS_PGN_CRO; pt_msg.u8_pri = 4; pt_msg.u8_src_addr = GB_CHARGER_ADDR; pt_msg.u8_dest_addr = GB_BMS_ADDR; pt_msg.u16_len = 1; pt_msg.u8_data[0] = flag; #if CAN_PLC_FLAG //欧标 CAN转PLC使能 if ((s_bms_data.u8_gun_type[gunNo] == 0)) { pt_msg.u16_len = 2; if(flag == 0xAA) pt_msg.u8_data[1] = 0x01; else pt_msg.u8_data[1] = 0x00; } #endif v_bms_tx(gunNo,&pt_msg); } /**************************************************** *函数名称: void v_bms_ccs_send(U8_T gunNo) *功能说明: CCS组帧发送函数 *参数说明: * 输入参数: U8_T gunNo 枪号 * 输出参数: void *最后修改时间: 20230210 *修改内容: 20230210 第一次创建子函数 ****************************************************/ static void v_bms_ccs_send(U8_T gunNo) { CAN_DATA_T pt_msg; U16_T u16_data; U16_T u16_out_data[2]; S_BMS_RT_DATA *pt_bms = &s_bms_data.s_bms_rt_data[gunNo]; u16_out_data[0] = u16_bms_get_sys_para(gunNo, E_BMS_GET_GUN_OUT_VOL); //输出电压 精度0.1 u16_out_data[1] = u16_bms_get_sys_para(gunNo, E_BMS_GET_GUN_OUT_CUR); //输出电流 精度0.1 pt_msg.u32_pgn = GB_BMS_PGN_CCS; pt_msg.u8_pri = 6; pt_msg.u8_src_addr = GB_CHARGER_ADDR; pt_msg.u8_dest_addr = GB_BMS_ADDR; u16_data = u16_out_data[0]; //电压输出值 pt_msg.u8_data[0] = (U8_T)u16_data; pt_msg.u8_data[1] = (U8_T)(u16_data>>8); #if CAN_PLC_FLAG //欧标 CAN转PLC使能 if ((s_bms_data.u8_gun_type[gunNo] == 0)) { /* 1.1 2.8 CR_Secc_EvseOutVolt Voltage output value 0.1 0 0~6553.5 V 当前输出电压 电压输出值 3.1 4.7 CR_Secc_EvseOutCurrent Current output value 0.1 -400 A 当前输出电流 电流输出值 4.8 4.8 CR_Secc_EvseOutCurrent Current output value 1 0 0~1 A 当前输出电流大于400A标志位 "0:小于400A电流计算:400A - 3.1~4.7的电流值; 1:大于400A电流计算:3.1~4.7的电流值 + 400A" 5.1 6.8 CR_Secc_MaxPowerLimit Maximum Power Limit (mandatory) 1000 0 0~600 W 桩最大功率限制 最大功率限制 7.1 7.2 CF_Secc_EvseSuspended 0: suspended, 1: permissible 桩停止状态位 0:暂停,1:允许 7.3 7.5 CR_Secc_EvsseIsolationStatus see the appendix 1 0 0~3 桩隔离状态(绝缘检测) 0 无效;1 有效;2 警告;3故障 7.6 7.6 CR_Secc_EvseMaxCurr_IsUse 0: No Use ; 1:Use 1 0 0~1 桩最大电流使用 0:不使用(默认CML中最大电流值); 1:使用(CCS中最大电流值) 7.7 8.8 CR_Secc_EvseMaxCurr_A Max output current 1 0 0 ~ 1000 A 桩最大输出电流 最大输出电流 */ U16_T u16_sys_data[3] = {0}; u16_sys_data[0] = u16_bms_get_sys_para(gunNo , E_BMS_GET_PARA_MAX_VOL); //最大输出电压 精度0.1 u16_sys_data[1] = u16_bms_get_sys_para(gunNo , E_BMS_GET_PARA_MAX_CUR); //最大输出电流 精度0.1 u16_sys_data[2] = ((u16_sys_data[0]/10)*(u16_sys_data[1]/10))/1000; pt_msg.u16_len = 8; if(u16_sys_data[1] > 4000) // { u16_data = (((U16_T)((u16_out_data[1]-4000))) | 0x8000); //最大输出电流(按电流上限输出充电机最高电流) } else u16_data = (U16_T)((4000 - u16_out_data[1])); //电流输出值 pt_msg.u8_data[2] = (U8_T)u16_data; pt_msg.u8_data[3] = (U8_T)(u16_data>>8); u16_data = u16_sys_data[2]; //桩最大功率限制 pt_msg.u8_data[4] = (U8_T)u16_data; pt_msg.u8_data[5] = (U8_T)(u16_data>>8); U8_T CF_Secc_EvseSuspended = 0; //桩停止状态位 0:暂停,1:允许 U8_T CR_Secc_EvsseIsolationStatus = 1; //桩隔离状态(绝缘检测) 0 无效;1 有效;2 警告;3故障 U8_T CR_Secc_EvseMaxCurr_IsUse = 1; //桩最大电流使用 0:不使用(默认CML中最大电流值); 1:使用(CCS中最大电流值) U16_T CR_Secc_EvseMaxCurr_A = u16_bms_get_sys_para(gunNo , E_BMS_GET_PARA_MAX_CUR) / 10; //最大输出电流 精度0.1 u16_data = (CR_Secc_EvseMaxCurr_A << 10) + (CF_Secc_EvseSuspended) + (CR_Secc_EvsseIsolationStatus << 2) + (CR_Secc_EvseMaxCurr_IsUse << 5); pt_msg.u8_data[6] = (U8_T)u16_data; pt_msg.u8_data[7] = (U8_T)(u16_data>>8); } else #endif { if(pt_bms->t_brm_data.u8_Bms_edition == 0x5A) //接收到2015+协议标识 5A 2015+团标协议 FF国标协议 { u16_data = (U16_T)((3000 - u16_out_data[1]/10)*10); //电流输出值 }else u16_data = (U16_T)((400 - u16_out_data[1]/10)*10); //电流输出值 pt_msg.u8_data[2] = (U8_T)u16_data; pt_msg.u8_data[3] = (U8_T)(u16_data>>8); u16_data = u16_bms_get_sys_para(gunNo,E_BMS_GET_GUN_CHR_TIME); //累计充电时间 min pt_msg.u8_data[4] = (U8_T)u16_data; pt_msg.u8_data[5] = (U8_T)(u16_data>>8); if (pt_bms->e_bms_standard == BMS_2011) { pt_msg.u16_len = 6; } else { pt_msg.u16_len = 7; if ((pt_bms->t_bsm_data.u16_batt_state&(1<<8)) == 0) pt_msg.u8_data[6] = 0xFC; else pt_msg.u8_data[6] = 0xFD; pt_msg.u8_data[7] = 0xFF; } } v_bms_tx(gunNo,&pt_msg); } /**************************************************** *函数名称: void v_bms_cst_send(U8_T gunNo) *功能说明: CST组帧发送函数 *参数说明: * 输入参数: U8_T gunNo 枪号 * 输出参数: void *最后修改时间: 20230210 *修改内容: 20230210 第一次创建子函数 ****************************************************/ static void v_bms_cst_send(U8_T gunNo) { CAN_DATA_T pt_msg; U8_T u8_data[4]; if(u8_bms_get_cst(gunNo,u8_data) == 0) return; pt_msg.u32_pgn = GB_BMS_PGN_CST; pt_msg.u8_pri = 4; pt_msg.u8_src_addr = GB_CHARGER_ADDR; pt_msg.u8_dest_addr = GB_BMS_ADDR; pt_msg.u16_len = 4; pt_msg.u8_data[0] = u8_data[0]; //中止原因 pt_msg.u8_data[1] = u8_data[1]; pt_msg.u8_data[2] = u8_data[2]; pt_msg.u8_data[3] = u8_data[3]; v_bms_tx(gunNo,&pt_msg); } /**************************************************** *函数名称: void v_bms_csd_send(U8_T gunNo) *功能说明: CSD组帧发送函数 *参数说明: * 输入参数: U8_T gunNo 枪号 * 输出参数: void *最后修改时间: 20230210 *修改内容: 20230210 第一次创建子函数 ****************************************************/ static void v_bms_csd_send(U8_T gunNo) { CAN_DATA_T pt_msg; U16_T u16_data; U8_T pile_num[17]; S_BMS_RT_DATA *pt_bms = &s_bms_data.s_bms_rt_data[gunNo]; v_bms_get_pile_nun(pile_num); pt_msg.u32_pgn = GB_BMS_PGN_CSD; pt_msg.u8_pri = 6; pt_msg.u8_src_addr = GB_CHARGER_ADDR; pt_msg.u8_dest_addr = GB_BMS_ADDR; pt_msg.u16_len = 8; #if CAN_PLC_FLAG //欧标 CAN转PLC使能 if ((s_bms_data.u8_gun_type[gunNo] == 0)) { /* 1.1 2.8 CR_Secc_CumulativeChTime 0 (no value with CCS), Cumulative Charging Time 1 0 0~600 min 判断 累计充电时间 0(CCS无值);累计充电时间 3.1 4.8 CR_Secc_EvseOutVolt Voltage output value 0.1 0 0~6553.5 V 添加项 不判断 桩枪线当前输出电压 电压输出值 5.1 5.3 CR_Secc_EvseIsolationStatus see the appendix 1 0 0~3 添加项 判断 桩隔离状态(绝缘检测) 0 无效;1 有效;2 警告;3故障 */ //充电时长 u16_data = u16_bms_get_sys_para(gunNo,E_BMS_GET_GUN_CHR_TIME); //累计充电时间 min pt_msg.u8_data[0] = (U8_T)u16_data; pt_msg.u8_data[1] = (U8_T)(u16_data>>8); //桩枪线当前输出电压 0.1V u16_data = u16_bms_get_sys_para(gunNo,E_BMS_GET_GUN_OUT_VOL); //输出电压 精度0.1 pt_msg.u8_data[2] = (U8_T)u16_data; pt_msg.u8_data[3] = (U8_T)(u16_data>>8); //桩隔离状态(绝缘检测) 0 无效;1 有效;2 警告;3故障 U8_T CR_Secc_EvsseIsolationStatus = 1; pt_msg.u8_data[4] = CR_Secc_EvsseIsolationStatus & 0x07; } else #endif { //充电时长 u16_data = u16_bms_get_sys_para(gunNo,E_BMS_GET_GUN_CHR_TIME); //累计充电时间 min pt_msg.u8_data[0] = (U8_T)u16_data; pt_msg.u8_data[1] = (U8_T)(u16_data>>8); //电量 u16_data = u16_bms_get_sys_para(gunNo,E_BMS_GET_GUN_CHR_POWER); //充电电量 0.1kwh pt_msg.u8_data[2] = (U8_T)u16_data; pt_msg.u8_data[3] = (U8_T)(u16_data>>8); pt_msg.u8_data[4] = pile_num[0]; if (pt_bms->e_bms_standard == BMS_2011) { pt_msg.u16_len = 5; } else { pt_msg.u16_len = 8; pt_msg.u8_data[5] = pile_num[1]; pt_msg.u8_data[6] = pile_num[2]; pt_msg.u8_data[7] = pile_num[3]; } } pt_bms->u8_csd_send_cnt ++; //csd发送次数加一 v_bms_tx(gunNo,&pt_msg); } /**************************************************** *函数名称: void v_bms_cem_send(U8_T gunNo) *功能说明: CEM组帧发送函数 *参数说明: * 输入参数: U8_T gunNo 枪号 * 输出参数: void *最后修改时间: 20230210 *修改内容: 20230210 第一次创建子函数 ****************************************************/ static void v_bms_cem_send(U8_T gunNo) { CAN_DATA_T pt_msg; S_BMS_RT_DATA *pt_bms = &s_bms_data.s_bms_rt_data[gunNo]; memset(&pt_msg, 0, sizeof(CAN_DATA_T)); pt_msg.u32_pgn = GB_BMS_PGN_CEM; pt_msg.u8_pri = 2; pt_msg.u8_src_addr = GB_CHARGER_ADDR; pt_msg.u8_dest_addr = GB_BMS_ADDR; pt_msg.u16_len = 4; pt_msg.u8_data[0] = 0xFC; pt_msg.u8_data[1] = 0xF0; pt_msg.u8_data[2] = 0xC0; pt_msg.u8_data[3] = 0xFC; if ((pt_bms->u16_timeout_flag & GB_BRM_TIMEOUT_FLAG) != 0) pt_msg.u8_data[0] |= 0x01; else if ((pt_bms->u16_timeout_flag & GB_BCP_TIMEOUT_FLAG) != 0) pt_msg.u8_data[1] |= 0x01; else if ((pt_bms->u16_timeout_flag & GB_BRO_TIMEOUT_FLAG) != 0) pt_msg.u8_data[1] |= 0x04; else if ((pt_bms->u16_timeout_flag & GB_BCS_TIMEOUT_FLAG) != 0) pt_msg.u8_data[2] |= 0x01; else if ((pt_bms->u16_timeout_flag & GB_BCL_TIMEOUT_FLAG) != 0) pt_msg.u8_data[2] |= 0x04; else if ((pt_bms->u16_timeout_flag & GB_BST_TIMEOUT_FLAG) != 0) pt_msg.u8_data[2] |= 0x10; else if ((pt_bms->u16_timeout_flag & GB_BSD_TIMEOUT_FLAG) != 0) pt_msg.u8_data[3] |= 0x01; pt_bms->t_cem_data.u8_cem_data[0] = pt_msg.u8_data[0]; pt_bms->t_cem_data.u8_cem_data[1] = pt_msg.u8_data[1]; pt_bms->t_cem_data.u8_cem_data[2] = pt_msg.u8_data[2]; pt_bms->t_cem_data.u8_cem_data[3] = pt_msg.u8_data[3]; pt_bms->u8_cem_send_cnt ++; //cem发送次数加一 // BMS_LOG("CEM发送"); v_bms_tx(gunNo,&pt_msg); } //发送 void v_bmsComm_tx_handle(U8_T gunNo) { S_BMS_RT_DATA *pt_bms = &(s_bms_data.s_bms_rt_data[gunNo]); //bms static U8_T cst_cnt[GUN_MAX_CNT] = {0}; // pt_bms->e_state = GB_BMS_CFG_RX_BRO_AA; switch(pt_bms->e_state) { case GB_BMS_STOP: //空闲状态,无报文发送 { //清除底层的多包状态 v_sae1393_clear_multi_pacet(&s_bms_data.s_gb_bms_can[gunNo].pt_dll); break; } case GB_BMS_HANDSHAKE_TX_CHM: //握手启动阶段,发送CHM(协议版本V1.1),250ms { if(u8_tim_ret(gunNo,cnt250ms,BMS_TIM_250MS) == 0) break; v_bms_chm_send(gunNo); break; } case GB_BMS_HANDSHAKE_TX_CRM_00: //握手辨识阶段,发送CRM-0x00,250ms { if(u8_tim_ret(gunNo,cnt250ms,BMS_TIM_250MS) == 0) break; v_bms_crm_send(gunNo,0x00); break; } case GB_BMS_HANDSHAKE_TX_CRM_AA: //握手辨识阶段结束,等待BCP进行参数设置,发送CRM_0xAA,250ms { if(u8_tim_ret(gunNo,cnt250ms,BMS_TIM_250MS) == 0) break; v_bms_crm_send(gunNo,0xAA); break; } case GB_BMS_CFG_TX_CTS_CML: //参数配置阶段,收到BCP,发送CML(充电机最大输出能力)/CTS对时(可选,不在此处发送) case GB_BMS_CFG_RX_BRO_AA: //参数配置阶段,收到BRO-0xAA,发送CML, 250ms, CTS,500ms { if(u8_tim_ret(gunNo,cnt250ms,BMS_TIM_250MS) == 1) { v_bms_cml_send(gunNo); } if(u8_tim_ret(gunNo,cnt500ms,BMS_TIM_500MS) == 1) { v_bms_cts_send(gunNo); } break; } case GB_BMS_CFG_TX_CRO_00: //桩根据接收BMS数据开始预充电,CRO-0x00,250ms { if(u8_tim_ret(gunNo,cnt250ms,BMS_TIM_250MS) == 0) break; v_bms_cro_send(gunNo,0x00); break; } case GB_BMS_CFG_TX_CRO_AA: //参数配置阶段,预充完成,周期发送CRO-0xAA,250ms,等待BCL、BCS { if(u8_tim_ret(gunNo,cnt250ms,BMS_TIM_250MS) == 0) break; v_bms_cro_send(gunNo,0xAA); break; } case GB_BMS_CHARGE_STAGE: //充电中阶段,CCS,50ms { if(u8_tim_ret(gunNo,cnt50ms,BMS_TIM_50MS) == 0) break; v_bms_ccs_send(gunNo); break; } case GB_BMS_CHARGE_TX_CST: //充电机或充电桩停止充电,发送停止报文并等着接收BMS停止充电报文,发送CST 10ms,等待BST { if(cst_cnt[gunNo] ++ < 1) break; cst_cnt[gunNo] = 0; v_bms_cst_send(gunNo); break; } case GB_BMS_FINISH_RX_BSD: //收到BSD,发送CSD 250ms //充电机没有真正停机以前,还是要发充电状态报文,以保证在车的接触器断开时充电机己经停机 { if(u8_tim_ret(gunNo,cnt250ms,BMS_TIM_250MS) == 0) break; v_bms_csd_send(gunNo); break; } case GB_BMS_TX_CEM: //检测到报文超时 发送cem { if(u8_tim_ret(gunNo,cnt250ms,BMS_TIM_250MS)) //有错误且时间周期满足,即发送CEM { v_bms_cem_send(gunNo); } break; } default: break; } } #endif #if 1 //bms流程相关 /**************************************************** *功能说明: BMS变量控制状态跳转 *参数说明: * 输入参数: U8_T gunNo 枪号 * 输出参数: void *最后修改时间: 20230228 *修改内容: 20230228 第一次创建子函数 ****************************************************/ static void v_control_steate_jump(U8_T gunNo) { S_BMS_RT_DATA *gb_bms_data = &(s_bms_data.s_bms_rt_data[gunNo]); U8_T ctrl_state = u16_bms_get_sys_para(gunNo,E_BMS_GET_GUN_FIOW_CTRL); //获取BMS流程状态 0无意义 1空闲 2开始握手 3绝缘完成,开始握手辨识 4预充完成,发送cro_aa 5充电停止 发送cst 6停止充电完成 停止发送CSD 7BMS通讯超时 E_BMS_STOP_INFO e_stop_info = E_BMS_STOP_NULL; BMS_BHM_DATA_T t_bhm_save; if(ctrl_state == 2) //1 开始BMS握手启动阶段 { if(gb_bms_data->e_state == GB_BMS_STOP) //0空闲/停止充电 { BMS_LOG("BMS HS start\n"); memset(gb_bms_data, 0, sizeof(S_BMS_RT_DATA)); //参数清0 gb_bms_data->e_bms_standard = BMS_2015; v_set_flow_state(gunNo,GB_BMS_HANDSHAKE_TX_CHM); //跳转1 u8_tim_reset(gunNo,cnt_global); //计时更新,BHM超时计时 } else if ((s_bms_data.u8_gun_type[gunNo] == 0) && gb_bms_data->e_state == GB_BMS_HANDSHAKE_TX_CHM) //欧标:2收到BHM,可以做绝缘检测,等待绝缘检测成功后发送CRO-00 { //logMsg_bms("bms---开始握手辨识\n"); #if CAN_PLC_FLAG //欧标 CAN转PLC使能 if(gb_bms_data->t_bhm_data.u8_CR_Plc_Aagvalue != 0) //当CR_Plc_Aagvalue ≠0 时发送CRM -00 v_set_flow_state(gunNo,GB_BMS_HANDSHAKE_TX_CRM_00); //跳转3 #endif u8_tim_reset(gunNo,cnt_global); //计时更新,BRM超时计时 } else if(gb_bms_data->u8_reconn_flag == 1 && u16_bms_get_sys_para(gunNo,E_BMS_GET_GUN_FLOW_RENEW)) { e_stop_info = s_bms_data.s_bms_rt_data[gunNo].e_stop_info; //重连清空前保存 bms超时原因 t_bhm_save = gb_bms_data->t_bhm_data; memset(&s_bms_data.s_bms_rt_data[gunNo], 0, sizeof(S_BMS_RT_DATA)); //参数清0 s_bms_data.s_bms_rt_data[gunNo].e_stop_info = e_stop_info; gb_bms_data->t_bhm_data = t_bhm_save; v_set_flow_state(gunNo,GB_BMS_HANDSHAKE_TX_CRM_00); //跳转3 u8_tim_reset(gunNo,cnt_global); //计时更新,BRM超时计时 v_set_rt_state(gunNo, BMS_STATE_HANDSHAKE_START_OK); //bms状态?? u16_bms_get_sys_para(gunNo,E_BMS_CLEAR_GUN_FLOW_RENEW); //清空重连标志 gb_bms_data->u8_reconn_flag = 0; //重连标识置0 BMS_LOG("BMS reconn, HS ident\n"); } } else if (!(s_bms_data.u8_gun_type[gunNo] == 0) && ctrl_state == 3) //国标:2 开始BMS握手辨识阶段 { if(gb_bms_data->e_state == GB_BMS_HANDSHAKE_TX_CHM) //2收到BHM,可以做绝缘检测,等待绝缘检测成功后发送CRO-00 { BMS_LOG("BMS HS ident\n"); v_set_flow_state(gunNo,GB_BMS_HANDSHAKE_TX_CRM_00); //跳转3 u8_tim_reset(gunNo,cnt_global); //计时更新,BRM超时计时 } else if(gb_bms_data->u8_reconn_flag == 1 && u16_bms_get_sys_para(gunNo,E_BMS_GET_GUN_FLOW_RENEW)) { e_stop_info = s_bms_data.s_bms_rt_data[gunNo].e_stop_info; //重连清空前保存 bms超时原因 t_bhm_save = gb_bms_data->t_bhm_data; memset(&s_bms_data.s_bms_rt_data[gunNo], 0, sizeof(S_BMS_RT_DATA)); //参数清0 s_bms_data.s_bms_rt_data[gunNo].e_stop_info = e_stop_info; gb_bms_data->t_bhm_data = t_bhm_save; v_set_flow_state(gunNo,GB_BMS_HANDSHAKE_TX_CRM_00); //跳转3 u8_tim_reset(gunNo,cnt_global); //计时更新,BRM超时计时 v_set_rt_state(gunNo, BMS_STATE_HANDSHAKE_START_OK); //bms状态?? u16_bms_get_sys_para(gunNo,E_BMS_CLEAR_GUN_FLOW_RENEW); //清空重连标志 gb_bms_data->u8_reconn_flag = 0; //重连标识置0 BMS_LOG("BMS reconn, HS ident\n"); } } else if(ctrl_state == 4) //3 启动充电 { if(gb_bms_data->e_state == GB_BMS_CFG_TX_CRO_00) //7收到BRO-aa,发送CRO-00,等待允许发送cro-aa { BMS_LOG("BMS start chg\n"); v_set_flow_state(gunNo,GB_BMS_CFG_TX_CRO_AA); //跳转8 u8_tim_reset(gunNo,cnt_global); u8_tim_reset(gunNo,cnt_bcl); //没通信前设置未允许充电 s_bms_data.s_bms_rt_data[gunNo].t_bsm_data.u16_batt_state |= (1<<8); //BSM-允许充电 } } else if(ctrl_state == 5) //4 充电机停机,发送CST { if(gb_bms_data->e_state == GB_BMS_HANDSHAKE_TX_CHM) //0空闲/停止充电 { memset(&s_bms_data.s_bms_rt_data[gunNo], 0, sizeof(S_BMS_RT_DATA)); v_set_flow_state(gunNo,GB_BMS_STOP); BMS_LOG("BMS HS stage CST req, reset\n"); } else if((gb_bms_data->e_state != GB_BMS_STOP) && //除了空闲及发送错误帧状态 (gb_bms_data->e_state != GB_BMS_CHARGE_TX_CST) && (gb_bms_data->e_state != GB_BMS_FINISH_RX_BSD) && (gb_bms_data->e_state != GB_BMS_TX_CEM) ) { BMS_LOG("BMS st=%d, CST cmd rx\n", gb_bms_data->e_state); v_set_bms_stop_info(gunNo,E_BMS_STOP_1001); //v_gb_bms_CST_stopReason(); //填充CST停止原因 v_set_flow_state(gunNo,GB_BMS_CHARGE_TX_CST); //跳转11 u8_tim_reset(gunNo,cnt_global); u8_tim_reset(gunNo,cnt_bcl); } } else if(ctrl_state == 1 || ctrl_state == 6) { if(gb_bms_data->e_state != GB_BMS_STOP) { BMS_LOG("Idle, st reset\n"); v_set_flow_state(gunNo,GB_BMS_STOP); //跳转3 } memset(gb_bms_data, 0, sizeof(S_BMS_RT_DATA)); //参数清0 } //bcs bcl都接收到了 进入充电中 if((gb_bms_data->u8_bms_rx_flag[4] == 1) && (gb_bms_data->u8_bms_rx_flag[5] == 1)) { if(gb_bms_data->e_state == GB_BMS_CFG_TX_CRO_AA) { v_set_rt_state(gunNo, BMS_STATE_CHARGING); //bms状态转10,充电中 v_set_flow_state(gunNo,GB_BMS_CHARGE_STAGE); //转充电中 s_bms_data.s_bms_rt_data[gunNo].e_stop_info = E_BMS_STOP_NULL; //进入到充电 bms故障原因就为0 避免在启动时的故障 BMS_LOG("BCS+BCL rx, enter chg\n"); } } } #endif #if 1 //数据初始化 /** * ************************************************************************ * @brief - BMS 任务数据初始化 * * * * @author jiankalka * @date 2025-08-13 * ************************************************************************ */ static void v_bms_data_init() { memset(&s_bms_data, 0, sizeof(S_BMS_DATA)); s_bms_data.s_gb_bms_can[0].pt_dll.u32_can_tx = u32_bms1_can_tx; s_bms_data.s_gb_bms_can[0].pt_dll.u32_can_rx = u32_bms1_can_rx; s_bms_data.s_bms_rt_data[0].e_state = GB_BMS_STOP; s_bms_data.s_bms_rt_data[0].e_bms_standard = BMS_2015; s_bms_data.s_gb_bms_can[1].pt_dll.u32_can_tx = u32_bms2_can_tx ; s_bms_data.s_gb_bms_can[1].pt_dll.u32_can_rx = u32_bms2_can_rx; s_bms_data.s_bms_rt_data[1].e_state = GB_BMS_STOP; s_bms_data.s_bms_rt_data[1].e_bms_standard = BMS_2015; s_bms_data.u8_gunCnt = u16_bms_get_sys_para(0,E_BMS_GET_PARA_GUN_CNT); //获取枪数量 memcpy(s_bms_data.u8_gun_type, g_t_share_data.t_sys_fix_cfg.u8_gun_type, GUN_MAX_CNT); //枪类型 0欧标 1国标 } #endif void v_bms_task(void *arg) { uint16_t sleep_time_ms; uint32_t last_send_time; uint32_t current_time; uint8_t gunNo; (void)arg; (void)BMS_LOCK_INIT(); sleep_time_ms = BMS_SLEEP_TIME_MS(); last_send_time = get_current_seconds(); v_bms_data_init(); for (;;) { BMS_FEED_DOG(); current_time = get_current_seconds(); if ((TASK_RUN_PRINT_TIME != 0U) && (u32_safe_seconds_since(last_send_time) >= TASK_RUN_PRINT_TIME)) { if (BMS_LOCK_TAKE() == 1U) { BMS_LOG("bms task is runing, sleep time is %ums", sleep_time_ms); (void)BMS_LOCK_GIVE(); } last_send_time = current_time; } for(gunNo=0; gunNo