導(dǎo)言-一個(gè)基于模型的例子
使用Arduino在simulink中搭建的LED閃爍的一個(gè)例子如圖1所示,相比之前C語(yǔ)言代碼實(shí)現(xiàn)的方式,這里沒(méi)有寫(xiě)一行代碼就實(shí)現(xiàn)了LED閃爍。讀者有沒(méi)有感覺(jué)這種開(kāi)發(fā)方式即簡(jiǎn)單又方便,要實(shí)現(xiàn)什么功能就直奔主題,不用一行一行的敲代碼、排查代碼錯(cuò)誤。圖1只是arduino其中的I/O輸出外設(shè),在圖2中還有其它很多外設(shè)可以使用,再結(jié)合matlab強(qiáng)大的功能,讀者可以實(shí)現(xiàn)很多實(shí)際應(yīng)用。
圖1 Arduino-simulink的LED閃爍模型
圖2 simulink中arduino其它外設(shè)的模型
任意單片機(jī)基于模型開(kāi)發(fā)方式
并不是每一個(gè)芯片廠商都有足夠的人力和資金投入到主流開(kāi)發(fā)軟件的生態(tài)適配,目前除了市面上用的比較火的幾款單片機(jī)(STM32、TMS320F28xx、S32K等)和Arduino平臺(tái)可以直接使用Matlab的硬件支持包直接開(kāi)發(fā)外,其它單片機(jī)沒(méi)辦法直接使用,這里給大家介紹一種萬(wàn)能的方式,可以在任意單片機(jī)上使用基于Simulink模型開(kāi)發(fā)方式。
1、8051單片機(jī)上運(yùn)行Simulink模型代碼
第1步:搭建Simulink模型
如圖3 所示,,這里使用了三個(gè)庫(kù),分別是“Delay(延時(shí)模型)”、“Logical Operator-NOT(邏輯操作-非模型)”和“out(輸出端口模型)”,這里的輸出端口為了方便代碼移植將名字改為L(zhǎng)ED。
圖3 LED閃爍simulink模型
第2步:設(shè)置模型生成參數(shù)并生成代碼
如圖4所示,點(diǎn)擊按鈕“Model Configuration Parameters”對(duì)simulink進(jìn)行設(shè)置。
圖4 simulink設(shè)置按鈕
如圖5所示,在彈出的“Configuration Parameters:xxxx”窗口中找到“Solver”欄,并點(diǎn)擊設(shè)置運(yùn)行參數(shù),按照?qǐng)D中的設(shè)置,完成后點(diǎn)擊“Apply”。
圖5 “Solver”欄參數(shù)設(shè)置
如圖6所示,在“Hardware Implementtation”欄中設(shè)置硬件參數(shù),按照?qǐng)D中的設(shè)置進(jìn)行操作,完成后點(diǎn)擊“Apply”。
圖6 “Hardware Implementtation”欄參數(shù)設(shè)置
如圖7所示,點(diǎn)擊“Code Generation”欄,設(shè)置代碼生成參數(shù),完成后點(diǎn)擊“Apply”。
圖7 “Code Generation”參數(shù)設(shè)置
如圖8所示,點(diǎn)開(kāi)“Code Generation”左邊的“>”符號(hào),在子欄目中找到“Code Style”項(xiàng)設(shè)置代碼生成風(fēng)格,完成后點(diǎn)擊“Apply”。
圖8 “Code Style”欄設(shè)置
如圖9所示,點(diǎn)開(kāi)“Code Generation”左邊的“>”符號(hào),在子欄目中找到“Code Placement”中設(shè)置“File packaging format”參數(shù),完成后點(diǎn)擊“Apply”,到這一步,所有參數(shù)都設(shè)置完成,然后點(diǎn)擊“OK”按鈕。
圖9 “Code Placement”欄設(shè)置
如圖10所示,點(diǎn)擊按鈕“Build Model”生成代碼。
圖10 點(diǎn)擊生成模型代碼
代碼生成根據(jù)電腦性能不同,需要的時(shí)間也不一樣,稍等一會(huì)兒,彈出“Code Generation Report”窗口報(bào)告,如圖11所示,在這個(gè)窗口中可以看到整個(gè)模型生成了三個(gè)文件,分別是“ert_main.c”、"LED_Blink.c"和"LED_Blink.h",然后在LED_Blink.slx文件所在的目錄下多了一個(gè)“LED_Blink_ert_rtw”名字的文件夾,生成的三個(gè)文件也包含在當(dāng)中;看這三個(gè)代碼有點(diǎn)像之前講的模塊化編程方式命名。
圖11 LED_Blink模型代碼生成報(bào)告
第3步:將simulink生產(chǎn)的代碼添加到8051單片機(jī)工程中
這一步也是整個(gè)過(guò)程中最關(guān)鍵部分,也是在很多資料中一直沒(méi)講清楚的部分,將生成的代碼移植到51單片機(jī)工程中去。先新建一個(gè)名字(其它名字也可以,只要正確建立Keil工程即可)為“LED_Blink”的Keil工程,工程的存放路徑放在剛剛模型生成代碼"Blink→LED_Blink_ert_rtw“文件夾下,如圖12所示。
圖12 在生成模型文件夾下建一個(gè)Keil工程
打開(kāi)剛剛建立的Keil工程,將ert_main.c和LED_Blink.c文件添加到”Source Group 1“中,如圖13所示。
圖13 模型代碼添加
在剛剛添加的文件中雙擊打開(kāi)ert_main.c,在下面代碼位置處加入8051單片機(jī)的內(nèi)容,代碼如下所示:
#include < stddef.h >
#include < stdio.h > /* This ert_main.c example uses printf/fflush */
#include "LED_Blink.h" /* Model's header file */
#include "rtwtypes.h"
#include < REGX52.H > /* 添加51單片機(jī)頭文件 */
/*********** 變量定義 *************/
#define MAIN_CLOCK 12000000
#define SYSTEM_DELAY 1000 /* 系統(tǒng)周期1ms */
#define LED_TASK_TIME 500 /* SYSTEM_DELAY*0.500 = 500ms任務(wù) */
uint16_T LED_Task_Count = LED_TASK_TIME; /* 任務(wù)定時(shí)器變量 */
void SYSTEM_T0_Init( void ); /* 定時(shí)器0初始化函數(shù) */
添加單片機(jī)代碼
然后在ert_main.c文件中添加定時(shí)器初始化代碼,如下所示:
void SYSTEM_T0_Init( void )
{
/* 定時(shí)器0配置為16位定時(shí)器,當(dāng)溢出時(shí)手工重裝 */
/* 清除所有有關(guān)T0的位 (T1不變) */
TMOD &= 0xF0;
/* 設(shè)置所需的T0相關(guān)位 (T1 不變) */
TMOD |= 0x01;
/* 停止定時(shí)器0 */
TR0 = 0;
/* 設(shè)置定時(shí)器重裝值 */
/* 我們這里設(shè)置1ms產(chǎn)生一次中斷 */
/* 定時(shí)器低8位賦值 */
TL0 = 65536 -(MAIN_CLOCK/SYSTEM_DELAY/12);
/* 定時(shí)器高8位賦值 */
TH0 = (65536-(MAIN_CLOCK/SYSTEM_DELAY/12)) >>8;
/* 啟動(dòng)T0 */
TR0 = 1;
/* 使能定時(shí)器T0中斷 */
ET0 = 1;
}
在ert_main.c中編寫(xiě)定時(shí)器中斷代碼,如下所示:
/*************************************
** 函 數(shù) 名:SYSTEM_Tick_Update() interrupt 1
** 輸入?yún)?shù):none
** 返 回 值:none
** 說(shuō) 明:定時(shí)器T0中斷入口函數(shù)
**************************************/
void SYSTEM_Tick_Update( void ) interrupt 1
{
/* 停止定時(shí)器0 */
TR0 = 0;
/* 設(shè)置定時(shí)器重裝值 */
/* 我們這里設(shè)置1ms產(chǎn)生一次中斷 */
/* 定時(shí)器低8位賦值 */
TL0 = 65536 -(MAIN_CLOCK/SYSTEM_DELAY/12);
/* 定時(shí)器高8位賦值 */
TH0 = (65536-(MAIN_CLOCK/SYSTEM_DELAY/12)) >>8;
/* 啟動(dòng)T0 */
TR0 = 1;
/* LED Task 任務(wù)計(jì)時(shí)器*/
LED_Task_Count--;
}
定時(shí)器中斷函數(shù)代碼
在main主函數(shù)中對(duì)代碼進(jìn)行修改,如下所示:
int_T main()
{
/* Initialize model */
LED_Blink_initialize();
/* 定時(shí)器0 初始化 */
SYSTEM_T0_Init();
/* 使能總中斷,這樣定時(shí)器0才會(huì)啟動(dòng) */
EA = 1;
/* Attach rt_OneStep to a timer or interrupt service routine with
* period 0.2 seconds (the model's base sample time) here. The
* call syntax for rt_OneStep is
*
* rt_OneStep();
*/
while (rtmGetErrorStatus(LED_Blink_M) == (NULL)) {
/* Perform other application tasks here */
if(LED_Task_Count<=0)
{
LED_Task_Count = LED_TASK_TIME;
rt_OneStep();
/*輸入/輸出接口放置位置*/
P1_0 = LED_Blink_Y.LED;
}
}
/* Disable rt_OneStep() here */
/* Terminate model */
LED_Blink_terminate();
return 0;
}
main函數(shù)中代碼
第4步:編譯Keil工程并運(yùn)行代碼
點(diǎn)擊Keil編譯按鈕編譯代碼,然后將代碼燒錄到實(shí)際芯片中或使用Pretous仿真驗(yàn)證代碼。到這里大家就完成了在51單片機(jī)上實(shí)現(xiàn)LED閃爍Simulink模型代碼移植的例子,LED閃爍的頻率實(shí)際由宏定義#define LED_TASK_TIME 500來(lái)控制,在8051單片機(jī)上運(yùn)行該代碼時(shí)LED將以500ms的周期翻轉(zhuǎn)。
2、simulink生成模型代碼剖析
關(guān)于8051單片機(jī)怎么搭建簡(jiǎn)單操作系統(tǒng)框架可以參考網(wǎng)絡(luò)上其他文章或關(guān)注作者的后續(xù)文章,這里就不再贅述,如圖14所示的LED閃爍模型,實(shí)際上就是運(yùn)行模型生成的rt_OneStep()函數(shù),每個(gè)Simulink生成的模型里面都會(huì)有這個(gè)函數(shù),rt_OneStep()運(yùn)行完之后所有通過(guò)輸入端的數(shù)據(jù)都會(huì)在搭建的模型邏輯中處理,然后通過(guò)輸出端輸出處理完后的數(shù)據(jù),在LED閃爍模型中,沒(méi)有輸入端,只有輸出端,所以模型每運(yùn)行完一次,里面的邏輯翻轉(zhuǎn)一次輸出端口LED狀態(tài),即LED_Blink_Y.LED的數(shù)據(jù),然后只需將模型輸出端口與實(shí)際物理端口關(guān)聯(lián)即可,這里關(guān)聯(lián)的是P1_0端口,則最終表現(xiàn)出來(lái)的效果就是P1_0狀態(tài),即模型每運(yùn)行一次,P1_0端口電平發(fā)生一次翻轉(zhuǎn),P1_0端口有連接LED,LED就會(huì)一直閃爍。
圖14 基于模型LED程序執(zhí)行流程
下面再深入到rt_OneStep()函數(shù)詳細(xì)了解下它到底在里面做了什么事情,是不是與前面所說(shuō)的一致,rt_OneStep()函數(shù)詳細(xì)內(nèi)容,函數(shù)中的其它內(nèi)容暫時(shí)不管,可以看到里面關(guān)鍵的一步,調(diào)用了LED_Blink_step()函數(shù),具體代碼如下所示:
void rt_OneStep(void)
{
static boolean_T OverrunFlag = false;
/* Disable interrupts here */
/* Check for overrun */
if (OverrunFlag) {
rtmSetErrorStatus(LED_Blink_M, "Overrun");
return;
}
OverrunFlag = true;
/* Save FPU context here (if necessary) */
/* Re-enable timer or interrupt here */
/* Set model inputs here */
/* Step the model */
LED_Blink_step();
/* Get model outputs here */
/* Indicate task complete */
OverrunFlag = false;
/* Disable interrupts here */
/* Restore FPU context here (if necessary) */
/* Enable interrupts here */
}
然后再到LED_Blink_step()函數(shù)中查看具體內(nèi)容,在主函數(shù)中調(diào)用的LED_Blink_Y.LED在該函數(shù)中可以找到具體的邏輯。至此,LED閃爍模型的整個(gè)代碼分析完成。其它模型也可以采用類(lèi)似的方式來(lái)分析,具體代碼如下所示:
void LED_Blink_step(void)
{
boolean_T rtb_Delay;
/* Delay: '< Root >/Delay' */
rtb_Delay = LED_Blink_DW.Delay_DSTATE[0];
/* Outport: '< Root >/LED' incorporates:
* Delay: '< Root >/Delay'
*/
LED_Blink_Y.LED = LED_Blink_DW.Delay_DSTATE[0];
/* Update for Delay: '< Root >/Delay' incorporates:
* Logic: '< Root >/Logical Operator'
*/
LED_Blink_DW.Delay_DSTATE[0] = LED_Blink_DW.Delay_DSTATE[1];
LED_Blink_DW.Delay_DSTATE[1] = !rtb_Delay;
}
-
單片機(jī)
+關(guān)注
關(guān)注
6035文章
44554瀏覽量
634652 -
C語(yǔ)言
+關(guān)注
關(guān)注
180文章
7604瀏覽量
136692 -
Simulink
+關(guān)注
關(guān)注
22文章
533瀏覽量
62380 -
模型
+關(guān)注
關(guān)注
1文章
3226瀏覽量
48809 -
Arduino
+關(guān)注
關(guān)注
188文章
6468瀏覽量
186954
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論