QP(状态机事件驱动型框架)

1 QP框架为什么简称QP

QP 这个简称可以理解为:

1)Quantum(量子) +  Platform(平台) = QP

2)量子跃迁是指微观粒子(如原子或分子)从一个量子态突然转变到另一个量子态的过程,伴随能量的吸收或释放。

3)一个借鉴了“量子跃迁”理念的、用于构建基于层次式状态机事件驱动型应用程序的完整开发平台

 

2 QP框架概述

image

3 层次式状态机是什么

       层次状态机即HFSM。在开发过程中,角色和系统的行为复杂性不断增加。传统状态机在处理复杂逻辑时,可能导致状态间的逻辑层次混乱。尤其是当一个状态需要包含多个子状态时,维护这些状态变得非常困难。引入层次状态机HFSM可以很好地解决这些问题。
  层次状态机的核心思想是,将一个状态机也作为状态,这样就能够在状态机内部嵌套多个子状态机,实现更复杂的状态切换逻辑,特别是互斥状态间的隔离,与包含状态间的共存。例如,角色可以有一个 移动状态 ,但这个状态下还可以细分为 行走 和 奔跑 子状态,明显的移动状态与行走和奔跑状态属于包含关系。角色还可以有一个 闲置状态 ,明显的闲置状态与移动状态属于互斥关系。
  层次状态机可以帮助我们清晰地管理这种复杂逻辑,使代码的组织结构更加合理,满足更多更复杂的需求

 

4 UML状态机

UML状态机,即是Unified Modeling Language State Machine。更详细的说是:用统一的建模语言,更加可视化、更加简洁、更加清晰的建立状态机。

 

5 QP的简单使用

5.1构造状态机的步骤

/*************************步骤1:定义状态机结构体*************************/
typedef struct {
    QHsm super;      /* 必须作为第一个成员 - 继承来自QHsm的必要属性 */
    
    /* 状态机特定属性 */
    uint32_t pressCount;
    uint32_t holdTime;
} ButtonStateMachine;//按键状态机结构体


/*************************步骤2:声明状态处理函数*************************/
/*          按键状态机初始伪状态函数 */
QState ButtonStateMachine_initial(ButtonStateMachine * const me, QEvt const * const e);
/* idle     按键状态机空闲状态处理函数 */
QState ButtonStateMachine_idle(ButtonStateMachine * const me, QEvt const * const e);
/* pressed  按键状态机按压状态处理函数 */
QState ButtonStateMachine_pressed(ButtonStateMachine * const me, QEvt const * const e);
/* held     按键状态机按住状态处理函数 */
QState ButtonStateMachine_held(ButtonStateMachine * const me, QEvt const * const e);



/*************************步骤3:实现状态机构造函数*************************/
void ButtonStateMachine_ctor(ButtonStateMachine * const me) {
    /* 调用QHsm_ctor()构造状态机me,并指定伪状态函数 */
    QHsm_ctor(&me->super, Q_STATE_CAST(&ButtonStateMachine_initial));
    
    /* 初始化状态机属性 */
    me->pressCount = 0;
    me->holdTime = 0;
    
    printf("ButtonStateMachine constructed\n");
}

/* 初始伪状态函数 */
QState ButtonStateMachine_initial(ButtonStateMachine * const me, QEvt const * const e) {
    (void)e; /* 避免未使用参数警告 */
    
    /* 执行初始转换到idle状态 */
    return Q_TRAN(&ButtonStateMachine_idle);
}

/* idle状态处理函数 */
QState ButtonStateMachine_idle(ButtonStateMachine * const me, QEvt const * const e) {
    switch (e->sig) {
        case Q_ENTRY_SIG: {
            printf("Entering IDLE state\n");
            return Q_HANDLED();
        }
        case BUTTON_PRESSED_SIG: {
            me->pressCount++;
            printf("Button pressed, count: %lu\n", me->pressCount);
            return Q_TRAN(&ButtonStateMachine_pressed);
        }
    }
    return Q_SUPER(&QHsm_top);
}

/* pressed状态处理函数 */
QState ButtonStateMachine_pressed(ButtonStateMachine * const me, QEvt const * const e) {
    switch (e->sig) {
        case Q_ENTRY_SIG: {
            printf("Entering PRESSED state\n");
            me->holdTime = 0;
            return Q_HANDLED();
        }
        case BUTTON_RELEASED_SIG: {
            printf("Button released after %lu ms\n", me->holdTime);
            return Q_TRAN(&ButtonStateMachine_idle);
        }
        case TIMEOUT_SIG: {
            me->holdTime += 100; /* 假设100ms超时 */
            if (me->holdTime >= 1000) { /* 按住1秒进入held状态 */
                return Q_TRAN(&ButtonStateMachine_held);
            }
            return Q_HANDLED();
        }
    }
    return Q_SUPER(&QHsm_top);
}

/* held状态处理函数 */
QState ButtonStateMachine_held(ButtonStateMachine * const me, QEvt const * const e) {
    switch (e->sig) {
        case Q_ENTRY_SIG: {
            printf("Entering HELD state - long press detected!\n");
            return Q_HANDLED();
        }
        case BUTTON_RELEASED_SIG: {
            printf("Long press released\n");
            return Q_TRAN(&ButtonStateMachine_idle);
        }
    }
    return Q_SUPER(&QHsm_top);
}

 

5.2状态处理函数如何被QP调用

- 1)在QP中,首先调用状态机构造函数QHsm_ctor(),用于构建状态机的静态结构;然后调用状态机初始化 QHsm_init(),启动状态机并执行初始转换;最后调用事件分发qhsm_dispatch(),向已初始化的状态机分发事件。

- 3)状态处理函数的格式框架:状态处理函数检查事件类型,并执行相应的动作。它可能返回以下值之一:

  • Q_RET_HANDLED:数值0,事件已处理。

  • Q_RET_IGNORED:数值1,事件被忽略(未处理)。

  • Q_RET_TRAN:数值2,事件已处理并触发了状态转换,即 响应对应事件,执行相关动作后,需要改变状态变化,就像关闭状态 --[开门事件]--> 打开状态。

  • Q_RET_SUPER:数值3,事件被委托给父状态处理。

  • Q_RET_UNHANDLED:数值4,表示事件未被当前状态处理,状态机会继续将事件传递给父状态或其他可能的状态。

- 4)状态网络的设计,实际上通过状态处理函数的格式框架,就可以设计状态网络,就可以设计事件在状态网络中的路由,就可以设计和事件在状态网络中的处理。

- 5)当然状态网络的层次结构,还需要超状态的概念,超状态是一个包含其他状态(子状态)的父状态。它本身可以包含状态逻辑,同时管理一组相关的子状态。

  • 事件首先传递给当前活动的子状态

  • 如果子状态不处理,事件会传递给超状态

  • 超状态可以处理子状态共享的事件逻辑

  • 进入超状态时,会自动进入其初始子状态

  • 退出超状态时,会退出所有活动的子状态

  • 在 QHSM(分层状态机)中,需要状态机结构体中的成员teep ,以达到跟踪状态转换的执行过程的目的。

posted @ 2025-11-04 11:18  FBshark  阅读(14)  评论(0)    收藏  举报