李肖遥QP事件状态机框架论坛之QP调试如下图

组织:李逍遥

QP事件状态机框架论坛上已经有很多教程了。此外,已经有中文版书籍。学习 QP 可能需要更多时间才能开始。有经验的攻城狮可能工作太忙没时间学习更多技术,使用 QP 框架的好处可能仍然无法吸引你,但如果现在有一款可以自动生成代码的图形编辑软件呢?会这么刺激吗?虽然不能完全脱离代码,但至少应用层可以通过使用这个软件来完成。我要推荐QM软件,一个基于QP框架UML语言的状态机图形编程软件。使用 QM 开发官方 Blingy 闪光灯的基础教程。

简介

QP是Quantum Leaps开发的事件驱动状态机框架,区别于传统的顺序系统(前端架构为main+ISR)和传统的多任务系统(操作系统),实现了object-面向C语言。编程,框架支持有限状态机FSM和分层状态机HSM。

QP的大体框架如下

开发者使用该框架的开发步骤如下:

了解整个项目需求时序图,用行为划分活动对象并为每个活动对象分配系统资源,减少对象之间的耦合,梳理每个活动对象之间的事件交换信号和事件枚举,事件交换每个活动对象与其自身对象下的触发信号事件之间。信号只是触发信号,事件是带参数的信号触发。例如状态机c语言编程,串口不仅接收接收该触发事件的串口,还接收与之相关的数据。每个活动对象下的特定状态机实现初始化并启动应用程序对事件进行排队。分配内存,初始化活动对象,分配优先级,最后启动QP将系统控制权交给QP管理。 QP 根据您的事件触发器在每个活动对象下执行状态机调试

如下图

关于QP的更多信息,请点击这里,有PSICC2-CN文档的电子版详细介绍了整个QP框架

QpNano

接下来简单介绍一下QpNano,因为我的建模使用的是QpNano,它是事件驱动框架下的定制版。顾名思义,它针对的是资源有限的微控制器。比如低端的8位和16位单片机8051、PIC、AVR、MSP、STM8等当然也适合32位处理器。

在简单介绍StateMachines板的资源之前,先在QP官网介绍如何使用Blinky(闪光灯)例程:

使用STM32F030C8T6 Cortex-m0处理器板载按键、12864液晶屏、字库、数码管、串口转USB、LED灯

在简单介绍了QP和QpNano之后,以下是我想重点推荐QP框架的原因。 QP 框架允许完全手动编程和使用自动代码生成工具 QM。 QM(QP™ Modeler)建模是一个基于QP框架和分层状态机UML语言图形的自动代码生成工具,可以实现该软件下各个对象的状态机和事件交换,状态机使用UML实现graphics,真正在应用层使用图形编程,更适合我们的编程思维。

Blinky 程序是一个 LED 闪烁程序。是学习QP和QM最基本的套路。下面是使用qm_3.3.0-win64搭建Blinky模型:

第一步是在QM中新建一个项目

如下图,点击File菜单下的New Model新建一个QM项目,然后在弹出的页面Frameworks下选择使用qpn或qp-nano framework,Templates模板选择None ,我暂时命名为Project,Location选择项目。保存位置

点击OK后可以看到项目已经生成如下图

第 2 步:创建一个对象

在上一步生成的工程的左上角,右键点击Mode Explorer下的Project,选择Add Package,创建一个包。在 Property Editor 中,nano 被命名为 AOs,并且将构造型选择为组件,如下所示

然后在AOs上右击选择Add Class创建一个类,在Property Editor中将nano命名为Blinky,在超类中选择qpn::QActive,如下图

然后在AOs上右击选择Add Attribute添加属性,在Property Editor中nano命名为AO_Blinky,类型为struct Blinky,即使是Blinky类的具体实例对象

如下图

然后在属性编辑器中右键单击 AO 并选择添加操作以增加类结构

nane 被命名为 Blinky_Ctor

teturn 类型选择 void

在下面的代码中添加代码结构

Blinky * const me = &AO_Blinky;  QActive_ctor(&me->super, Q_STATE_CAST(&Blinky_initial));//是qpn框架自带的API函数用于类构造

Q_STATE_CAST(&Blinky_initial)是指定初始化状态为Blinky_initial

如图

第 3 步:为对象创建状态机

右击上一步中的Blinky类,选择Add State Machine,创建状态机,双击SM如下图

可以看到Blinky的SM会弹出一个带有网格的状态机工作区。工作区的大小可以通过网格的右下角进行拉伸。

第四步:画出具体的状态实现图

上一步在类中新建了一个状态机,下面需要实现具体的状态图。

刷机程序非常简单。 LED有两种状态:开和关,相互触发的事件有延迟。开和关两种状态只需要等待延迟事件,一旦触发延迟事件,就会执行开灯和关灯的动作。

如下图,右边有个小宽框,就是状态

点击状态图标在Sange工作区创建状态,在Property Editor属性编辑名称中命名为LedOn,如下图

同样的方法建立第二个状态LedOff,如下图

然后点击LedOn的状态图,在属性编辑器属性入口状态机中添加代码进入事件处理

QActive_armX((QActive *)me, 0U, BSP_TICKS_PER_SEC/8U, 0);

和Led改变状态函数UpdataLesState(LedOn);

为退出状态机的退出事件添加代码

QActive_disarmX((QActive *)me, 0U);

QActive_armX((QActive *)me, 0U, BSP_TICKS_PER_SEC/8U, 0)是qpn框架提供的API函数,用来生成(BSP_TICKS_PER_SEC/8U)的Tick延迟,BSP_TICKS_PER_SEC是定义的秒数board Tick,心跳时钟。

QActive_disarmX((QActive *)me, 0U);也是qpn框架系统提供的取消延迟的API函数

同样的方法LedOff也一样,只是将入口事件Led的执行状态改为LedOff即可。

如下图

下一步是创建两个状态之间的转换。右侧状态机图标下方还有一个Transition图标,表示状态转换。

从 LedOn 状态到 LedOff 状态的转换是一个延迟事件,因为 qpn 框架提供了延迟事件的枚举为 Q_TIMEOUT,可以直接使用。

点击图标从LedOn拉伸到LedOff状态状态机c语言编程,在属性编辑器中触发触发到Q_TIMEOUT如下图

最后需要为对象下的状态机指定一个初始化转换,即初始化转换到哪个状态

点击右侧图标 Initial Transition 指定转换到 LedOn 状态如下图

第 5 步:生成 C 代码

首先,你需要为对象创建一个文件声明和定义对象。右键单击模型资源管理器并选择添加目录。在Property Editor属性中,路径指定我命名为Code的目录(默认在项目文件目录下)

然后在Model Explorer中,可以看到Code选项,右键,选择Add File,在Property Editor属性名中命名为Blinky.c

同样的方法创建文件Project.h主要用于事件枚举,包括外部使用的.h文件,以及外部声明对象。

如下图

然后在Blinky.c中定义和声明Blinky对象并初始化,QM中有如下代码生成说明

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论