完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
简介
QP由Quantum Leaps公司开发异于传统顺序式系统(前后台架构即main+ISR)和传统多任务系统(操作系统)的事件驱动型状态机框架,实现了在C语言下的面向对象编程,该框架支持有限状态机FSM和层次式状态机HSM。 QP大体的框架如下图 对于开发者使用该框架的开发步骤如下:
如下图所示 QpNano 接下来简单介绍下QpNano,因为我的建模是使用QpNano,它是由事件驱动型框架下的裁剪版本,顾名思义,是针对资源有限的单片机。如低端的8位和16位单片机8051,PIC,AVR,MSP,STM8等当然也适应于32位处理器。 下面介绍如何在StateMachines板上运用QP官网上Blinky(闪灯)的例程之前简单介绍下StateMachines板的资源:
简单介绍完QP和QpNano后,下面才是我要重点推荐使用QP框架的原因。QP框架允许完全手工编程和使用自动生成代码工具QM。QM(QP™ Modeler)建模是基于QP框架和层次式状态机UML语言图形自动代码生成工具,可以在该软件下实现各个对象的状态机和事件交换,而状态机实现方式是使用UML图形,真正做到应用层使用图形编程,更适合我们的编程思维。 Blinky例程是一个LED闪灯程序,是学习QP、QM最基本的例程,以下是使用qm_3.3.0-win64下建立Blinky模型: 第一步在QM中新建工程 如下图所示在File菜单下点击New Modle新建一个QM工程,然后在弹出的页面Frameworks下选择使用qpn即qp-nano框架,Templates模板选择None,Name我暂且命名为Project,Location选择工程保存位置 点击OK后可以看到已经生成了Project的项目如下图所示 第二步:建立对象 在上一步骤中生成的工程左上角Mode Explorer下Project处鼠标右键选择Add Package建立一个包,在Property Editor处nane命名为AOs, stereotype选择components如下图所示 然后在AOs处鼠标右键选择Add Class建立一个类,在Property Editor处nane命名为Blinky, superclass 处选择qpn::QActive,如下图所示 接着在AOs处鼠标右键选择Add Attribute增加属性,在Property Editor处nane处命名为AO_ Blinky,type为struct Blinky,即使Blinky类的具体实例对象 如下图所示 接着在AOs处鼠标右键选择Add Operation增加类构造,在Property Editor处 nane处命名为Blinky_Ctor teturn type 选择void 在下方Code处具体添加代码构造 Blinky * const me = &AO_Blinky; QActive_ctor(&me->super, Q_STATE_CAST(&Blinky_initial)); //是qpn框架自带的API函数用于类构造 Q_STATE_CAST(&Blinky_initial)是指定初始化状态为Blinky_initial 如图所示 第三步:为对象建立状态机 在上一步骤的类Blinky处右键选择Add State Machine建立状态机,双击SM如下图所示 可以看到有会弹出SM of Blinky带有珊格的状态机工作区域,工作区域小大可由珊格最右下角拉伸。 第四步:画具体状态实现图 在上一步骤中已经在类里新建了一个状态机,下面需要实现具体的状态图。 闪灯程序非常简单,LED有两种状态即亮与灭,互相触发的事件为延时。亮与灭的两种状态只要等待延时事件,延时事件一旦触发就执行亮灯灭灯的动作。 如下图所示在右方有一个小宽框即为状态 点击该状态图标到珊格工作区域建立一个状态,在Property Editor属性编辑name处命名为LedOn如下图所示 同样的方法建立第二个状态LedOff,如下图所示 然后点击LedOn该状态图,在Property Editor属性编entry状态机进入事件处理中加入代码 QActive_armX((QActive *)me, 0U, BSP_TICKS_PER_SEC/8U, 0); 和Led改变状态函数UpdataLesState(LedOn); 在exit状态机退出事件中加入代码 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是板子定义每秒多少个Tick,即心跳时钟。 QActive_disarmX((QActive *)me, 0U); 也是qpn框架系统提供的API函数,用于取消延时 相同的方法LedOff也是如此,将entry事件Led执行状态改为LedOff即可。 如下图所示 接下来就要使两个状态建立转换了同样在右方状态机图标下方有一个Transition图标表示状态转换迁移。 从LedOn状态转换到LedOff状态是延时事件,因为qpn框架提供了延时事件的枚举为Q_TIMEOUT,可以直接使用。 点击图标,从LedOn拉伸至LedOff状态,并在属性编辑里trigger触发为Q_TIMEOUT如下图所示 最后需要为该对象下的状态机指定一个初始化转移,即初始化转换到哪一个状态 点击右方图标Initial Transition指定为转换到LedOn状态如下图所示 第五步:生成C代码 首先需要为对象建立一个文件声明和定义对象,在Model Explorer中鼠标右键选择Add Directory,在Property Editor属性中path指定目录我命名为Code(默认是在建立工程文件目录下) 然后在Model Explorer可以看到Code选项右键选择Add File,并在Property Editor属性name中命名为Blinky.c 同样的方法建立文件Project.h主要用于事件枚举、包含外部使用到的.h文件、外部声明对象。 如下图所示 接着在Blinky.c中定义和声明Blinky对象和初始化,QM中有以下代码生成指令 $declare() 声明 $define() 定义 如图所示 最后点击工具栏Tools选择Generate Code或直接按F7生成C代码 第六步:将QM生成代码加入到项目工程中 首先需要将qpn移植到STM32F030中,我使用qpn合作式内核,只需要在SysTick_Handler加入qpn 定时服务API QF_tickXISR(0)并在QF_onStartup()函数中加入SysTick配置中断时间和优先级。 如图所示 然后需要为Blinky对象分配事件队列内存,并制定整个项目中所使用到的活动对象个数本例程只有一个在#include "qpn_conf.h" 宏定义QF_MAX_ACTIVE配置。 如图所示 整个Blinky QM建模由
介绍完成,看起来一个非常简单的闪灯程序由QM生成非常耗时,不如自己敲几行代码来的快,但这是飞跃,逻辑代码层完全由图形实现,意味着以后不同复杂的项目都可以使用图形来管理并且图形比起代码来说更加易懂和维护,图形编程是以后的方向。 |
|
|
|
只有小组成员才能发言,加入小组>>
imx6ull 和 lan8742 工作起来不正常, ping 老是丢包
2573 浏览 0 评论
3346 浏览 9 评论
3025 浏览 16 评论
3518 浏览 1 评论
9126 浏览 16 评论
1248浏览 3评论
640浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
629浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2379浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1944浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-1-28 08:26 , Processed in 1.148069 second(s), Total 77, Slave 58 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (威廉希尔官方网站 图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号