GBT 27930-2015电动汽车非车载传导式充电机与电池管理系统之间的通信协议(mgq)
使用GD32F30X系列编写适用于GBT 27930-2015的充电协议适用的代码,具体代码如下:
uint8_t gBCP_message[13]={0,0,0,0,0,0,0,0,0,0,0,0,0};
uint8_t gBCS_message[9]={0,0,0,0,0,0,0,0,0};
//-------------软件定时器和计时器
uint8_t bBMS10msCnt = 0;
uint8_t bBMS1sCnt = 0;
uint8_t bBmsState = 0;
//Timeout判断定时器,=0不运行,=1启动,>6/11/31/61/101超出Timeout
uint8_t bStart5sTime = 0;
uint8_t bStart10sTime = 0;
uint8_t bStart30sTime = 0;
uint8_t bStart60sTime = 0;
uint8_t bStart1sTime = 0;
//定时器相关
//5s
void Timer5sStart(void);
uint8_t Timer5sOut(void);
void Timer5sClear(void);
//10s
void Timer10sStart(void);
uint8_t Timer10sOut(void);
void Timer10sClear(void);
//30s
void Timer30sStart(void);
uint8_t Timer30sOut(void);
void Timer30sClear(void);
//60s
void Timer60sStart(void);
uint8_t Timer60sOut(void);
void Timer60sClear(void);
//1s
void Timer1sStart(void);
uint8_t Timer1sOut(void);
void Timer1sClear(void);
///********************
//模块内的局部函数
//*********************/
uint8_t tmpCSTAfterBST = 0;
uint8_t tmpTP1250ms = 0;
uint8_t tmpTP1050ms = 0;
uint8_t tmpCTSCMLGet = 0;
uint8_t tmpCRM00Err =0;
uint8_t tmpCRMAAErr =0;
uint8_t tmpCTSorCMLErr = 0;
uint8_t tmpCROErr = 0;
uint8_t tmpCCSErr = 0;
uint8_t tmpCSTErr = 0;
uint8_t tmpCSDErr = 0;
/**
*多包传输控制
*/
void TP_Send(void)
{
if(bTPPGN!=0)
{
tmpTP1250ms++;
if(gTPMmgNum2 == 0)
tmpTP1050ms++;
if(gTPENDGet==1)
{ //传输结束
tmpTP1050ms = 0;
tmpTP1250ms = 0;
bTPPGN = 0;
gTPCTSGet = 0;
gTPENDGet = 0;
}
if(gTPCTSGet==1)
{ //传输准备开始
//如果要传送第1个包开始的2个包,则过程如下:
//中断中,设置bTPMmgTime = 1-1 =0;
//第一次CAN_TP_SEND();传送第1个包[0],bTPMmgTime++ =1
//第二次CAN_TP_SEND();传送第2个包[1],bTPMmgTime++ =2
//结束:bTPMmgTime == (1 + 2 -1 =2)
if(gTPMmgNum2 == 0)
{
gTPCTSGet=0;
}
else
{
CAN_TP_SEND(); //10ms,TP数据发送周期
if((gTPMmgStart+gTPMmgNum2-1)==bTPMmgTime)
{ // 该CTS发送结束
gTPCTSGet=0;
}
}
tmpTP1050ms = 0;
tmpTP1250ms = 0; //重新开始150ms定时
}
if(tmpTP1250ms >= 125)
{
//置错误标值,怎么处理TP传送错误
tmpTP1250ms = 0;
bTPPGN = 0;
gTPCTSGet = 0;
gTPENDGet = 0;
}
if(tmpTP1050ms >= 105)
{
//置错误标值,怎么处理TP传送错误
tmpTP1050ms = 0;
bTPPGN = 0;
gTPCTSGet = 0;
gTPENDGet = 0;
}
}
}
void Charger_Timer(void)
{
if(STATE_IDLE != gBmsState)
{
//------------这些时间更新是否安排到定时器中更合适,不受状态改变影响
if(bStart1sTime > 0)
bStart1sTime++;
bBMS10msCnt++;
if(bBMS10msCnt >= 100)
{
bBMS10msCnt = 0;
bBMS1sCnt++;
if(bBMS1sCnt==50)
bBMS1sCnt = 0; //50s
if(bStart5sTime > 0)
bStart5sTime ++ ;
if(bStart10sTime > 0)
bStart10sTime ++ ;
if(bStart30sTime > 0)
bStart30sTime ++ ;
if(bStart60sTime > 0)
bStart60sTime ++ ;
}
}
}
void GB27930_SEND(void)
{
//用来控制报文刷新周期-------状态改变时,重新开始计时
if(bBmsState!=gBmsState)
{
bBmsState = gBmsState;
bBMS10msCnt = 0;
bBMS1sCnt = 0;
bStart1sTime = 0;
bStart5sTime = 0;
bStart10sTime = 0;
bStart30sTime = 0;
bStart60sTime = 0;
}
//TP传输和普通传输互不干扰,在每个10ms周期,先执行剩余的TP任务,之后进行对应的阶段
TP_Send();
//------------------------------TP传输----参考SAE J1939-------------------------
//BMS状态
switch(gBmsState)
{
case STATE_IDLE:
bBMS10msCnt = 0;
if(gCHMGet==1)
gBmsState = STATE_START; //调试要求(和标准不一样):收到CHM之后,才开始CAN协议流程
break;
case STATE_START: //系统启动(必须)
Timer5sStart(); //系统启动5s后跳过CHM计时
Timer60sStart(); //CRM超时计时
if(gCHMGet==1)
{
bStart30sTime = 1; //30sTimeout //每次收到CHM都重新开始30s计时
gBmsState = STATE_HAND_SHK;
gCHMGet = 0;
break;
}
//没有收到CHM。但在系统启动5s后,或者收到CRM后后,跳过发送BHM,进入下一个阶段
if(bStart5sTime > 6)
{
bStart5sTime = 0;
gBmsState = STATE_RECOG;
break;
}
if(gCRM00Get==1)
{
bStart5sTime = 0;
bStart60sTime = 0;
bStart30sTime = 0;
gBmsState = STATE_RECOG;
gCRM00Get = 0;
break;
}
break;
case STATE_HAND_SHK://充电握手
//每次收到CHM 30s后或者系统启动(必须)60s后,没有收到CRM,则充电时序结束,故障级别3
if((bStart60sTime > 61)||(bStart30sTime > 31))
{
gBmsState = STATE_FAULT;
tmpCRM00Err = 1;
bStart60sTime = 0;
bStart30sTime = 0;
gCRM00Get = 0;
gCHMGet = 0;
break;
}
if(gCRM00Get==1)
{
bStart60sTime = 0;
bStart30sTime = 0;
gBmsState = STATE_RECOG;
gCRM00Get = 0;
break;
}
if(gCHMGet==1)
{
bStart30sTime = 1; //每次收到CHM都重新开始30s计时
gCHMGet = 0;
}
if(bBMS10msCnt%25==0)
CAN_BHM_SEND(); //周期250ms,发送车辆握手报文
break;
case STATE_RECOG: //BRM发送后,5s未接收到CRMAA,则错误//充电辨识
if(gCRMAAGet==1)
{
gBmsState = STATE_CONFIGURE; //参数配置
bStart5sTime = 0; //5sTimeout
gCRMAAGet = 0;
break;
}
if(bStart5sTime > 6)
{ //5sTimeout
gBmsState = STATE_FAULT;
tmpCRMAAErr = 1;
bStart5sTime = 0;
break;
}
//---TP传输-------------------
if(bBMS10msCnt % 25==0)
{
if(bTPPGN==0)
{
CAN_BRM_TP_START(); //周期250ms,发送BMS和车辆辨识报文
Timer5sStart(); //开始发送BRM,启动5s定时(需要修改成,发送BRM成功后吗?)
}
}
break;
case STATE_CONFIGURE: //参数配置, CTS是可选的。
if(gCMLGet==0)
{
//---TP传输---------------
if(bStart5sTime > 6)
{ //5sTimeout
tmpCTSorCMLErr = 1;
gBmsState = STATE_FAULT;
gCMLGet = 0;
gCTSGet = 0;
gCRM00Get = 0;
gCRMAAGet = 0;
bStart5sTime = 0;
break;
}
if(bBMS10msCnt%50==0)
{
if(bTPPGN==0)
{
CAN_BCP_TP_START(); //参数配置阶段发送报文
Timer5sStart();
}
}
}
else
{
//A1
if(tmpCTSCMLGet==0)
{ //第一次收到CML,或者CTS和CML
bStart5sTime = 0; //停止(gCMLGet==0)||(gCTSGet==0)期间的5s定时器
tmpCTSCMLGet = 1;
//判断充电机参数能否进行充电
if(!gCMLGOOD)
{ //如果参数不合适
gCMLGet=0;
gCTSGet=0;
tmpCTSCMLGet=0;
if(bBMS10msCnt%25==0)
CAN_BRO_SEND(0x00);
break;
}
}
if(gCROGet==1)
{
bStart5sTime = 0; //停止后,在下次发送BRO AA时,被再次启动
}
if(gCROGOOD==1)
{ //5s定时在前面代码已经被关闭
gBmsState = STATE_CHARGE;
bStart60sTime = 0;
gCROGOOD = 0;
gCMLGet = 0;
break;
}
if(bStart5sTime > 6)
{
gBmsState = STATE_FAULT;
tmpCROErr = 1;
gCMLGet = 0;
bStart5sTime = 0;
bStart60sTime = 0;
break;
}
if(bStart60sTime > 61)
{
gBmsState = STATE_FAULT;
tmpCROErr =1;
gCMLGet = 0;
bStart5sTime = 0;
bStart60sTime = 0;
break;
}
if(bBMS10msCnt%25==0)
{ //电机参数合适,则发送BROAA,等待CROAA。
Set_HSD_Ctrlx(HSD3);
CAN_BRO_SEND(0xAA);
Timer5sStart();
Timer60sStart();
}
}
break;
case STATE_CHARGE: //充电阶段
if(gCCSGet==1)
{
协议要求自上次接收到报文起开始1s定时,
gCCSGet=0;
bStart1sTime = 1; //定时器重新启动
}
if(bStart1sTime > 101)
{ //定时器在1s内没接收到CCS,发生错误。
gBmsState = STATE_FAULT;
tmpCCSErr = 1;
gCCSGet = 0;
bStart1sTime = 0;
break;
}
if((gCSTGet==1)&&(tmpCSTAfterBST==1))
{
//判断是否满足充电结束条件
gBmsState = STATE_CHARGE_END;
bStart1sTime = 0;
bStart5sTime = 0;
//不停止10s定时器
break;
}
if(bStart5sTime > 6)
{ //发送BST后,5s内没收到CST,标准中A1和A2处理不同,这里按照A1,作为充电错误。
gBmsState = STATE_FAULT;
tmpCSTErr = 1;
bStart5sTime = 0;
tmpCSTAfterBST = 0;
gSTOPCharge = 0;
gCSTGet = 0;
break;
}
//----------------------------
if(bBMS10msCnt%5==0)
CAN_BCL_SEND(); //50ms,充电总需求报文
//---TP传输-------------------
if(bBMS10msCnt%25==1)
{
if(bTPPGN==0)
{
CAN_BCS_TP_START(); //250ms,电池充电总状态报文,错开上一个报文
}
}
//充电器在接收到BCL和BCS后,开始发送CCS
Timer1sStart(); //等待CCS,启动1s定时器。定时器的启动是在第一次收到CCS前还是后?
//以下几个报文需要修改成收到第一个CCS报文再开启发送
if(bBMS10msCnt%25==6)
CAN_BSM_SEND();
//-----------------TP传输
//可选的三个报文,较长,发一次多长时间
if(bBMS1sCnt%10==3)
{
if(bTPPGN==0)
{
// CAN_BMV_TP_START();
}
}
else if(bBMS1sCnt%10==5)
{
if(bTPPGN==0)
{
// CAN_BMT_TP_START();
}
}
else if(bBMS1sCnt%10==7)
{
if(bTPPGN==0)
{
// CAN_BSP_TP_START();
}
}
//判断是否需要中止充电,
// 1、由BMS其它模块程序控制。1)正常结束、2)故障结束
// 2、收到充电器CST报文
//该段程序需要调整到前面去吗?
//发送BST之后,要停止发送BCL、BCS、BSM、BMV、BMT、BSP
if(/*(ONC_stop==1)||*/(gCSTGet=1))
{
CAN_BST_SEND(); //10ms调用1次? //--中止充电原因报文
tmpCSTAfterBST=1;
Timer5sStart(); //第一次发送BST后,等待下一次CST,5s内。
bStart10sTime = 1; //最后一次发送BST后,检测电流是否为5A以下,10s内。
}
break;
case STATE_CHARGE_END: //结束阶段
if(bStart10sTime > 11)
{
gBmsState = STATE_FAULT;
tmpCSDErr = 1;
break;
}
if(gCSDGet==1)
{
gBmsState = STATE_POWER_OFF;
bStart10sTime = 0;
gCSTGet = 0;
gCSDGet = 0;
break;
}
if(bBMS10msCnt%25==0)
CAN_BSD_SEND(); //PGN7168统计数据(电压、温度最值)
break;
case STATE_POWER_OFF: //系统休眠
gBmsState = STATE_IDLE; //调试需求,准备开始下一次测试
gCHMGet=0;
gCRM00Get=0;
gCRMAAGet=0;
gCTSGet = 0;
gCMLGet = 0;
gCMLGOOD =0;
gCROGet = 0;
gCROGOOD =0;
gCCSGet = 0;
gCSTGet = 0;
gCSDGet = 0;
gTPCTSGet =0;
gTPENDGet =0;
bStart1sTime = 0;
bStart5sTime = 0;
bStart10sTime = 0;
bStart30sTime = 0;
bStart60sTime = 0;
break;
case STATE_FAULT: //错误报文,需要进一步考虑,同时还要需要在第一次进入前,清零全局变量和计时器等。
if(gCRM00Get==1)
gBmsState = STATE_RECOG; //充电辨识
if(gCRMAAGet==1)
gBmsState = STATE_CONFIGURE; //参数配置
if(bBMS10msCnt%25==0)
CAN_BEM_SEND();
break;
//异常情况
case Abnormal_CCS: //非正常状态下停止(充电机方面的原因)
if(gCSTGet==1)
{ //重新收到CST报文
Timer10sStart();
}
if(bStart10sTime > 11)
{
gBmsState = STATE_FAULT;
break;
}
if(gCSDGet==1)
{
gBmsState = STATE_POWER_OFF;
bStart10sTime = 0;
gCSTGet = 0;
//系统休眠
break;
}
//断开车辆DC继电器
break;
case STATE_BMS_FAULT: //BMS接收报文超时,只在cansend.c中进行判断
break;
default:
break;
}
}
//-----------各个报文的具体内容-------------
//-----------握手阶段-------------
void CAN_BHM_SEND(void)
{
can_trasnmit_message_struct TxMsg;
_BMS_BHM_CONTEXT *BMS_BHM_Msg;
BMS_BHM_Msg = (_BMS_BHM_CONTEXT *)TxMsg.tx_data;
memset(BMS_BHM_Msg,0xff,sizeof(_BMS_BHM_CONTEXT));
BMS_BHM_Msg->MaxChargeWholeVol = sysDataStru.V_total;
TxMsg.tx_dlen = 8;
TxMsg.tx_ft = CAN_FT_DATA;
TxMsg.tx_ff = CAN_FF_EXTENDED;
TxMsg.tx_efid = BHM_CANID;
can_message_transmit(CAN1,&TxMsg);
}
void CAN_BRM_TP_START(void) //开始发送BMS和车辆辨识报文
{
can_trasnmit_message_struct TxMsg;
TxMsg.tx_data[0]=0x10;
TxMsg.tx_data[1]=49;
TxMsg.tx_data[2]=0;
TxMsg.tx_data[3]=7;
TxMsg.tx_data[4]=0xFF;
TxMsg.tx_data[5]=0;
TxMsg.tx_data[6]=BRM_PGN; // //数据字节41
TxMsg.tx_data[7]=0;
TxMsg.tx_dlen = 8;
TxMsg.tx_ft = CAN_FT_DATA;
TxMsg.tx_ff = CAN_FF_EXTENDED;
TxMsg.tx_efid = TP_START_CANID;
can_message_transmit(CAN1,&TxMsg);
gBRM_message[4] = (uint8_t)(SysParamStru.Rated01AH); //整车电池容量
gBRM_message[5] = (uint8_t)(SysParamStru.Rated01AH>>8);
gBRM_message[6] = (uint8_t)SysParamStru.VpMax_ChgTHD; //额定总电压
gBRM_message[7] = (uint8_t)(SysParamStru.VpMax_ChgTHD>>8);
bTPPGN = TxMsg.tx_data[6];
bTPuint8_tNum = TxMsg.tx_data[1]; //如果有数据大于255,则需要使用word
bTPMmgNum = TxMsg.tx_data[3]; //报文的数据帧数目,如7
bTPMmgTime = 0;
}
//-----------参数配置阶段
void CAN_BCP_TP_START(void)
{ //500ms,发送电池充电参数配置,13个数据,需要2个数据包。
gBCP_message[0] = (uint8_t)(SysParamStru.Vcell_OverPretTHD*10);//0.01V //单体过压保护门限mV
gBCP_message[1] = (uint8_t)(SysParamStru.Vcell_OverPretTHD*10>>8);
gBCP_message[2] = (uint8_t)(4000-SysParamStru.Ip_ChgCutTHD/10);// 0.1A //允许充电最大电流切断值 0.1A
gBCP_message[3] = (uint8_t)((4000-SysParamStru.Ip_ChgCutTHD/10)>>8);
gBCP_message[4] = (uint8_t)(SysParamStru.Rated01KWh); //标称总容量
gBCP_message[5] = (uint8_t)(SysParamStru.Rated01KWh>>8);
gBCP_message[6] = (uint8_t)(SysParamStru.VpMax_ChgTHD); //允许充电最大电压
gBCP_message[7] = (uint8_t)(SysParamStru.VpMax_ChgTHD>>8);
gBCP_message[8] = (uint8_t)(SysParamStru.Tbalance_OverPretTHD); //均衡过温保护门限℃
gBCP_message[9] = (uint8_t)(sysDataStru.SOC/10);
gBCP_message[10]= (uint8_t)((sysDataStru.SOC/10)>>8);
gBCP_message[11]= (uint8_t)(sysDataStru.V_total);
gBCP_message[12]= (uint8_t)(sysDataStru.V_total>>8);
can_trasnmit_message_struct TxMsg;
TxMsg.tx_data[0]=0x10;
TxMsg.tx_data[1]=13;
TxMsg.tx_data[2]=0;
TxMsg.tx_data[3]=2;
TxMsg.tx_data[4]=0xFF;
TxMsg.tx_data[5]=0;
TxMsg.tx_data[6]=BCP_PGN; //数据字节13
TxMsg.tx_data[7]=0;
TxMsg.tx_dlen = 8;
TxMsg.tx_ft = CAN_FT_DATA;
TxMsg.tx_ff = CAN_FF_EXTENDED;
TxMsg.tx_efid = TP_START_CANID;
can_message_transmit(CAN1,&TxMsg);
bTPPGN = TxMsg.tx_data[6];
bTPuint8_tNum = TxMsg.tx_data[1];
bTPMmgNum = TxMsg.tx_data[3];
bTPMmgTime = 0;
}
void CAN_BRO_SEND(uint8_t da) //看充电机是否合适
{
can_trasnmit_message_struct TxMsg;
memset(TxMsg.tx_data,0xff,8);
TxMsg.tx_data[0] = da;
TxMsg.tx_dlen = 8;
TxMsg.tx_ft = CAN_FT_DATA;
TxMsg.tx_ff = CAN_FF_EXTENDED;
TxMsg.tx_efid = BRO_CANID;
can_message_transmit(CAN1,&TxMsg);
}
uint8_t tmp50msTime=0;
void CAN_BCL_SEND(void) //50ms调用一次,200次后,10s。充电总需求报文(电压、电流、充电方式)
{
can_trasnmit_message_struct TxMsg;
TxMsg.tx_data[0] = 00;
TxMsg.tx_data[1] = 0x32;
TxMsg.tx_data[2]=(uint8_t)(4000-20); //充电机最高允许充电电流(单位0.1A)高字节
TxMsg.tx_data[3]=(uint8_t)((4000-20)>>8);
TxMsg.tx_data[4] = 0x02; //01恒压充电 02恒流充电
TxMsg.tx_dlen= 5;
TxMsg.tx_ft = CAN_FT_DATA;
TxMsg.tx_ff = CAN_FF_EXTENDED;
TxMsg.tx_efid = BCL_CANID;
can_message_transmit(CAN1,&TxMsg);
}
void CAN_BCS_TP_START(void) //电池充电总状态报文
{
can_trasnmit_message_struct TxMsg;
uint16_t temp;
gBCS_message[0] = (uint8_t)(sysDataStru.V_total/1000); //要求充电电压测量值
gBCS_message[1] = (uint8_t)((sysDataStru.V_total/1000)>>8);
gBCS_message[2] = (uint8_t)(4000-sysDataStru.I_system); //要求充电电流测量值
gBCS_message[3] = (uint8_t)((4000-sysDataStru.I_system)>>8);
gBCS_message[4] = (uint8_t)(Cmd7B1QuerySystemACK.Vmax_Cell/100);
gBCS_message[5] = (uint8_t)(((Cmd7B1QuerySystemACK.Vmax_Cell/100>>8)&0x0F)|0x10); //组号暂时设置为1
gBCS_message[6] = (uint8_t)sysDataStru.SOC/10; //菏电状态
temp = SysParamStru.Rated01AH*(100 - sysDataStru.SOC/10)*60/10*sysDataStru.I_system;
if(temp > 600)
temp = 600;
gBCS_message[7] = (uint8_t)temp; //估计剩余充电时间,unit:minute
gBCS_message[8] = (uint8_t)(temp>>8);
TxMsg.tx_data[0]=0x10;
TxMsg.tx_data[1]=9;
TxMsg.tx_data[2]=0;
TxMsg.tx_data[3]=2;
TxMsg.tx_data[4]=0xFF;
TxMsg.tx_data[5]=0;
TxMsg.tx_data[6]=BCS_PGN;
TxMsg.tx_data[7]=0;
TxMsg.tx_dlen = 8;
TxMsg.tx_ft = CAN_FT_DATA;
TxMsg.tx_ff = CAN_FF_EXTENDED;
TxMsg.tx_efid = TP_START_CANID;
can_message_transmit(CAN1,&TxMsg);
bTPPGN = TxMsg.tx_data[6];
bTPuint8_tNum = TxMsg.tx_data[1];
bTPMmgNum = TxMsg.tx_data[3];
bTPMmgTime = 0;
}
void CAN_BSM_SEND(void) // 充电机充电状态报文ccs
{
can_trasnmit_message_struct TxMsg;
TxMsg.tx_data[0] = 1; //假定1
TxMsg.tx_data[1] = Cmd7B2QueryLECUACK.Tmax_Cell/10 + TMP_OFFSET_GB27930; //电压输出值
TxMsg.tx_data[2] = 1; //
TxMsg.tx_data[3] = Cmd7B2QueryLECUACK.Tmin_Cell/10 + TMP_OFFSET_GB27930; //电流输出值
TxMsg.tx_data[4] = 2; //假定2
TxMsg.tx_data[5] = 0x00; //累计充电时间
TxMsg.tx_data[6] = 0x01<<4; //允许充放/禁止充电
TxMsg.tx_dlen = 8;
TxMsg.tx_ft = CAN_FT_DATA;
TxMsg.tx_ff = CAN_FF_EXTENDED;
TxMsg.tx_efid = BSM_CANID;
can_message_transmit(CAN1,&TxMsg);
}
void CAN_BST_SEND(void) //--中止充电原因报文
{
can_trasnmit_message_struct TxMsg;
_BMS_BST_CONTEXT *BMS_BST_Msg;
BMS_BST_Msg = (_BMS_BST_CONTEXT *)TxMsg.tx_data;
memset(BMS_BST_Msg,0xff,sizeof(_BMS_BST_CONTEXT));
if(1)//(ONC_stop==1)//电压达到设定值
BMS_BST_Msg->State0.OneByte.VolSetValBits = 1;
else if(gCSTGet==1)
BMS_BST_Msg->State0.OneByte.ChargeStopBits = 1;
BMS_BST_Msg->State1.EndChargeTroubleReason = 0x00;
BMS_BST_Msg->State2.EndChargeErroReason = 0x00;
TxMsg.tx_dlen = 4;
TxMsg.tx_ft = CAN_FT_DATA;
TxMsg.tx_ff = CAN_FF_EXTENDED;
TxMsg.tx_efid = BST_CANID;
can_message_transmit(CAN1,&TxMsg);
}
//------------充电结束阶段
void CAN_BSD_SEND(void) //PGN7168统计数据(电压、温度最值)
{
can_trasnmit_message_struct TxMsg;
_BMS_BSD_CONTEXT *BMS_BSD_Msg;
BMS_BSD_Msg = (_BMS_BSD_CONTEXT *)TxMsg.tx_data;
memset(BMS_BSD_Msg,0xff,sizeof(_BMS_BSD_CONTEXT));
BMS_BSD_Msg->EndChargeSOC = sysDataStru.SOC/10;
BMS_BSD_Msg->UnitBatteryminVol = Cmd7B1QuerySystemACK.Vmax_Cell; // 最低单体电压值
BMS_BSD_Msg->UnitBatteryMaxVol = Cmd7B1QuerySystemACK.Vmax_Cell; // 最高单体电压值
BMS_BSD_Msg->BatteryMinTemp = Cmd7B2QueryLECUACK.Tmax_Cell/10 + TMP_OFFSET_GB27930; //最低温度值/10+50
BMS_BSD_Msg->BatteryMaxTemp = Cmd7B2QueryLECUACK.Tmax_Cell/10 + TMP_OFFSET_GB27930; //最高温度值/10+50
TxMsg.tx_dlen = 8;
TxMsg.tx_ft = CAN_FT_DATA;
TxMsg.tx_ff = CAN_FF_EXTENDED;
TxMsg.tx_efid = BHM_CANID;
can_message_transmit(CAN1,&TxMsg);
}
//------------错误报文
void CAN_BEM_SEND(void)
{
can_trasnmit_message_struct TxMsg;
TxMsg.tx_data[0] = (tmpCRMAAErr<<2)|tmpCRM00Err;
TxMsg.tx_data[1] = (tmpCROErr<<2)|tmpCTSorCMLErr;
TxMsg.tx_data[2] = (tmpCSTErr<<2)|tmpCCSErr;
TxMsg.tx_data[3] = tmpCSDErr;
TxMsg.tx_dlen = 8;
TxMsg.tx_ft = CAN_FT_DATA;
TxMsg.tx_ff = CAN_FF_EXTENDED;
TxMsg.tx_efid = BEM_CANID;
can_message_transmit(CAN1,&TxMsg);
}
void CAN_TP_SEND(void) //------TP数据传输
{
//检测到CTS,马上开始传送,需要增加超时退出(250ms)
switch(bTPPGN)
{
case BRM_PGN: //数据字节
CAN_TP_SEND_DATA(gBRM_message);
break;
case BCP_PGN:
CAN_TP_SEND_DATA(gBCP_message);
break;
case BCS_PGN:
CAN_TP_SEND_DATA(gBCS_message);
break;
default:
break;
}
}
void CAN_TP_SEND_DATA(uint8_t data_str[])
{
uint8_t i;
can_trasnmit_message_struct TxMsg;
TxMsg.tx_dlen = 8;
TxMsg.tx_ft = CAN_FT_DATA;
TxMsg.tx_ff = CAN_FF_EXTENDED;
TxMsg.tx_efid = TP_DATA_CANID;
if(bTPMmgTime < (bTPMmgNum-1))
{
TxMsg.tx_data[0] = bTPMmgTime + 1; //索引
for(i=0;i<7;i++)
TxMsg.tx_data[i+1] = data_str[bTPMmgTime*7 + i];
can_message_transmit(CAN1,&TxMsg);
bTPMmgTime++;
}
else if(bTPMmgTime == (bTPMmgNum-1))
{
TxMsg.tx_data[0] = bTPMmgTime + 1;
if(0==(bTPuint8_tNum%7))
{
for(i=0;i<7;i++)
TxMsg.tx_data[i+1] = data_str[bTPMmgTime*7 + i];
}
else
{
for(i=0;i<bTPuint8_tNum%7;i++)
TxMsg.tx_data[i+1] = data_str[bTPMmgTime*7 + i];
for(;i<7;i++)
TxMsg.tx_data[i+1] = 0xff;
}
can_message_transmit(CAN1,&TxMsg);
bTPMmgTime++;
}
}
//5s定时器
void Timer5sStart(void)
{
if(bStart5sTime==0)
bStart5sTime = 1;
}
uint8_t Timer5sOut(void)
{
if(bStart5sTime > 6)
{
bStart5sTime = 7;
return 1;
}
else
return 0;
}
void Timer5sClear(void)
{
bStart5sTime = 0;
}
//10s定时器
void Timer10sStart(void)
{
if(bStart10sTime==0)
bStart10sTime = 1;
}
uint8_t Timer10sOut(void)
{
if(bStart10sTime > 11)
{
bStart10sTime = 12;
return 1;
}
else
return 0;
}
void Timer10sClear(void)
{
bStart10sTime = 0;
}
//30s定时器
void Timer30sStart(void)
{
if(bStart30sTime==0)
bStart30sTime = 1;
}
uint8_t Timer30sOut(void)
{
if(bStart30sTime > 31)
{
bStart30sTime = 32;
return 1;
}
else
return 0;
}
void Timer30sClear(void)
{
bStart30sTime = 0;
}
//60s定时器
void Timer60sStart(void)
{
if(bStart60sTime==0) bStart60sTime = 1;
}
uint8_t Timer60sOut(void)
{
if(bStart60sTime > 6)
{
bStart60sTime = 7;
return 1;
}
else
return 0;
}
void Timer60sClear(void)
{
bStart60sTime = 0;
}
//1s定时器
void Timer1sStart(void)
{
if(bStart1sTime==0)
bStart1sTime = 1;
}
uint8_t Timer1sOut(void)
{
if(bStart1sTime > 101)
{
bStart1sTime = 102;
return 1;
}
else
return 0;
}
void Timer1sClear(void)
{
bStart1sTime = 0;
}
GBT 27930-2015电动汽车非车载传导式充电机与电池管理系统之间的通信协议(mgq)相关推荐
- 充电桩用linux系统吗,电动汽车充电桩和电池在管理系统上有什么差别?
随着电动汽车充电桩的普及,给电动汽车消费者增加了很多便利,可是在使用的过程中也出现了一些问题.其中最重要的一项,就是需要充电桩的输出参数必须与电动车的电池参数匹配才能使用.所以越来越多的人就在考虑电动 ...
- 车载充电机与直流转换器
车载充电机 车载充电机是指固定安装在电动汽车上的充电机,具有为电动汽车动力电池,安全.自动充满电的能力,充电机依据电池管理系统(BMS)提供的数据,能动态调节充电电流或电压参数,执行相应的动作,完成充 ...
- 艾德克斯充电测试软件_艾德克斯车载充电机测试方案解析(图)
数据显示,2015年第一季度,在多重利好政策的刺激下,国内 车载充电机与BMS电池管理系统 充电机主要应用给电动汽车上的动力电池充电,按是否安装在车上,充电机可分为车载式(随车型)和固定式.固定式充电 ...
- 怎么调节电机启动值_开关式智能充电机-全自动充电机-铅酸电池充电机品牌-济南能华...
开关式智能充电机-全自动充电机-铅酸电池充电机品牌-济南能华NHCD系列 全自动智能充电机,可调智能充电机,可调直流充电机,可调全自动充电机 ,可调蓄电池充电机 便携式可调智能充电机 便携式全自动充电 ...
- 电动汽车车载充电机 (OBC) 与车载 DC/DC 转换器技术
电动汽车车载充电机 (OBC) 与车载 DC/DC 转换器技术 一.高性能电动汽车车载充电机(OBC) 电路 二.双向充电机(Bi-OBC )技术方案 三.车载DC/DC 转换器电路拓扑比较 四.充电 ...
- 新能源汽车车载双向OBC,PFC,LLC,V2G 双向 充电桩 电动汽车 车载充电机 充放电机 MATLAB仿真模型
新能源汽车车载双向OBC,PFC,LLC,V2G 双向 充电桩 电动汽车 车载充电机 充放电机 MATLAB仿真模型 : (1)基于V2G技术的双向AC/DC.DC/DC充放电机MATLAB仿真模型: ...
- 主题:快进式合并 和 非快进式合并
一.快进式合并 这是 Git 合并时候的默认选项.在 Git 中,分支进行合并的时候,如果能够采用快进(fast-forward, ff)方式合并,则会直接以快进方式合并,分支的提交历史没有 &quo ...
- AJAX框架衣柜内部改造,让衣柜鲜活起来 非拆改式租房改造案例赏析(图)
在外租住的房子,大的格局是不能改变的,中规中矩的环境显然无法满足人们对居室的个性需求,面对这个难题,中华衣柜网推荐4款非拆改式家居改造案例,可以实现常换常新,其中自己动手的衣柜设计,使家一直保持充满活 ...
- ! [已拒绝] dev - dev (非快进式)
拉取代码 git pull origin dev:dev 的时候报这种错误 ! [已拒绝] dev -> dev (非快进式) 可以这样解决,强制更新: git ...
最新文章
- 程序员常挂在嘴边的10句话:刚刚还是好的啊!
- html5自动旋转图片,HTML5画布旋转图片
- Windows 8 Directx 开发学习笔记(八)要有光
- paip.c++ 指针跟引用的区别.
- ai俄罗斯方块java,C#实现俄罗斯方块AI
- 基于Java的简单WebAPI接口调用(中国气象数据网接口调用示例)
- 【历史上的今天】10 月 11 日:域名 baidu.com 问世;三星 Galaxy Note 7 爆炸门告一段落;图灵奖数据库先驱诞生
- android 热修复阿里,Android热修复(阿里热修复)
- 路由交换技术实战七 FR 网络中配置 OSPF( 完成版 )
- rhel6 中安装使用finger命令
- Markdown入门指南
- 分数在c语言程序中怎么输入,如何在c语言中实现分数相加,以分数形式输出,并化为最简...
- 解开硬盘逻辑死锁的一种有效方法 (转)
- 2、mysql基本操作中
- html5 audio样式修改,HTML5中 audio的样式设置
- springboot2.0 的ssl证书配置
- NLP论文解读:无需模板且高效的语言微调模型(下)
- Mac Android 合作,干货:这个秘籍让笔记本同时拥有(mac/win/Android)系统
- 【译】创意编码之噪音
- 回顾苹果操作系统Mac OS的发展历史