QM UML狀態機建模實例之Blinky for cortex-m0


簡介:
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.她是由事件驅動型框架下的裁剪版本,顧名思義,是針對資源有限的單片機。如低端的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生成非常耗時,不如自己敲幾行代碼來的快,但這是飛躍,邏輯代碼層完全由圖形實現,意味着以后不同復雜的項目都可以使用圖形來管理並且圖形比起代碼來說更加易懂和維護,圖形編程是以后的方向。

如須了解更多關於StateMachines板信息請淘寶搜索 “QP學習板”找到全然電子或加入扣扣群129063491交流QM UML QP狀態機等技術。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM