关注、星标公众号,直达精彩内容
来源:技术让梦想更伟大
作者:李肖遥
QM建模工具可用于两种操作模式:交互式GUI模式和命令行模式。同时也支持windows、Linux、MaxOS操作系统上运行,其两种操作模式都是一样的,我将在windows上演示。
windows上运行QM直接双击桌面快捷方式,启动QM无需任何命令行参数。也可以通过将QM模型文件拖放到QM快捷方式上来启动QM™,我们以一个QM建模和实现简单的“闪烁”应用程序,来学习如何从零开始构建一个QM项目,并且在桌面上执行时将运行结果打印到屏幕上。
我们先新建一个Model如下图所示,这里我们直接选择默认的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()
;。
之后在Property Editor
中添加
QTimeEvt_armX(&me->timeEvt, BSP_TICKS_PER_SEC/2, BSP_TICKS_PER_SEC/2);
以与之前类似的方式,添加第二个过渡并将其触发器也更改为TIMEOUT,最终效果如下
与基于状态机的大多数其他图形工具相比,QM将代码生成“颠倒
”了,通过QM,可以确定生成的代码结构,目录名,文件名以及每个文件中包含的元素,也可以将自己的代码与生成的代码混合,并使用QM生成尽可能多或更少的整体代码。
首先创建一个目录,该目录将确定磁盘上生成的文件相对于QM模型文件的位置。
在Model Explorer
视图中,右键单击模型项,然后在弹出菜单中选择Add directory
,这是将在其中生成代码的目录。与QM模型文件的目录路径相关联的可以在属性编辑器中进行编辑,代码将在与模型相同的目录中生成。
向目录添加源文件和头文件,这是我们的常规操作。
在QM中,我们可以键入自己的代码以及代码生成指令,把下面一段代码复制到文件中。
#include "qpc.h"
#include
#include /* 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) {
fprintf(stderr, "Assertion failed in %s:%d", module, loc);
exit(-1);
}
void QF_onStartup(void) {}
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 main() {
/* 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}
当然也可以像生成任何其他手写代码一样构建生成的代码,然后开始编译代码如下图所示。
如果将blinky.c文件设计为在Windows或Linux之类的桌面操作系统上运行,则由于printf()语句,因此在开头编码了板级支持软件包(BSP)功能。这是如何在Windows命令提示符下生成blinky.exe可执行文件的方法:
以上动图都是参考官网的,为了能够帮助我们清晰的理解相关操作,感谢大家支持,原创不易,希望大家三连转发支持,感谢!
‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧ END ‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧
推荐阅读:
嵌入式编程专辑Linux 学习专辑C/C++编程专辑
Qt进阶学习专辑
关注我的微信公众号,回复“加群”按规则加入技术交流群。
点击“阅读原文”查看更多分享。