代码改变世界

数字电源数字控制状态机及伪代码实现

2023-06-06 17:23  斑鸠,一生。  阅读(273)  评论(0编辑  收藏  举报

  未完待续~~~

  个人做数字电源有一段时间了,将近些年的感悟总结记录在下,欢迎大家多多指教,感谢!(参考Ti的UCD3138控制器的Demo Program)


 一、基本控制逻辑状态机

   下图为常见的数字电源控制转态机。

   绿色椭圆为三个状态,黑色为转态转移路径,红色为发生异常后的状态转移路径。

 

   三个状态:

      • Idle:该状态用于等待开机,该状态的主要任务是检测开机条件,如果满足开机条件,就会向下一个状态转换;如果检测到指定的异常,将会跳转到Idle转态。满足开机条件是Idle 转态的结束信号。
      • Ramp up:该状态用于实现软开关等特殊要求的,该状态会存在一个结束条件,当满足条件时,将会进入下一个状态;如果检测到指定的异常,将会跳转到Idle转态。
      • Steady:该状态用于实现稳态控制,电源主要功能均在此阶段实现。如果检测到指定的异常,将会跳转到Idle转态。

  转态转换条件:

    Condition one:控制器从Idle状态转换为Ramp up状态转换的触发条件,该条件包含以下几个检测项目:

      • Enable Signal: 开机使能信号

    Condition two:控制器从Ramp up状态转换为Steady状态转换的触发条件,该条件除了包含Condition one的检测项目外,还需要收到Ramp up结束的信号。常见的Ramp up结束信号有:

      • 软启动时间满足
      • 输出电压达到设定范围
      • 输出电流达到设定范围

    Condition three: 控制器从Steady 状态切换为Idle状态转换的触发条件,该条件包含以下几个检测项目:

      • Disable Signal:关机使能信号

  Error 事件:当满足异常条件中任何一条的时候,控制器立即切换到Idle转态。

      • OCP:输入/输出过流
      • OVP:输入/输出过压
      • UVP:输入/输出欠压
      • OTP:  过温
      • UTP:  欠温

 二、改进控制逻辑状态机

    电源启动的时候,输出电压或许不是从零开始启动,考虑到多模块并机的需求,现在主流数字电源常包含Prebias功能,控制状态机如下:

 

    Prebias 的作用在另外一篇博文里面进行了详述,为了防止输出电压或者输出电流倒灌进数字电源,从Idle状态出来之后,在进行Ramp up之前,通常需要设定数字电源开始工作的初始状态,常见的几种方式有:

      • 初始化开关频率
      • 初始化占空比

     Prebias 的目的是通过电源启动的初始化控制,减轻或者消除输出电流倒灌导致输出电压降低的现象。

        Prebias 状态的结束条件是完成初始化计算或者设定,自动退出Prebias状态。

三、目前主流控制逻辑状态机

     上面两种控制逻辑存在一个问题是,当发生Error事件的时候,电源切换至Idle状态,在Idle检测到满足开机条件时,再次开机。如果故障未被排除,再次开机可能导致电源损坏。

    为了避免这种现象,主流的控制逻辑状态机将Error事件分为两类,一类事件允许再次开机的Error回到Idle转态,另外一类Error事件不允许再次开机或者得满足特定条件才允许再次开机。

  

四、伪代码实现

   在整个程序的生命周期里面,需要定义一个变量state来指示当前程序所属的状态,而且该变量状态数量为有限个。

  Plan A: 使用if else 做状态判断和切换。

int main()
{
    int state = 0;
    
    while(1){
        if( state == 0){
            task_A();
            state = 1;
        }
        else if( state == 1){
            task_B();
            state = 2;
        }
        else if( state == 2){
            task_C();
            state = 3;
        }
        //......
    }
}

 

   Plan B: 使用Switch函数做状态判断和切换。(Ti给的UCD3138程序就是使用的这种结构)

int main()
{
    int state = 0;
    
    while(1){
        switch( state ){
            case 0x00:
                task_A();
                state = 1;
                break;
            case 0x01:
                task_B();
                state = 2;
                break;
            case 0x02:
                task_C();
                state = 3;
                break;
            //......
            default:
                break;

        }
    }
}