QP(状态机事件驱动型框架)
1 QP框架为什么简称QP
QP 这个简称可以理解为:
1)Quantum(量子) + Platform(平台) = QP
2)量子跃迁是指微观粒子(如原子或分子)从一个量子态突然转变到另一个量子态的过程,伴随能量的吸收或释放。
3)一个借鉴了“量子跃迁”理念的、用于构建基于层次式状态机的事件驱动型应用程序的完整开发平台。
2 QP框架概述

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,以达到跟踪状态转换的执行过程的目的。

浙公网安备 33010602011771号