QM法化简C语言程序,QM基础教程
中文翻譯教程首發CSDN,轉載請標明出處:http://www.voidcn.com/article/p-qbuyghua-bpr.html
NOTE:本中文教程相對官方原版教程,刪減了Building Blinky on Windows/Linux 這章,讀者可以參考我的另外一篇博文《使用QM的外部工具功能編譯代碼》中gcc的例子,其次增加了Add Free Operation章
這個教程介紹了怎么使用QM建模,并實現一個簡單的、可以在嵌入式板子上閃爍一個LED的或者在桌面環境能夠下打印LED的狀態轉換的”Blinky”應用。
NOTE:這個教程是使用的是QP/C框架(version 5).在其它的QP框架下運行也是類似
Blinky on TivaC LaunchPad
Creating New Model
打開File->Model…菜單或者點擊在Edit Toolbar上的
按鈕。接下來將會打開New Model Dialog Box窗口:
New Model dialog
選擇model基于那個 QP framework type (“Frameworks” 面板)。這里可以選擇:qpc for QP/C?, qpcpp for QP/C++?, and qpn for QP-nano?。在這個教程中,你保留默認的qpc framewords type。
給model命名(“Name:” 框)。NOTE:.qm后綴名會自動添加。在這個教程中,重命名model為blinky。
選擇model文件存放的目錄(“Location:” 框)。你可以手動輸入目錄路徑,也可以點擊右側圖標選擇路徑。NOTE:model的路徑也是生成代碼的地方。所有成的目錄和文件都是相對于model文件目錄來說的。
點擊OK按鈕。
Adding Model Items
現在你可以開始添加items到一個新的model中。
Add a Package
第一個要添加的是Package。在UML中package是一個組結構,用于合并其他model items到一個higher-level單元。它一般用來將classes組合到一起,但package同樣可以持有free attributes,free operations,和其他的packages。
在 Model Explorer 窗口右擊blinky item,在彈出菜單中,選擇Add Package。
`
Add Package
在Property Editor窗口中修改package的名字為AOs(Active Objects),并選擇stereotype為components。
`
Package Properties
Add a Class
接下來添加一個class到新的package中,因為只有class可以擁有行為 (i.e.,State Machines).
在Model Explorer窗口下右擊AOs package并在彈出菜單中選擇Add Class
`
Add Class
在Property Editor窗口中修改class名字為Blinky,并且選擇superclass為qpc::QMActive.
Setting Superclass
NOTE:
在QM? 一個狀態機只可以和繼承QP state machine classes的class相關聯。所選擇的狀態機superclass決定狀態機實現策略.
Add a Time Event
通過添加一個Time Event,以便傳遞周期事件到目標的blinky狀態機中的blinking狀態。
在Model Explorer窗口下右擊Blinky類,并在彈出菜單中選擇Add Attribute
`
Adding Attribute
在Property Editor窗口中修改attribute的名字為timeEvt,類型為QTimeEvt,visibility選擇為private。
`
Attribute Properties
Add Free Operation (改動:新增)
增加一個Free Operation可以生成對應的普通函數,提供調用。
在Model Explorer窗口下右擊AOs Package
`
Add Free Operation
在Property Editor窗口中修改Operation的名字為Blinky_ctor,并選擇return type為void。添加如下代碼:
Blinky * const me = &l_blinky;
QMActive_ctor(&me->super, Q_STATE_CAST(&Blinky_initial));
QTimeEvt_ctorX(&me->timeEvt, &me->super, TIMEOUT_SIG, 0U);
`
Operation Properties
Note 1:
上面的代碼第二行的構造函數,應該和對應的類所選用的superclass一致
QMActive_ctor()對應qpc::QMActive
QActive_ctor()對應qpc::QActive
QMsm_ctor()對應qpc::QMsm
QHsm_ctor()對應qpc::QHsm
這幾個構造函數的參數都是一致的。
Note 2:
之所以使用Operation定義構造函數,而不是在對應的源文件中手動定義,其中一個原因可能是因為free Operation和class同在AOs下,修改class的superclass后,很容易就找到對應的構造函數進行修改。無需翻看源文件。
Add State Machine
在Model Explorer窗口下右擊Blinky類,并在彈出菜單中選擇Add Start Machine
`
Adding State Machine
Drawing State Machine Diagram
在Property Editor窗口中右擊SM狀態機,并在彈出菜單中選擇Show Diagram(顯示圖表)。另外你可以雙擊SM狀態機執行默認動作:Show Diagram
`
Show State Machine Diagram
Add States
在Diagram Toolbox 點擊選中state工具,移動鼠標(不用按下左鍵)到diagram窗口合適的地方,這里選擇左上角。注意到現在鼠標的形狀發生了變化(如下圖)。按下鼠標左鍵放置state形狀,然后鼠標右鍵不要放松,往右下角拖動改變大小。釋放鼠標。
`
Adding the off State
在Property Editor窗口中修改state的名字為off,并增加entry動作BSP_ledOff();到這個狀態。
使用類似的方法添加第二個state。在Property Editor窗口中修改state的名字為on,并增加entry動作BSP_ledOn();到這個狀態。
`
Setting Properties of State ‘off’
Add Initial Transition
在Diagram Toolbox 點擊選中initial transition工具。移動鼠標(不用按下左鍵)到diagram窗口合適的地方。注意到現在鼠標的形狀發生了變化(如下圖)。按下鼠標左鍵,并拖動它(長按左鍵)到state的邊緣。注意鼠標形狀變化在接觸到邊緣后。釋放鼠標。
`
Adding the Initial Transition
在Property Editor窗口中給Initial Transition 增加動作QTimeEvt_armX(&me->timeEvt, BSP_TICKS_PER_SEC/2, BSP_TICKS_PER_SEC/2);
Note
在Initial Transition的動作代碼為起始BSP_TICKS_PER_SEC/2次clock ticks,和其后每次BSP_TICKS_PER_SEC/2次clock ticks投遞time event。
Add Transitions
在Diagram Toolbox 點擊選中transition工具。移動鼠標(不用按下左鍵)到diagram窗口合適的地方。注意到現在鼠標的形狀發生了變化(如下圖)。按下鼠標左鍵,并拖動它(長按左鍵)到state的邊緣。注意鼠標形狀變化在接觸到邊緣后。釋放鼠標。
`
Adding a Transition
在Property Editor窗口中修改這個transition的trigger為TIMEOUT。
使用類似的方法添加第二個transition并改變它的trigger為TIMEOUT。
`
Complete State Machine
Generating Code
相比于其他的圖形化狀態機工具,QM? 讓生成代碼”上下顛倒(upside down)”了.QM? 讓你確定生成代碼的結構,目錄名,文件名和進入文件里的每個元素(看物理設計)。你可以混合你自己的代碼到生成代碼中,并使用QM生成你覺得合適的,盡可能多或者盡可能少的總代碼。
Add Directory
首先需要創建一個目錄,這個目錄的設置決定了生成代碼相對于
·
Adding a Directory
在Model Explorer窗口下右擊Blinky model項,并在彈出菜單中選擇Add Directory。這將會是代碼生成的目錄。目錄的路徑參考于QM Model File并可以在Property Editor中編輯。在directory中填入”.”符號,代表了生成的代碼使用和QM Model File相同的目錄。
Add File
在directory里可以添加Files。在實際的項目中,通常會將代碼分成頭文件和源文件,并使用獨立的源文件作為板級支持包(BSP)和mian()。但為了簡單起見,這個教程在會在下面的步驟中,將會將他們都放到一個文件里:blinky.c里:
Adding a File
在Model Explorer窗口下右擊directory項,并在彈出菜單中選擇Add File。在這個文件創建后,你可以在Property Editor里編輯它的名字為blinky.c
Edit File (改動:手工代碼,增加ctor函數的生成)
你需要為QP?每個file-template提供一個前體(body),在其中你可以輸入自己的代碼以及代碼生成指令。下面的代碼將會演示最重要的兩個指令 $declare(AOs::Blinky)用于生成Blinky class的聲明;$define(AOs::Blinky) 用于生成Blinky class的定義和$define(AOs::Blinky_ctor)用于生成對應的構造函數。
#include "qp_port.h"
#include
#include
#define BSP_TICKS_PER_SEC 100
void BSP_ledOff(void) {
printf("LED OFF\r\n");
}
void BSP_ledOn(void) {
printf("LED ON\r\n");
}
void Q_onAssert(char const Q_ROM * const Q_ROM_VAR file, int line) {
fprintf(stderr, "Assertion failed in %s, line %d", file, line);
exit(0);
}
void QF_onStartup(void) {}
void QF_onCleanup(void) {}
void QF_onClockTick(void) {
QF_TICK((void *)0);
}
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;
/*************** ask QM to define the Blinky_ctor operation *********/
$define(AOs::Blinky_ctor)
/*************** ask QM to define the Blinky class ******************/
$define(AOs::Blinky)
int main() {
static QEvt const *blinky_queueSto[10];
Blinky_ctor();
QF_init();
QActive_start(AO_Blinky, 1U,
blinky_queueSto, Q_DIM(blinky_queueSto),
(void *)0, 1024U, (QEvt *)0);
return QF_run();
}
`
Creating a Fully-Qualified Item Name by Drag-n-Drop
Opening blinky.c File and Pasting the Code
Generate Code
點擊工具條中的Generate Code按鍵,生成代碼。
Code Generation
這時QM已經在blinky.qm這個QM Model File相同的目錄下生成了代碼。可以使用一個代碼編輯器對代碼進行查看。
Building the Project (改動:刪除)
總結
以上是生活随笔為你收集整理的QM法化简C语言程序,QM基础教程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 农村医保自己怎么交 报销时要提供这些材料
- 下一篇: 开通京东金条有风险吗