QM UML状态机建模实例之Blinky for cortex-m0

2023-11-01 21:59

本文主要是介绍QM UML状态机建模实例之Blinky for cortex-m0,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

关注、星标公众号,直达精彩内容

来源:全然电子

整理:李肖遥

    QP事件状态机框架论坛已经有很多教程了,加上已经有中文版本的书籍学习QP相对来说多花一些时间就能入门,有经验的攻城狮们可能忙于工作无法学习更多的技术,使用QP框架的好处可能仍不会让您动心,但是如果现在有一款能自动生成代码的图形编辑软件呢?是不是会有那么点心动,虽然不能完全脱离代码,但是至少应用层可以完全使用使用该软件来完成,我要推荐就是QM软件,一个基于QP框架UML语言的状态机图形编程软件,下面是我使用QM开发官方Blingy闪灯的基本教程。

简介

QP由Quantum Leaps公司开发异于传统顺序式系统(前后台架构即main+ISR)和传统多任务系统(操作系统)的事件驱动型状态机框架,实现了在C语言下的面向对象编程,该框架支持有限状态机FSM和层次式状态机HSM。


QP大体的框架如下图
 
对于开发者使用该框架的开发步骤如下:

  1. 理解整个项目需求

  2. 顺序图,划分出具有行为的活动对象并且将系统的资源分配到各个活动对象中,降低对象间的耦合,整理出各个活动对象间的事件交换

  3. 信号和事件的枚举,各个活动对象间的事件交换和自身对象下的触发信号事件。信号是只有触发信号而事件是带有参数的信号触发例如串口接收不仅有串口接收这一触发事件并且还有与之一起的数据

  4. 各个活动对象下的具体状态机实现

  5. 初始化并启动应用程序 给事件列队分配内存,初始化活动对象分配优先级最后启动QP将系统控制权交给QP管理,QP则根据你的事件触发来执行各个活动对象下的状态机

  6. 调试


如下图所示
 
更多关于QP的资料请看点击http://www.state-machine.com/psicc2/index.html,里面有电子版本的PSiCC2-CN文档详细介绍了整个QP框架

QpNano

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


下面介绍如何在StateMachines板上运用QP官网上Blinky(闪灯)的例程之前简单介绍下StateMachines板的资源:

  1. 使用STM32F030C8T6 Cortex-m0处理器

  2. 板载按键、12864液晶屏、字库、数码管、串口转USB,LED灯

    简单介绍完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中新建工程

  • 第二步:建立对象

  • 第三步:为对象建立状态机

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

  • 第五步:生成C代码

  • 第六步:将QM生成代码加入到项目工程中

介绍完成,看起来一个非常简单的闪灯程序由QM生成非常耗时,不如自己敲几行代码来的快,但这是飞跃,逻辑代码层完全由图形实现,意味着以后不同复杂的项目都可以使用图形来管理并且图形比起代码来说更加易懂和维护,图形编程是以后的方向。


版权归原作者所有,如有侵权,请联系删除。

‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧  END  ‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧

推荐阅读:

嵌入式编程专辑Linux 学习专辑C/C++编程专辑
Qt进阶学习专辑

关注我的微信公众号,回复“加群”按规则加入技术交流群。


点击“阅读原文”查看更多分享。

这篇关于QM UML状态机建模实例之Blinky for cortex-m0的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/326033

相关文章

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

基于UE5和ROS2的激光雷达+深度RGBD相机小车的仿真指南(五):Blender锥桶建模

前言 本系列教程旨在使用UE5配置一个具备激光雷达+深度摄像机的仿真小车,并使用通过跨平台的方式进行ROS2和UE5仿真的通讯,达到小车自主导航的目的。本教程默认有ROS2导航及其gazebo仿真相关方面基础,Nav2相关的学习教程可以参考本人的其他博客Nav2代价地图实现和原理–Nav2源码解读之CostMap2D(上)-CSDN博客往期教程: 第一期:基于UE5和ROS2的激光雷达+深度RG

C++操作符重载实例(独立函数)

C++操作符重载实例,我们把坐标值CVector的加法进行重载,计算c3=c1+c2时,也就是计算x3=x1+x2,y3=y1+y2,今天我们以独立函数的方式重载操作符+(加号),以下是C++代码: c1802.cpp源代码: D:\YcjWork\CppTour>vim c1802.cpp #include <iostream>using namespace std;/*** 以独立函数

实例:如何统计当前主机的连接状态和连接数

统计当前主机的连接状态和连接数 在 Linux 中,可使用 ss 命令来查看主机的网络连接状态。以下是统计当前主机连接状态和连接主机数量的具体操作。 1. 统计当前主机的连接状态 使用 ss 命令结合 grep、cut、sort 和 uniq 命令来统计当前主机的 TCP 连接状态。 ss -nta | grep -v '^State' | cut -d " " -f 1 | sort |

数学建模笔记—— 非线性规划

数学建模笔记—— 非线性规划 非线性规划1. 模型原理1.1 非线性规划的标准型1.2 非线性规划求解的Matlab函数 2. 典型例题3. matlab代码求解3.1 例1 一个简单示例3.2 例2 选址问题1. 第一问 线性规划2. 第二问 非线性规划 非线性规划 非线性规划是一种求解目标函数或约束条件中有一个或几个非线性函数的最优化问题的方法。运筹学的一个重要分支。2

Java Websocket实例【服务端与客户端实现全双工通讯】

Java Websocket实例【服务端与客户端实现全双工通讯】 现很多网站为了实现即时通讯,所用的技术都是轮询(polling)。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发 出HTTP request,然后由服务器返回最新的数据给客服端的浏览器。这种传统的HTTP request 的模式带来很明显的缺点 – 浏 览器需要不断的向服务器发出请求,然而HTTP

828华为云征文|华为云Flexus X实例docker部署rancher并构建k8s集群

828华为云征文|华为云Flexus X实例docker部署rancher并构建k8s集群 华为云最近正在举办828 B2B企业节,Flexus X实例的促销力度非常大,特别适合那些对算力性能有高要求的小伙伴。如果你有自建MySQL、Redis、Nginx等服务的需求,一定不要错过这个机会。赶紧去看看吧! 什么是华为云Flexus X实例 华为云Flexus X实例云服务是新一代开箱即用、体

OCC开发_变高箱梁全桥建模

概述     上一篇文章《OCC开发_箱梁梁体建模》中详细介绍了箱梁梁体建模的过程。但是,对于实际桥梁,截面可能存在高度、腹板厚度、顶底板厚度变化,全桥的结构中心线存在平曲线和竖曲线。针对实际情况,通过一个截面拉伸来实现全桥建模显然不可能。因此,针对变高箱梁,本文新的思路来实现全桥建模。 思路 上一篇文章通过一个截面拉伸生成几何体的方式行不通,我们可以通过不同面来形成棱柱的方式实现。具体步骤

UML- 统一建模语言(Unified Modeling Language)创建项目的序列图及类图

陈科肇 ============= 1.主要模型 在UML系统开发中有三个主要的模型: 功能模型:从用户的角度展示系统的功能,包括用例图。 对象模型:采用对象、属性、操作、关联等概念展示系统的结构和基础,包括类图、对象图、包图。 动态模型:展现系统的内部行为。 包括序列图、活动图、状态图。 因为要创建个人空间项目并不是一个很大的项目,我这里只须关注两种图的创建就可以了,而在开始创建UML图

LLVM入门2:如何基于自己的代码生成IR-LLVM IR code generation实例介绍

概述 本节将通过一个简单的例子来介绍如何生成llvm IR,以Kaleidoscope IR中的例子为例,我们基于LLVM接口构建一个简单的编译器,实现简单的语句解析并转化为LLVM IR,生成对应的LLVM IR部分,代码如下,文件名为toy.cpp,先给出代码,后面会详细介绍每一步分代码: #include "llvm/ADT/APFloat.h"#include "llvm/ADT/S