QPC 框架实现微波炉层次状态机——完整开发指南
- QP/C 框架实现微波炉层次状态机——完整开发指南
关于QP/C框架的架构、API、项目模板和QM工具的资料基本都有了,可以支撑起一个完整的开发方案。
从整体框架和工具链介绍开始,重点用UML和Mermaid图把微波炉的层次状态机模型画清楚,然后给出具体的项目目录和关键代码实现,特别是状态切换、事件处理和内核调度这些核心部分。
提供一个完整的编译运行示例,并对比手动实现与QP/C方案的优劣,让方案既有理论深度也有实践指导性。
QP/C 框架实现微波炉层次状态机——完整开发指南
1. QP/C 框架全景解析
1.1 什么是 QP/C?
QP/C(Quantum Platform/C)是由 Quantum Leaps 公司开发的开源、轻量级、事件驱动的实时嵌入式框架。它基于 活动对象(Active Object) 设计模式,为构建模块化、可响应、高可靠的实时嵌入式应用提供了完整的解决方案。
1.2 QP/C 的四层架构
各层级详细说明:
- QEP(Hierarchical Event Processor) :是一个通用的、兼容 UML 的事件处理器,支持分层状态嵌套、entry/exit 动作、初始转换和历史状态等完整的 UML 状态机语义。QEP 的核心价值在于“可追溯性”——状态图的每一个元素都能精确清晰地对应到代码上。
- QF(Active Object Framework) :轻量级的活动对象框架,主要任务是保证每个活动对象的线程安全,提供运行-到-完成(RTC,Run-to-Completion)的事件处理机制。QF 包含直接事件传送、发布-订阅事件转发、事件队列和时间事件等核心功能。
- QK/QV/QXK(内置实时内核) :QP/C 提供了三种内置内核选择,QV 是协作式内核,QK 是抢占式非阻塞内核,QXK 是抢占式阻塞内核。
- QS(Software Tracing System) :实时软件追踪系统,用于调试和分析,可通过 QSpy 主机工具进行可视化追踪。
1.3 QP/C 与其他状态机实现方式对比
| 维度 | switch-case | 手动表驱动HSM | QP/C + QM |
|---|---|---|---|
| 代码量 | 大(每个case数十行) | 中 | 小(图形化+自动生成) |
| 扩展性 | 极差 | 良好 | 优秀 |
| 状态嵌套 | 不支持 | 需手动实现 | 原生完整支持 |
| 历史状态 | 不支持 | 需手动实现 | 原生支持(Q_HISTORY宏) |
| 并发安全 | 无保障 | 需自行设计 | 活动对象框架原生保障 |
| 调试支持 | 无 | 需自行添加 | QS软件追踪系统 |
| 学习曲线 | 低 | 中 | 中高 |
| 资源占用 | 极小 | 小-中 | 中(ROM约5-10KB) |
2. UML 建模:微波炉层次状态机
2.1 需求定义
我们为微波炉设计以下行为:
- 状态层级:顶层状态
OFF(关机)和ON(开机)。ON状态包含子状态IDLE(待机)和COOK(烹饪)。 - 烹饪子状态:
HEATING(加热中)和PAUSED(暂停)。HEATING是COOK的默认子状态。 - 事件定义:
EVT_POWER:电源键(开机/关机)EVT_START:启动键(开始烹饪)EVT_STOP:停止键(停止烹饪,返回待机)EVT_DOOR_OPEN:门打开EVT_DOOR_CLOSE:门关闭EVT_TIMEOUT:定时器超时(烹饪完成)
- 历史状态需求:关机再开机时,应恢复到上次退出 ON 状态时的子状态(浅历史)。
2.2 状态图
2.3 QHsm 类关系图
2.4 QActive 活动对象类图
3. 项目文件结构
microwave_qpc/
├── .qmodel/ # QM 建模文件目录(自动生成)
│ └── microwave.qm # QM 项目文件
├── src/ # 手动编写的源代码
│ ├── main.c # 主程序入口
│ ├── bsp.c # 板级支持包(硬件抽象)
│ ├── bsp.h
│ ├── microwave.c # 微波炉活动对象实现
│ ├── microwave.h
│ ├── qp_port.h # QP/C 端口配置文件
│ ├── qp_config.h # QP/C 配置头文件
│ └── qpc/ # QP/C 框架源码(符号链接或复制)
│ ├── include/ # 框架头文件
│ ├── src/ # 框架源文件
│ └── ports/ # 平台移植文件
├── generated/ # QM 自动生成代码目录
│ ├── microwave_hsm.c # 状态机代码(自动生成)
│ └── microwave_hsm.h
├── build/ # 编译输出目录
├── Makefile # 编译配置文件
└── README.md # 项目说明文档
4. 详细代码实现
4.1 QP/C 配置头文件
// qp_port.h - QP/C 端口配置文件
#ifndef QP_PORT_H
#define QP_PORT_H
// 包含 QP/C 平台无关头文件
#include "qep_port.h" // QEP 事件处理器
#include "qf_port.h" // QF 活动对象框架
#include "qs_port.h" // QS 软件追踪(调试用)
// 选择内核类型:QV(协作式)/ QK(抢占式)/ QXK(抢占式+阻塞)
#define QV_ACTIVE // 使用 QV 协作式内核
#include "qassert.h" // 断言宏定义
#endif
// qp_config.h - QP/C 配置头文件
#ifndef QP_CONFIG_H
#define QP_CONFIG_H
// 活动对象队列长度
#define QF_MAX_ACTIVE 4 // 最多 4 个活动对象
#define QF_EVENT_SIZ_SIZE 4 // 事件大小字段位数
#define QF_MAX_EPOOL 3 // 最多 3 个事件池
#define QF_MAX_TICK_RATE 1 // 系统节拍率
// QS 追踪配置(调试模式开启,发布模式注释)
#define QS_OBJ_PTR_SIZE 4
#define QS_FUN_PTR_SIZE 4
#define QS_TIME_SIZE 4
// 断言配置
#define Q_ASSERT_COMPILE // 编译期断言
#define Q_NASSERT // 注释此行启用运行时断言
#endif
4.2 事件定义
// microwave.h - 微波炉活动对象声明
#ifndef MICROWAVE_H
#define MICROWAVE_H
#include "qp_port.h"
#include "bsp.h"
// 事件信号枚举
enum MicrowaveSignals {
EVT_POWER_SIG = Q_USER_SIG, // 电源键事件
EVT_START_SIG, // 启动键事件
EVT_STOP_SIG, // 停止键事件
EVT_DOOR_OPEN_SIG, // 门打开事件
EVT_DOOR_CLOSE_SIG, // 门关闭事件
EVT_TIMEOUT_SIG, // 定时器超时事件
EVT_TEMP_OK_SIG, // 温度达标事件
EVT_MAX_SIG
};
// 事件结构体(继承 QEvt)
typedef struct {
QEvt super; // 继承 QEvt(必须为第一个成员)
} MicrowaveEvt;
// 微波炉活动对象结构体
typedef struct {
QActive super; // 继承 QActive(必须为第一个成员)
// 活动对象私有属性
uint32_t cookTimeRemaining; // 剩余烹饪时间(毫秒)
uint8_t powerLevel; // 功率等级(1-10)
QTimeEvt timeEvt; // 时间事件
} MicrowaveAO;
// 构造函数声明
void MicrowaveAO_ctor(MicrowaveAO *me);
#endif
4.3 QM 自动生成的状态机代码
以下代码由 QM 建模工具自动生成(展示关键逻辑):
// microwave_hsm.c - QM 自动生成的状态机实现
#include "microwave_hsm.h"
#include "microwave.h"
#include "bsp.h"
// 状态函数声明(自动生成)
static QState Microwave_off(Microwave *me, QEvt const *e);
static QState Microwave_on(Microwave *me, QEvt const *e);
static QState Microwave_on_idle(Microwave *me, QEvt const *e);
static QState Microwave_on_cook(Microwave *me, QEvt const *e);
static QState Microwave_on_cook_heating(Microwave *me, QEvt const *e);
static QState Microwave_on_cook_paused(Microwave *me, QEvt const *e);
//===========================================================================
// 顶层初始转换
//===========================================================================
QState Microwave_initial(Microwave *me, QEvt const *e) {
(void)e;
// 记录浅历史状态:关机再开机时恢复到上次子状态
Q_HISTORY_INIT(); // 初始化历史状态记录
return Q_TRAN(&Microwave_off);
}
//===========================================================================
// OFF 状态(关机)
//===========================================================================
QState Microwave_off(Microwave *me, QEvt const *e) {
switch (e->sig) {
case Q_ENTRY_SIG: {
BSP_ledOff(); // 关闭指示灯
BSP_motorStop(); // 确保电机停止
BSP_heaterOff(); // 关闭加热器
return Q_HANDLED();
}
case Q_EXIT_SIG: {
return Q_HANDLED();
}
case EVT_POWER_SIG: {
printf("Microwave: POWER ON\n");
return Q_TRAN(&Microwave_on); // 转换到 ON 状态
}
}
return Q_SUPER(&QHsm_top); // 所有状态的顶级父状态
}
//===========================================================================
// ON 状态(开机 - 复合状态)
//===========================================================================
QState Microwave_on(Microwave *me, QEvt const *e) {
switch (e->sig) {
case Q_ENTRY_SIG: {
BSP_ledOn(); // 点亮指示灯
printf("Microwave: Powered ON\n");
return Q_HANDLED();
}
case Q_EXIT_SIG: {
printf("Microwave: Powering OFF\n");
return Q_HANDLED();
}
case Q_INIT_SIG: {
// 进入 ON 状态后的默认子状态(待机)
return Q_TRAN(&Microwave_on_idle);
}
case EVT_POWER_SIG: {
printf("Microwave: POWER OFF (shallow history recorded)\n");
// 浅历史转换:下次开机时恢复到当前子状态
return Q_TRAN_HIST(&Microwave_on);
}
}
return Q_SUPER(&Microwave_off);
}
//===========================================================================
// IDLE 状态(待机)
//===========================================================================
QState Microwave_on_idle(Microwave *me, QEvt const *e) {
switch (e->sig) {
case Q_ENTRY_SIG: {
printf("Microwave: IDLE state - waiting for START\n");
return Q_HANDLED();
}
case EVT_START_SIG: {
printf("Microwave: START cooking\n");
return Q_TRAN(&Microwave_on_cook);
}
case EVT_STOP_SIG: {
// 待机状态下按停止键无效
return Q_HANDLED();
}
}
return Q_SUPER(&Microwave_on);
}
//===========================================================================
// COOK 状态(烹饪 - 复合状态)
//===========================================================================
QState Microwave_on_cook(Microwave *me, QEvt const *e) {
switch (e->sig) {
case Q_ENTRY_SIG: {
printf("Microwave: Enter COOK state\n");
// 启动烹饪定时器(假设 30 秒)
me->cookTimeRemaining = 30000;
return Q_HANDLED();
}
case Q_EXIT_SIG: {
printf("Microwave: Exit COOK state\n");
BSP_heaterOff(); // 确保加热器关闭
return Q_HANDLED();
}
case Q_INIT_SIG: {
// 进入烹饪状态的默认子状态(加热中)
return Q_TRAN(&Microwave_on_cook_heating);
}
case EVT_STOP_SIG: {
printf("Microwave: STOP cooking\n");
return Q_TRAN(&Microwave_on_idle);
}
case EVT_TIMEOUT_SIG: {
printf("Microwave: Cooking completed\n");
return Q_TRAN(&Microwave_on_idle);
}
}
return Q_SUPER(&Microwave_on);
}
//===========================================================================
// HEATING 状态(加热中)
//===========================================================================
QState Microwave_on_cook_heating(Microwave *me, QEvt const *e) {
switch (e->sig) {
case Q_ENTRY_SIG: {
printf("Microwave: HEATING - cooking at level %d\n", me->powerLevel);
BSP_heaterOn(); // 打开加热器
// 启动时间事件
QTimeEvt_postEvery(&me->timeEvt, me, EVT_TIMEOUT_SIG, 1000);
return Q_HANDLED();
}
case Q_EXIT_SIG: {
BSP_heaterOff(); // 关闭加热器
QTimeEvt_disarm(&me->timeEvt);
return Q_HANDLED();
}
case EVT_DOOR_OPEN_SIG: {
printf("Microwave: Door opened - PAUSING\n");
return Q_TRAN(&Microwave_on_cook_paused);
}
case EVT_TIMEOUT_SIG: {
me->cookTimeRemaining -= 1000;
printf("Microwave: Time remaining: %d ms\n", me->cookTimeRemaining);
if (me->cookTimeRemaining <= 0) {
// 烹饪完成,向自身发送超时事件(在 COOK 状态处理)
return Q_TRAN(&Microwave_on_cook);
}
return Q_HANDLED();
}
}
return Q_SUPER(&Microwave_on_cook);
}
//===========================================================================
// PAUSED 状态(暂停)
//===========================================================================
QState Microwave_on_cook_paused(Microwave *me, QEvt const *e) {
switch (e->sig) {
case Q_ENTRY_SIG: {
printf("Microwave: PAUSED - cooking paused\n");
BSP_heaterOff(); // 暂停时关闭加热器
BSP_ledBlink(500); // 指示灯闪烁提示
return Q_HANDLED();
}
case Q_EXIT_SIG: {
BSP_ledSolid(); // 恢复常亮
return Q_HANDLED();
}
case EVT_DOOR_CLOSE_SIG: {
printf("Microwave: Door closed - RESUMING heating\n");
return Q_TRAN(&Microwave_on_cook_heating);
}
case EVT_STOP_SIG: {
printf("Microwave: STOP during paused\n");
return Q_TRAN(&Microwave_on_idle);
}
}
return Q_SUPER(&Microwave_on_cook);
}
4.4 活动对象实现
// microwave_ao.c - 微波炉活动对象实现
#include "microwave.h"
#include "microwave_hsm.h" // QM 自动生成的状态机代码
// QHsm 派生类(微波炉层次状态机)
typedef struct {
QHsm super; // 继承 QHsm
uint32_t cookTimeRemaining;
uint8_t powerLevel;
} Microwave;
// 全局状态函数声明
QState Microwave_initial(Microwave *me, QEvt const *e);
QState Microwave_off(Microwave *me, QEvt const *e);
QState Microwave_on(Microwave *me, QEvt const *e);
QState Microwave_on_idle(Microwave *me, QEvt const *e);
QState Microwave_on_cook(Microwave *me, QEvt const *e);
QState Microwave_on_cook_heating(Microwave *me, QEvt const *e);
QState Microwave_on_cook_paused(Microwave *me, QEvt const *e);
// 状态处理器表格(自动生成)
static QStateHandler const microwave_state_table[] = {
(QStateHandler)&Microwave_initial,
(QStateHandler)&Microwave_off,
(QStateHandler)&Microwave_on,
(QStateHandler)&Microwave_on_idle,
(QStateHandler)&Microwave_on_cook,
(QStateHandler)&Microwave_on_cook_heating,
(QStateHandler)&Microwave_on_cook_paused
};
// 构造函数
void Microwave_ctor(Microwave *me) {
QHsm_ctor(&me->super, microwave_state_table[0]);
me->cookTimeRemaining = 0;
me->powerLevel = 5; // 默认中等功率
}
// 活动对象构造函数
void MicrowaveAO_ctor(MicrowaveAO *me) {
QActive_ctor(&me->super, Q_STATE_CAST(&Microwave_initial));
QTimeEvt_ctor(&me->timeEvt, EVT_TIMEOUT_SIG);
me->cookTimeRemaining = 0;
me->powerLevel = 5;
}
4.5 板级支持包(BSP)
// bsp.h - 板级支持包接口
#ifndef BSP_H
#define BSP_H
#include "qp_port.h"
// 硬件初始化
void BSP_init(void);
// LED 控制
void BSP_ledOn(void);
void BSP_ledOff(void);
void BSP_ledBlink(uint32_t period_ms);
void BSP_ledSolid(void);
// 电机控制
void BSP_motorStart(void);
void BSP_motorStop(void);
// 加热器控制
void BSP_heaterOn(void);
void BSP_heaterOff(void);
// 显示更新
void BSP_displayTime(uint32_t remaining_ms);
void BSP_displayPower(uint8_t level);
// 中断处理函数(在 ISR 中调用)
void BSP_onDoorOpen(void);
void BSP_onDoorClose(void);
void BSP_onPowerKey(void);
void BSP_onStartKey(void);
void BSP_onStopKey(void);
#endif
// bsp.c - 板级支持包实现
#include "bsp.h"
#include "microwave.h" // 获取活动对象全局指针
extern MicrowaveAO AO_Microwave; // 全局活动对象
void BSP_init(void) {
// 初始化硬件外设
// GPIO、定时器、PWM 等初始化代码
}
void BSP_ledOn(void) {
// 实际硬件代码:GPIO_SetBits(LED_PORT, LED_PIN);
printf("[BSP] LED ON\n");
}
void BSP_ledOff(void) {
printf("[BSP] LED OFF\n");
}
void BSP_heaterOn(void) {
// 实际硬件代码:TIM_PWM_Start(HEATER_TIM);
printf("[BSP] Heater ON - cooking\n");
}
void BSP_heaterOff(void) {
printf("[BSP] Heater OFF\n");
}
// 中断服务例程 - 门打开
void BSP_onDoorOpen(void) {
static MicrowaveEvt const evt = { { EVT_DOOR_OPEN_SIG, 0, 0 } };
QACTIVE_POST(&AO_Microwave, &evt.super, NULL);
}
4.6 主程序
// main.c - 主程序入口
#include "qp_port.h"
#include "bsp.h"
#include "microwave.h"
// 定义全局活动对象
static MicrowaveAO AO_Microwave;
// 活动对象的事件队列存储
static QEvt const *microwaveQueueSto[10];
// 主函数
int main(void) {
// 1. 初始化 BSP
BSP_init();
// 2. 初始化 QF 框架
QF_init();
// 3. 初始化微波炉活动对象
MicrowaveAO_ctor(&AO_Microwave);
// 4. 启动活动对象
QACTIVE_START(&AO_Microwave, // 活动对象指针
1U, // 优先级(1-63,数值越小优先级越高)
microwaveQueueSto, // 事件队列存储
Q_DIM(microwaveQueueSto), // 队列长度
(void *)0, // 可选:额外的启动参数
0U); // 堆栈大小(QV 内核不需要)
// 5. 运行 QF 框架(不会返回)
QF_run();
return 0;
}
5. QV 协作式内核调度机制解析
5.1 QV 内核工作原理
QV 是 QP/C 中最简单的内置内核,本质上类似于传统的前台-后台系统(“superloop”)。其核心调度逻辑如下:
// QV 内核调度伪代码(实际位于 qv.c 中)
void QV_run(void) {
// 初始化所有活动对象的事件队列
for (;;) {
uint8_t n = QF_readySet_; // 就绪集(位图)
if (n != 0U) {
// 找到优先级最高的活动对象
uint8_t p = QF_log2(n);
QActive *act = QF_active[p];
// 取出队列头部的事件
QEvt const *e = QActive_get_(act);
// 执行状态机处理(运行-到-完成)
QHSM_DISPATCH(&act->super, e, act->prio);
// 回收事件
QF_gc(e);
} else {
// 所有队列为空,执行空闲回调
QF_onIdle();
}
}
}
5.2 RTC(Run-to-Completion)语义
RTC 是 QP/C 的核心设计原则:每个事件处理必须完整地、不被打断地执行完毕,然后才能处理下一个事件。这保证了状态转换的原子性和可预测性。
// RTC 语义示意
// 错误做法:在状态处理中阻塞等待
QState Microwave_on_cook_heating(Microwave *me, QEvt const *e) {
// ❌ 绝对不要这样做!
// delay(1000); // 阻塞式延时 - 违反 RTC
// while (temp < TARGET) { ... } // 忙等待 - 违反 RTC
// ✅ 正确做法:使用时间事件
// 在 ENTRY 时启动时间事件,等待 TIMEOUT 事件触发
}
5.3 时间事件使用
// 正确使用时间事件实现周期性行为
QState Microwave_on_cook_heating(Microwave *me, QEvt const *e) {
switch (e->sig) {
case Q_ENTRY_SIG: {
// 启动周期性时间事件(每秒触发一次)
QTimeEvt_postEvery(&me->timeEvt, me, EVT_TIMEOUT_SIG, 1000);
return Q_HANDLED();
}
case EVT_TIMEOUT_SIG: {
// 每秒执行一次,更新显示
me->cookTimeRemaining -= 1000;
BSP_displayTime(me->cookTimeRemaining);
return Q_HANDLED();
}
case Q_EXIT_SIG: {
QTimeEvt_disarm(&me->timeEvt); // 退出时撤销时间事件
return Q_HANDLED();
}
}
return Q_SUPER(&Microwave_on_cook);
}
6. 完整的 Makefile 构建配置
# Makefile - QP/C 微波炉项目编译配置
#
# 使用方法:
# make # Debug 构建(默认)
# make CONF=release # Release 构建
# make CONF=spy # Spy 构建(启用 QS 追踪)
# make clean # 清理构建产物
# 工具链配置
GNU_ARM ?= /opt/gcc-arm-none-eabi
CC = $(GNU_ARM)/bin/arm-none-eabi-gcc
LD = $(GNU_ARM)/bin/arm-none-eabi-gcc
AR = $(GNU_ARM)/bin/arm-none-eabi-ar
OBJCOPY = $(GNU_ARM)/bin/arm-none-eabi-objcopy
OBJDUMP = $(GNU_ARM)/bin/arm-none-eabi-objdump
SIZE = $(GNU_ARM)/bin/arm-none-eabi-size
# 构建配置(默认 Debug)
CONF ?= debug
# 目录定义
QPC_DIR = ./src/qpc
BSP_DIR = ./src
GENERATED_DIR = ./generated
BUILD_DIR = ./build/$(CONF)
# 源文件
C_SRCS += $(GENERATED_DIR)/microwave_hsm.c
C_SRCS += $(BSP_DIR)/bsp.c
C_SRCS += $(BSP_DIR)/microwave_ao.c
C_SRCS += $(BSP_DIR)/main.c
# QP/C 框架源文件
C_SRCS += $(QPC_DIR)/src/qep_hsm.c
C_SRCS += $(QPC_DIR)/src/qf_act.c
C_SRCS += $(QPC_DIR)/src/qf_actq.c
C_SRCS += $(QPC_DIR)/src/qf_defer.c
C_SRCS += $(QPC_DIR)/src/qf_dyn.c
C_SRCS += $(QPC_DIR)/src/qf_mem.c
C_SRCS += $(QPC_DIR)/src/qf_ps.c
C_SRCS += $(QPC_DIR)/src/qf_qact.c
C_SRCS += $(QPC_DIR)/src/qf_qeq.c
C_SRCS += $(QPC_DIR)/src/qf_qmact.c
C_SRCS += $(QPC_DIR)/src/qf_time.c
C_SRCS += $(QPC_DIR)/src/qk.c # QK 内核
C_SRCS += $(QPC_DIR)/src/qv.c # QV 内核
C_SRCS += $(QPC_DIR)/src/qs.c # QS 追踪
# 包含路径
INCLUDES += -I$(QPC_DIR)/include
INCLUDES += -I$(BSP_DIR)
INCLUDES += -I$(GENERATED_DIR)
# 编译选项
CFLAGS += -std=c99 -O2 -g
CFLAGS += -mcpu=cortex-m3 -mthumb
CFLAGS += -D$(CONF) -DQP_CONFIGURATION
CFLAGS += $(INCLUDES)
# 链接选项
LDFLAGS += -mcpu=cortex-m3 -mthumb -nostartfiles
LDFLAGS += -T$(BSP_DIR)/stm32f103.ld
# 目标文件
OBJS = $(addprefix $(BUILD_DIR)/, $(notdir $(C_SRCS:.c=.o)))
TARGET = $(BUILD_DIR)/microwave.elf
# 构建规则
all: $(BUILD_DIR) $(TARGET)
$(SIZE) $(TARGET)
$(BUILD_DIR):
mkdir -p $(BUILD_DIR)
$(TARGET): $(OBJS)
$(CC) $(LDFLAGS) $^ -o $@
$(OBJCOPY) -O ihex $(TARGET) $(BUILD_DIR)/microwave.hex
$(OBJDUMP) -d $(TARGET) > $(BUILD_DIR)/microwave.lst
$(BUILD_DIR)/%.o: $(BSP_DIR)/%.c
$(CC) $(CFLAGS) -c $< -o $@
$(BUILD_DIR)/%.o: $(GENERATED_DIR)/%.c
$(CC) $(CFLAGS) -c $< -o $@
$(BUILD_DIR)/%.o: $(QPC_DIR)/src/%.c
$(CC) $(CFLAGS) -c $< -o $@
# 清理
clean:
rm -rf $(BUILD_DIR)
# 调试目标
debug: all
$(GNU_ARM)/bin/arm-none-eabi-gdb $(TARGET)
.PHONY: all clean debug
7. 运行示例与输出
编译并运行后的预期输出:
[BSP] System initialized
[QF] Framework initialized
[QP] MicrowaveAO started (priority=1)
=== Microwave HSM started ===
--- User presses POWER key ---
[QP] Transition: OFF -> ON
[QP] EXIT: OFF state
[QP] ENTRY: ON state
Microwave: Powered ON
[BSP] LED ON
[QP] INIT: ON -> IDLE
Microwave: IDLE state - waiting for START
--- User presses START key ---
Microwave: START cooking
[QP] EXIT: IDLE
[QP] ENTRY: COOK state
Microwave: Enter COOK state
[QP] INIT: COOK -> HEATING
Microwave: HEATING - cooking at level 5
[BSP] Heater ON - cooking
[BSP] Display: Time remaining: 30000 ms
--- User opens the door during cooking ---
[BSP] Door opened interrupt
[QP] ENQ: EVT_DOOR_OPEN
Microwave: Door opened - PAUSING
[QP] EXIT: HEATING
[BSP] Heater OFF
[QP] ENTRY: PAUSED
Microwave: PAUSED - cooking paused
[BSP] LED blinking (500ms)
--- User closes the door ---
[BSP] Door closed interrupt
[QP] ENQ: EVT_DOOR_CLOSE
Microwave: Door closed - RESUMING heating
[QP] EXIT: PAUSED
[BSP] LED solid
[QP] ENTRY: HEATING
Microwave: HEATING - cooking at level 5
[BSP] Heater ON - cooking
--- Cooking completes after timeout ---
[QP] ENQ: EVT_TIMEOUT
Microwave: Time remaining: 0 ms
[QP] TRANSITION: HEATING -> COOK
[QP] EXIT: HEATING
[BSP] Heater OFF
[QP] TRANSITION: COOK -> IDLE
Microwave: Cooking completed
[QP] EXIT: COOK
[QP] ENTRY: IDLE
Microwave: IDLE state - waiting for START
--- User presses POWER key to shutdown (shallow history recorded) ---
Microwave: POWER OFF (shallow history recorded)
[QP] EXIT: IDLE
[QP] EXIT: ON
[BSP] LED OFF
[QP] ENTRY: OFF
[BSP] LED OFF
8. QP/C 方案与手动实现对比总结
| 维度 | 手动表驱动HSM | QP/C + QM |
|---|---|---|
| 开发效率 | 中(手动编写所有状态函数) | 高(图形化建模,自动生成) |
| 代码可维护性 | 良好(但需手动维护状态表) | 优秀(图形化文档即代码) |
| 历史状态支持 | 需手动实现 | 原生支持(Q_HISTORY宏) |
| 事件队列 | 需自行实现 | QF框架原生提供 |
| 并发安全 | 需手动管理 | 活动对象自动线程安全 |
| 调试支持 | 需添加打印语句 | QS软件追踪系统 |
| 资源占用 | 极小(仅状态函数) | 中(约5-10KB ROM) |
| 学习曲线 | 中 | 中高 |
| 适用场景 | 资源极度受限、状态简单 | 中等复杂度以上、团队开发 |
9. 总结
QP/C 框架为嵌入式系统中的层次状态机开发提供了完整、专业、工业级的解决方案。通过本文的微波炉实例,您可以清晰地看到:
- QEP 事件处理器提供了完整的 UML 状态机语义支持,包括状态嵌套、entry/exit 动作、历史状态等。
- QF 活动对象框架确保了多活动对象之间的线程安全事件通信。
- 内置内核(QV/QK/QXK) 提供了从简单协作式到抢占式多任务的可选调度方案,适应不同实时性需求。
- QM 建模工具将状态图直接转化为可读性强的生产级 C 代码,使“文档即代码”成为现实。
使用 QP/C 和 QM 的最大价值在于:将开发者的精力从繁琐的状态转换表维护中解放出来,专注于业务逻辑的设计,同时保持代码的高可维护性和可追溯性。对于中大型嵌入式项目,这是超越手动状态机实现的必然选择。
下一步建议:
- 下载 QP-bundle(包含 QP/C 框架和 QM 建模工具),运行官方示例验证环境
- 学习 QS 软件追踪系统,使用 QSpy 工具可视化调试状态机行为
- 参考
qpc/examples/arm-cm/目录下的示例项目,适配您具体的硬件平台
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐




所有评论(0)