赞
踩
例子的主要功能是每隔0.5s闪烁LED
具体的使用流程参考的是 状态机 | 如何从零开始构建一个QM项目 (qq.com)
在左上角找到新建模型的选项
我们可以看到有3种框架,qpc,qpcpp和qpn.其中qpcpp是C++的部分基本和我们用不上,之后qpn这个是qpc nano的意思,但是现在这个已经不用了,没有更新了。所以我们采用qpc。详情可以参见Quantum Leaps · GitHub
我们新建一个类似于官方闪灯的空白模型,然后生成到对应目录,选择qpc -> None
添加的第一项是包,UML中的包是一种分组构造,它允许我们将其他模型项组合到更高级别的单元(包)中。程序包最常见的用途是将类分组在一起,但是程序包也可以包含自由属性,自由操作甚至其他程序包。
在Model Explorer
视图中,右键单击模型项目以获取特定于该项目的弹出菜单,然后选择Add Package
,在Property Editor
视图中更改名字如下图:
接下来,向新包中添加一个类,因为只有类才能具有行为(即状态机)。
在Model Explorer
视图中,右键单击AOs
以获取特定于该项目的弹出菜单,然后选择Add Class
,在Property Editor
视图中更改名字如下图:
接下来添加时间事件属性,该属性将周期性触发“Blinky”状态机中的闪烁。
在Model Explorer
视图中,右键单击Blinky:QActive
以获取特定于该项目的弹出菜单,然后选择Add Attribute
,在Property Editor
视图中更改配置如下图:
在Model Explorer
视图中,右键单击Blinky:QActive
以获取特定于该项目的弹出菜单,然后选择Add State Machine
,双击SM,如下图:
在图工具箱中,单击状态工具,将鼠标移动到图表窗口,在其中放置状态形状的左上角。单击鼠标并将其拖动到状态形状的右下角,释放鼠标。举个例子如下:
在Property Editor
中,将状态名称更改为off
,然后将entry
添加到此状态BSP_ledOff()
;,添加第二个状态就变为on
、BSP_ledOn()
。
再添加起始的默认状态,也就是起点。
注意添加起点之后也需要增加状态机的超时的事件。
QTimeEvt_armX(&me->timeEvt, BSP_TICKS_PER_SEC/2, BSP_TICKS_PER_SEC/2);
使用第一个箭头将全部的设置链接起来
注意需要更改为TIMEOUT
结束之后的成品是这样子的
与基于状态机的大多数其他图形工具相比,QM将代码生成“颠倒”了,通过QM,可以确定生成的代码结构,目录名,文件名以及每个文件中包含的元素,也可以将自己的代码与生成的代码混合,并使用QM生成尽可能多或更少的整体代码。使用QM是为了减少代码而不是真的一点点代码都不要写的,只是把逻辑部分给你生成好了。该写的还是一样的。
首先创建一个目录,该目录将确定磁盘上生成的文件相对于QM模型文件的位置。
在Model Explorer
视图中,右键单击模型项,然后在弹出菜单中选择Add directory
,这是将在其中生成代码的目录。与QM模型文件的目录路径相关联的可以在属性编辑器中进行编辑,代码将在与模型相同的目录中生成。
向目录添加源文件和头文件
在QM中,我们可以键入自己的代码以及代码生成指令,把下面一段代码复制到文件中。
#include "qpc.h" #include <stdio.h> #include <stdlib.h> /* for exit() */ Q_DEFINE_THIS_FILE enum { BSP_TICKS_PER_SEC = 100 }; void BSP_ledOff(void) { // 添加操作代码 printf("LED OFF\n"); } void BSP_ledOn(void) { // 添加操作代码 printf("LED ON\n"); } void Q_onAssert(char const * const module, int loc) { printf("Assertion failed in %s:%d", module, loc); } void QF_onStartup(void) { NVIC_SetPriority(SysTick_IRQn, 1); // 设置中断优先级 } void QF_onCleanup(void) {} void QF_onClockTick(void) { QF_TICK_X(0U, (void *)0); /* perform the QF clock tick processing */ } enum BlinkySignals { TIMEOUT_SIG = Q_USER_SIG, MAX_SIG }; /*============== ask QM to declare the Blinky class ================*/ $declare${AOs::Blinky} static Blinky l_blinky; QActive * const AO_Blinky = &l_blinky.super; static void Blinky_ctor(void) { Blinky *me = (Blinky *)AO_Blinky; QActive_ctor(&me->super, Q_STATE_CAST(&Blinky_initial)); QTimeEvt_ctorX(&me->timeEvt, &me->super, TIMEOUT_SIG, 0U); } int StateMachine_Start() { /* statically allocate event queue buffer for the Blinky AO */ static QEvt const *blinky_queueSto[10]; QF_init(); /* initialize the framework */ Blinky_ctor(); /* explicitly call the "constructor" */ QACTIVE_START(AO_Blinky, 1U, /* priority */ blinky_queueSto, Q_DIM(blinky_queueSto), (void *)0, 0U, /* no stack */ (QEvt *)0); /* no initialization event */ return QF_run(); /* run the QF application */ } /*================ ask QM to define the Blinky class ================*/ $define${AOs::Blinky}
后面通过生成代码我们就可以生成代码了
生成的文件大概如下:
/*.$file${Code::Blinky.c} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ /* * Model: model.qm * File: ${Code::Blinky.c} * * This code has been generated by QM 5.1.4 <www.state-machine.com/qm/>. * DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. * * This program is open source software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ /*.$endhead${Code::Blinky.c} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ #include "main.h" #include "qpc.h" #include <stdio.h> Q_DEFINE_THIS_FILE enum { BSP_TICKS_PER_SEC = 1000 }; void BSP_ledOff(void) { HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin); // printf("LED OFF\n"); } void BSP_ledOn(void) { HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin); // printf("LED ON\n"); } void Q_onAssert(char const *const module, int loc) {} void QF_onStartup(void) { NVIC_SetPriority(SysTick_IRQn, 1); // 设置中断优先级 } void QF_onCleanup(void) {} void QV_onIdle(void) {} void QF_onClockTick(void) { QF_TICK_X(0U, (void *)0); /* perform the QF clock tick processing */ } enum BlinkySignals { TIMEOUT_SIG = Q_USER_SIG, MAX_SIG }; /*============== ask QM to declare the Blinky class ================*/ /*.$declare${AOs::Blinky} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ /*.${AOs::Blinky} ..........................................................*/ typedef struct { /* protected: */ QActive super; /* private: */ QTimeEvt TimeEvt; } Blinky; /* protected: */ static QState Blinky_initial(Blinky *const me, void const *const par); static QState Blinky_LED_ON(Blinky *const me, QEvt const *const e); static QState Blinky_LED_OFF(Blinky *const me, QEvt const *const e); /*.$enddecl${AOs::Blinky} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ static Blinky l_blinky; QActive *const AO_Blinky = &l_blinky.super; static void Blinky_ctor(void) { Blinky *me = (Blinky *)AO_Blinky; QActive_ctor(&me->super, Q_STATE_CAST(&Blinky_initial)); QTimeEvt_ctorX(&me->TimeEvt, &me->super, TIMEOUT_SIG, 0U); } int StateMachine_Start() { /* statically allocate event queue buffer for the Blinky AO */ static QEvt const *blinky_queueSto[10]; QF_init(); /* initialize the framework */ Blinky_ctor(); /* explicitly call the "constructor" */ QACTIVE_START(AO_Blinky, 1U, /* priority */ blinky_queueSto, Q_DIM(blinky_queueSto), (void *)0, 0U, /* no stack */ (QEvt *)0); /* no initialization event */ return QF_run(); /* run the QF application */ } /*================ ask QM to define the Blinky class ================*/ /*.$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ /*. Check for the minimum required QP version */ #if (QP_VERSION < 690U) || (QP_VERSION != ((QP_RELEASE ^ 4294967295U) % 0x3E8U)) #error qpc version 6.9.0 or higher required #endif /*.$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ /*.$define${AOs::Blinky} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ /*.${AOs::Blinky} ..........................................................*/ /*.${AOs::Blinky::SM} ......................................................*/ static QState Blinky_initial(Blinky *const me, void const *const par) { /*.${AOs::Blinky::SM::initial} */ QTimeEvt_armX(&me->TimeEvt, BSP_TICKS_PER_SEC / 2, BSP_TICKS_PER_SEC / 2); return Q_TRAN(&Blinky_LED_ON); } /*.${AOs::Blinky::SM::LED_ON} ..............................................*/ static QState Blinky_LED_ON(Blinky *const me, QEvt const *const e) { QState status_; switch (e->sig) { /*.${AOs::Blinky::SM::LED_ON} */ case Q_ENTRY_SIG: { BSP_ledOn(); status_ = Q_HANDLED(); break; } /*.${AOs::Blinky::SM::LED_ON::TIMEOUT} */ case TIMEOUT_SIG: { status_ = Q_TRAN(&Blinky_LED_OFF); break; } default: { status_ = Q_SUPER(&QHsm_top); break; } } return status_; } /*.${AOs::Blinky::SM::LED_OFF} .............................................*/ static QState Blinky_LED_OFF(Blinky *const me, QEvt const *const e) { QState status_; switch (e->sig) { /*.${AOs::Blinky::SM::LED_OFF} */ case Q_ENTRY_SIG: { BSP_ledOff(); status_ = Q_HANDLED(); break; } /*.${AOs::Blinky::SM::LED_OFF::TIMEOUT} */ case TIMEOUT_SIG: { status_ = Q_TRAN(&Blinky_LED_ON); break; } default: { status_ = Q_SUPER(&QHsm_top); break; } } return status_; } /*.$enddef${AOs::Blinky} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。