使用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)相关推荐

  1. 充电桩用linux系统吗,电动汽车充电桩和电池在管理系统上有什么差别?

    随着电动汽车充电桩的普及,给电动汽车消费者增加了很多便利,可是在使用的过程中也出现了一些问题.其中最重要的一项,就是需要充电桩的输出参数必须与电动车的电池参数匹配才能使用.所以越来越多的人就在考虑电动 ...

  2. 车载充电机与直流转换器

    车载充电机 车载充电机是指固定安装在电动汽车上的充电机,具有为电动汽车动力电池,安全.自动充满电的能力,充电机依据电池管理系统(BMS)提供的数据,能动态调节充电电流或电压参数,执行相应的动作,完成充 ...

  3. 艾德克斯充电测试软件_艾德克斯车载充电机测试方案解析(图)

    数据显示,2015年第一季度,在多重利好政策的刺激下,国内 车载充电机与BMS电池管理系统 充电机主要应用给电动汽车上的动力电池充电,按是否安装在车上,充电机可分为车载式(随车型)和固定式.固定式充电 ...

  4. 怎么调节电机启动值_开关式智能充电机-全自动充电机-铅酸电池充电机品牌-济南能华...

    开关式智能充电机-全自动充电机-铅酸电池充电机品牌-济南能华NHCD系列 全自动智能充电机,可调智能充电机,可调直流充电机,可调全自动充电机 ,可调蓄电池充电机 便携式可调智能充电机 便携式全自动充电 ...

  5. 电动汽车车载充电机 (OBC) 与车载 DC/DC 转换器技术

    电动汽车车载充电机 (OBC) 与车载 DC/DC 转换器技术 一.高性能电动汽车车载充电机(OBC) 电路 二.双向充电机(Bi-OBC )技术方案 三.车载DC/DC 转换器电路拓扑比较 四.充电 ...

  6. 新能源汽车车载双向OBC,PFC,LLC,V2G 双向 充电桩 电动汽车 车载充电机 充放电机 MATLAB仿真模型

    新能源汽车车载双向OBC,PFC,LLC,V2G 双向 充电桩 电动汽车 车载充电机 充放电机 MATLAB仿真模型 : (1)基于V2G技术的双向AC/DC.DC/DC充放电机MATLAB仿真模型: ...

  7. 主题:快进式合并 和 非快进式合并

    一.快进式合并 这是 Git 合并时候的默认选项.在 Git 中,分支进行合并的时候,如果能够采用快进(fast-forward, ff)方式合并,则会直接以快进方式合并,分支的提交历史没有 &quo ...

  8. AJAX框架衣柜内部改造,让衣柜鲜活起来 非拆改式租房改造案例赏析(图)

    在外租住的房子,大的格局是不能改变的,中规中矩的环境显然无法满足人们对居室的个性需求,面对这个难题,中华衣柜网推荐4款非拆改式家居改造案例,可以实现常换常新,其中自己动手的衣柜设计,使家一直保持充满活 ...

  9. ! [已拒绝] dev - dev (非快进式)

    拉取代码 git pull origin dev:dev 的时候报这种错误 ! [已拒绝]          dev        -> dev  (非快进式) 可以这样解决,强制更新: git ...

最新文章

  1. 程序员常挂在嘴边的10句话:刚刚还是好的啊!
  2. html5自动旋转图片,HTML5画布旋转图片
  3. Windows 8 Directx 开发学习笔记(八)要有光
  4. paip.c++ 指针跟引用的区别.
  5. ai俄罗斯方块java,C#实现俄罗斯方块AI
  6. 基于Java的简单WebAPI接口调用(中国气象数据网接口调用示例)
  7. 【历史上的今天】10 月 11 日:域名 baidu.com 问世;三星 Galaxy Note 7 爆炸门告一段落;图灵奖数据库先驱诞生
  8. android 热修复阿里,Android热修复(阿里热修复)
  9. 路由交换技术实战七 FR 网络中配置 OSPF( 完成版 )
  10. rhel6 中安装使用finger命令
  11. Markdown入门指南
  12. 分数在c语言程序中怎么输入,如何在c语言中实现分数相加,以分数形式输出,并化为最简...
  13. 解开硬盘逻辑死锁的一种有效方法 (转)
  14. 2、mysql基本操作中
  15. html5 audio样式修改,HTML5中 audio的样式设置
  16. springboot2.0 的ssl证书配置
  17. NLP论文解读:无需模板且高效的语言微调模型(下)
  18. Mac Android 合作,干货:这个秘籍让笔记本同时拥有(mac/win/Android)系统
  19. 【译】创意编码之噪音
  20. 回顾苹果操作系统Mac OS的发展历史

热门文章

  1. 自动驾驶路径规划——Dijkstra算法
  2. 微商成交率低无客源怎么办?大咖这样做可以逆袭成功
  3. 给wordpress页面添加特色图也叫缩略图
  4. 【数据库】模式、内模式、数据库
  5. 拆解FPGA芯片,带你深入了解其原理
  6. Python对下周几本周几等进行中文日期解析
  7. 记录使用到的正则表达式
  8. NLP-机器学习-监督学习-回归
  9. 出海日本和美国市场的卡牌RPG,都是如何设计UI的?
  10. python之路day08--文件的操作