当前位置:   article > 正文

QP状态机学习②——QM的使用_qm状态机

qm状态机
QM的使用主要是生成UML的状态机

例子的主要功能是每隔0.5s闪烁LED
在这里插入图片描述
具体的使用流程参考的是 状态机 | 如何从零开始构建一个QM项目 (qq.com)

  • 首先打开软件

在这里插入图片描述

在左上角找到新建模型的选项
在这里插入图片描述
在这里插入图片描述

我们可以看到有3种框架,qpc,qpcpp和qpn.其中qpcpp是C++的部分基本和我们用不上,之后qpn这个是qpc nano的意思,但是现在这个已经不用了,没有更新了。所以我们采用qpc。详情可以参见Quantum Leaps · GitHub

在这里插入图片描述

  • 新建QP模型

我们新建一个类似于官方闪灯的空白模型,然后生成到对应目录,选择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();,添加第二个状态就变为onBSP_ledOn()
再添加起始的默认状态,也就是起点。
在这里插入图片描述
在这里插入图片描述
注意添加起点之后也需要增加状态机的超时的事件。
在这里插入图片描述

QTimeEvt_armX(&me->timeEvt, BSP_TICKS_PER_SEC/2, BSP_TICKS_PER_SEC/2);
  • 1

使用第一个箭头将全部的设置链接起来
在这里插入图片描述
注意需要更改为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}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61

后面通过生成代码我们就可以生成代码了
在这里插入图片描述
生成的文件大概如下:

/*.$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} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177

可以看到这边生成的文件相较于之前的多了状态的流转以及一些 其他的部分。这个文件我们就可以真正用于QP的移植了。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/酷酷是懒虫/article/detail/811378
推荐阅读
相关标签
  

闽ICP备14008679号