⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 charge.c

📁 Keil单片机软件开发平台下的一个51系列单片机工程
💻 C
📖 第 1 页 / 共 3 页
字号:
    }
    if (Jkmk.temp[24] == 1)
    {
        SetVoltaget();
        return;
    }
#endif
    
#ifdef HARD_XK
    Jkmk.temp[25] = step;
#endif

    switch (step)
    {
    case 0://floating charge
        //set voltage current limit
        ChargeTimerStop(3);         //停止均充保护计时器
        ChargeTimerStop(5);         //停止转均充延时计时器

        ChargeTimerPlay(2);         // 运行均充周期计时器
#ifdef HARD_XK
        X_SetChargeState(1);
        X_Charge();
#endif
        break;
    case 1://floating charge to equipoise charge
        //set voltage current limit
        ChargeTimerStart(5);        //启动转均充延时计时器
#ifdef HARD_XK
        X_SetChargeState(1);
#endif
        break;
    case 2://equipoise charge
        //set voltage current limit
        ChargeTimerStop(5);         //停止转均充延时计时器

        ChargeTimerStart(3);        //启动均充保护计时器
#ifdef HARD_XK
        X_SetChargeState(1);
#endif
        break;
    case 3://equipoise charge to floating charge
        //set voltage current limit
        ChargeTimerStart(4);        //启动稳流均充计时器
#ifdef HARD_XK
        X_SetChargeState(1);
#endif
        break;
    case 4://discharge power cut
        //启动停电计时器
        //set voltage current limit
        Jkmk.ao_cfg[0] = Jkmk.mk_cfg[6];
        break;
    case 5://batt test
        ChargeTimerStart(6);        //启动电池测试计时器
#ifdef HARD_XK
        X_SetChargeState(2);
        X_Discharge();
#endif
        break;
    case 6://IS STOP
#ifdef HARD_XK
        X_SetChargeState(0);
        X_Stop();
#endif
        break;
    }
    SetVoltaget();
}
/****************************************************************************/
void SetLimitI(int limit)
{
    long ltemp;
    Cha.i_limit = limit;
    Cha.i_rating = RatingCurrent();
    Cha.i_batt = Jkmk.ai_v[17];

    Cha.i_out = Jkmk.ai_v[7];
    Cha.i_outratio  = Jkmk.ao_cfg[1];
    if (Cha.i_batt > 0)
    {
        ltemp = (long)Cha.i_out * 1000 / Cha.i_rating;      //实际输出比率
        Cha.unit_p = (long)ltemp * 1000 / Cha.i_outratio;   //充电模块响应系数
        Jkmk.temp[31] = Cha.unit_p; //debug
        Cha.unit_p = 1200;
        if (Cha.i_da > 0)
        {
            Cha.unit_p = (long)Cha.i_out *1000 /Cha.i_da;
        }
        else
        {
            Cha.unit_p = 1000;
        }
    }
    else
    {
        Cha.unit_p = 1000;
    }
    Cha.i_load = Cha.i_out - Cha.i_batt;
//    Cha.i_da  = Cha.i_load + Cha.i_limit;  //i_out edit to i_da
    if (Cha.i_load < 0)
    {
         Cha.i_load = 0;
    }
    if (Cha.i_batt > Cha.i_limit)
    {
        Cha.i_low  = Cha.i_limit + Cha.i_load;
    }
    else
    {
        Cha.i_low  = Cha.i_limit;
    }

    Cha.i_high = Cha.i_limit + Cha.i_load;
    if (Cha.i_high > Cha.i_rating)
    {
        Cha.i_high = Cha.i_rating;
    }
    Cha.i_high = Cha.i_rating; //debug

    Cha.i_e = Cha.i_limit - Cha.i_batt;

    //根据电池电流调节 电流偏离限流值0。2A开始调节
    if ((Cha.i_e < -1) || (Cha.i_e > 1))
    {
        Cha.i_da += Cha.i_e/2 ;
        if (Cha.i_da > Cha.i_high)
        {
            Cha.i_da = Cha.i_high;
        }
        if (Cha.i_da < Cha.i_low)
        {
            Cha.i_da = Cha.i_low;
        }
        ltemp = Cha.i_da;
        Cha.i_outratio = (long)ltemp * 1000 / Cha.i_rating;
        SetOutI(Cha.i_outratio);            //设置输出电流比率
    }
/*
    Jkmk.temp[37] = Cha.i_e;   //debug

    Jkmk.temp[38] = Cha.i_low;   //debug
    Jkmk.temp[39] = Cha.i_da;   //debug
    Jkmk.temp[28] = Cha.i_high;   //debug
    Jkmk.temp[29] = Cha.i_out;   //debug
    Jkmk.temp[18] = Cha.i_load;   //debug
    Jkmk.temp[19] = Cha.i_outratio;   //debug
*/

}
/*
所有充电状态充电电流都不可超过限流值,
当充电电流大于限流值,则减小充电模块输出限流点,这样将导致充电电压下降。
当充电电流小于限流值,则增大充电模块输出限流点,
系统母线故障时将打开限流点,不限流
*/
void LimitCurrent(void)
{
    int step;
    /*
    Jkmk.ai_v[17]   1路电池电流
    Jkmk.ai_v[19]   2路电池电流

    Jkmk.temp[36]   转浮充电流
    Jkmk.temp[35]   转均充电流

    Jkmk.mk_cfg[51]   模块数量
    Jkmk.mk_cfg[52]   模块容量

    Jkmk.temp[34]   限流
    Jkmk.temp[30]   允许输出电流
    */
    if (Jkmk.temp[24] != 0)
    {//手动
        return;
    }
    Jkmk.temp[34] = Jkmk.mk_cfg[10] * Jkmk.mk_cfg[30]/10;    //100mA充电限流值

    step = GetChargeStep();
    switch (step)
    {
    case 0://floating charge
        SetOutI(1000);//打开限流
        break;
    case 1://floating charge to equipoise charge
    case 2://equipoise charge
        SetLimitI(Jkmk.temp[34]);
        break;
    case 3://equipoise charge to floating charge
    case 4://power cut discharge
        SetOutI(1000);//打开限流
        break;
    case 5://batt test
        break;
    case 6://batt alarm
        SetOutI(1000);//打开限流
        break;
    }
}
/****************************************************************************/
/**
2路DAC输出过程
//1 判断输出给定值是否合法  给定值判断在设置时处理过了
2 根据各自量程换算输出DAC值
3 输出


控制方式有两种
1 直接控制电压和电流,
2 控制2路电压,通过电压间接控制电流


序号
ao_v
0   电压    1路电压
1   电流    1路电流
2   电压
3

ao_cfg
0   电压缓冲
1   电流缓冲
2   2路电压缓冲
3   2路电流缓冲

4   1路电压量程
5   1路电流量程
7   2路电压量程
8   2路电流量程
*/
void DaOutU(int value)
{
#ifdef HARD_XK
    int da_value;
    Jkmk.ao_v[0] = value;
//相控电压换算成DA值,再输出到DA控制PI板
//判断量程是否为零
    if (Jkmk.ao_cfg[4] > 0)
    {
        da_value = (long)((long)value * MAX_DAVALUE)/(long)Jkmk.ao_cfg[4];
    }
    else
    {
        da_value = 0;
    }
    DA_Out1(da_value);
#endif
}

void DaOutI(int value)
{
#ifdef HARD_XK
    int da_value;
    Jkmk.ao_v[1] = value;
//相控电流换算成DA值,再输出到DA控制PID板
//判断量程是否为零
    if (Jkmk.ao_cfg[5] > 0)
    {
        da_value = (long)((long)value * MAX_DAVALUE)/(long)Jkmk.ao_cfg[5];
    }
    else
    {
        da_value = 0;
    }
    DA_Out2(da_value);
#endif
}

/****************************************************************************/
void SetOutI(int value)
{
    int i_limit;
    long int ltemp;
    if (value > 1000)
    {
        value = 1000;
    }
    if (value < 10)
    {
        value = 10;
    }
    Jkmk.ao_cfg[1] = value;
    i_limit = CdmkCurrentLimit();
    if (i_limit != value)
    {
        Jkmk.ao_v[1] = Jkmk.ao_cfg[1];
        TranOutI();
    }
//        BeepSet(1);
}
/****************************************************************************/
/****************************************************************************/
void SetCurrent(void)
{
#ifdef HARD_GP
    LimitCurrent();
#endif
#ifdef HARD_XK
    X_Current();
#endif
}
/****************************************************************************/
//adjust
//定时时执行持函数,维持设定电压
void SetVoltaget(void)//adjust
{
    int step;
    step = GetChargeStep();
        //温度补偿
    if (Jkmk.mk_cfg[21])
    {
         Cha.v_compensate = Jkmk.mk_cfg[13] * (Jkmk.ai_v[25]-Jkmk.mk_cfg[14])/100;
         Cha.v_compensate = 0;
    }
    else
    {
         Cha.v_compensate = 0;
    }
    switch (step)
    {
    //set out is floating charge voltage
    case 0:
    case 1:
    case 4:
    case 5:
        //浮充电压
        Jkmk.ao_cfg[0] = Jkmk.mk_cfg[6] + Cha.v_compensate;
        break;
    //set out is equipoise charge voltage
    case 2:
    case 3:
        if (Jkmk.mk_cfg[8] == 0)
        {
            Jkmk.ao_cfg[0] = Jkmk.mk_cfg[6] + Cha.v_compensate;
            SetChargeStep(0);
        }
        else
        {
        //均充电压
            Jkmk.ao_cfg[0] = Jkmk.mk_cfg[7] + Cha.v_compensate;
        }
        break;
    }
#ifdef HARD_GP
    TranOutV();
#endif
#ifdef HARD_XK
    X_Voltaget();
#endif
}
/****************************************************************************/
void Capacity(void)
{
/*按充电效率和放电曲线分别计算充电放电时电池当前容量 每10秒运行一次
**充电 按充电效率累加电池容量 到100%饱和
**放电 按放电曲线计算失去容量 到0%停止
**充电
**                                capc
** y * cck * x = capc  ==>  x = -------
**                              cck * y
**
**放电
** x1 < x < x2    y1 > y > y2
**
** x-x1     y1-y            (x2-x1)(y1-y)
** ----- = ------  ==>  x = ------------- + x1
** x2-x1    y1-y2              y1-y2
**
** 原始单位
** 标称容量 1 = 1Ah, 容量比 1 = 0.1%, 充电效率 1 = 0.1%,
** 电流 1 = 0.1A, 电压 1 = 0.1V, 放电曲线时间 1 = 0.1小时
** 计算中单位统一为
** 电流 1 = 0.1A, 电压 1 = 0.1V, 时间 1 = 10秒, 比值 1 = 0.1%;
** 0x7FFFFFFF = 2147483647 即2.14E9
*/
    static long diff_capac = 0;
    int i;
    long  x, x1, x2, y1_y2, cck, y;
    y     = (long)Jkmk.ai_v[17]*10;        /* 电池电流                    */
    y1_y2 = (long)Jkmk.mk_cfg[10];      /* 0.1C电流值 0.1A数 即电池容量 */
    if (y == 0)
        return;
    /* 电池状态  4 放电 5测试  */
    if ((Jkmk.temp[25] == 4) || (Jkmk.temp[25] == 5))
    {
        cck = (long)Jkmk.mk_cfg[16];    /* 充电效率 1 = 0.1%             */
        x   = (long)((long)360 * (long)100 * (long)Jkmk.mk_cfg[10]);
        cck = (cck * y / 100);
        x = x/cck;
        /* 电池按当前电流充电 预计充电时间*/
        diff_capac += MAX_DIFF_CAPAC * 100 / x;
    }
    else                /* 放电     */
    {
        /* 0.1C=10h   0.2C=4.9h  0.3C=3.0h  0.4C=2.0h  0.5C=1.4h
           0.6C=1.2h  0.7C=1.1h  0.8C=0.9h  0.9C=0.7h  1.0C=0.5h */
        y = -y;
        for ( i = 1; i < 9; i++ )
            if ( y <= ((i+1) * y1_y2) ) break;

        x1 = (long)Jkmk.mk_cfg[20+i] * 36;  /* 放电曲线值1放电10秒数 */
        x2 = (long)Jkmk.mk_cfg[20+i - 1] * 36;  /* 放电曲线值2放电10秒数 */
        x  = (x2 - x1) * ((i+1) * y1_y2 - y) / (y1_y2) + x1;
        /* 电池按当前电流放电 预计放电时间*/

        diff_capac -= MAX_DIFF_CAPAC * 100 / x;
    }

    if (i)  /*电压过低 容量不计算*/
    {
        diff_capac = 0;
    }
    /* 容量累积到够0.1%加入容量*/
    if ((diff_capac < -MAX_DIFF_CAPAC) || (diff_capac >  MAX_DIFF_CAPAC))
    {
        Jkmk.mk_cfg[11] += diff_capac / MAX_DIFF_CAPAC;
        diff_capac -= (diff_capac / MAX_DIFF_CAPAC) * MAX_DIFF_CAPAC;
        /* 防止当前容量异常值*/
        if (Jkmk.mk_cfg[11] > 100)
        {
            Jkmk.mk_cfg[11] = 100;
        }
        if (Jkmk.mk_cfg[11] < 0)
        {
            Jkmk.mk_cfg[11] = 0;
        }
        SaveModuleData(MODULE_JKMK|DATA_MKCFG, 11, 0);
    }
}
/****************************************************************************/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -