嵌入式 開發(fā) 軟件(嵌入式開發(fā)軟件有哪些)
提示:文章撰寫完成后,可以自動(dòng)生成目錄,如何生成請(qǐng)參考右側(cè)幫助文檔。
目錄
前言
在嵌入式開發(fā)中,利用Simulink的相關(guān)功能模塊搭建好邏輯流程之后,很重要的一個(gè)步驟就是利用代碼生成功能將我們搭建好的函數(shù)轉(zhuǎn)換成代碼,并與嵌入式平臺(tái)的芯片軟件工程進(jìn)行融合,使得我們開發(fā)出來(lái)的函數(shù)能夠在單片機(jī)上運(yùn)行,??從而實(shí)現(xiàn)產(chǎn)品的功能需求。
1. 項(xiàng)目創(chuàng)建
本次用Simulink搭建的項(xiàng)目目標(biāo)產(chǎn)品是車載智能保險(xiǎn)絲盒,前兩篇文章中的CAN模塊、雨刮器模塊都是該項(xiàng)目的函數(shù),這些函數(shù)通過(guò)一個(gè)完整的Simulink項(xiàng)目進(jìn)行組裝和管理,函數(shù)之間以文件夾的形式,將相關(guān)的函數(shù)文件統(tǒng)一歸類,我的理解是這樣建立的工程和編輯代碼時(shí)在編譯器中建立的工程類似。
和在KEIL或者IAR中編譯運(yùn)行一樣,simulink工程也可以進(jìn)行模型測(cè)試、依賴檢查、運(yùn)行檢查等。版本管理也集成了SVN或者git,簡(jiǎn)單設(shè)置即可實(shí)現(xiàn)。我使用SVN進(jìn)行版本管理,不過(guò)一般都是直接復(fù)制文件夾進(jìn)行更新、提交即可。
2. 代碼生成 1. 構(gòu)建模塊
各個(gè)模塊的操作都一樣,設(shè)置參數(shù)和操作。本文以近光模塊為例進(jìn)行說(shuō)明,主要是因?yàn)榻饽K功能比較簡(jiǎn)單,信號(hào)量小,邏輯簡(jiǎn)單,主要信號(hào)如下:
輸入信號(hào):
1. 點(diǎn)火開關(guān)IGN信號(hào)
2. 大燈電源信號(hào)
3. 近光燈開關(guān)信號(hào)
4.短路判斷信號(hào)
5.開路判斷信號(hào)
6. 消息刷新標(biāo)志
輸出信號(hào):
1.近光繼電器控制信號(hào)
2. CAN 報(bào)文信號(hào)
3. 消息發(fā)送標(biāo)志
消息刷新標(biāo)志和消息發(fā)送標(biāo)志是系統(tǒng)內(nèi)部判斷信號(hào),不作為對(duì)外輸出,相當(dāng)于寫代碼時(shí)設(shè)置的標(biāo)志位是局部變量。
功能邏輯結(jié)構(gòu)如下:
總體結(jié)構(gòu)
2. 內(nèi)部結(jié)構(gòu)
三狀態(tài)流
函數(shù)搭建完成后點(diǎn)擊RUN圖標(biāo),若無(wú)報(bào)錯(cuò)則證明語(yǔ)法結(jié)構(gòu)正確,滿足生成代碼的前提條件。至于控制邏輯是否正確,可以通過(guò)搭建儀表盤上的指示燈進(jìn)行仿真,仿真方法請(qǐng)參考上一篇文章《Simulink模型實(shí)現(xiàn)汽車雨刮器基本功能并仿真》。
2.設(shè)置參數(shù)
點(diǎn)擊工具欄模型設(shè)置的齒輪圖標(biāo),進(jìn)入?yún)?shù)設(shè)置界面
以本項(xiàng)目中嵌入代碼的生成為例,主要需要調(diào)整的參數(shù)設(shè)置如下:
在求解器下,選擇求解器選擇,類型選擇固定步長(zhǎng),求解器選擇離散
細(xì)節(jié)選項(xiàng)fixed-step size設(shè)置為0.01,采樣步長(zhǎng)為0.01s。這個(gè)參數(shù)和嵌入式工程中函數(shù)循環(huán)調(diào)用的頻率有關(guān),以本工程為例,設(shè)置為0.01s表示每10ms調(diào)用一次該函數(shù)。如果不按照設(shè)置值進(jìn)行定時(shí)中斷,將會(huì)影響模塊中的定時(shí)操作。
代碼生成選項(xiàng)中主要有兩個(gè)參數(shù)需要注意,一是System target file選擇為ert.tlc,二是Language選擇為C語(yǔ)言。
在Report選項(xiàng)中選擇Generate Code Report,一般前兩項(xiàng)分別是Generate Report和Automatically Open,第三項(xiàng)Web View是可選的。
根據(jù)使用的MCU型號(hào),我們需要在Hardware Implementation中選擇對(duì)應(yīng)的MCU廠商和內(nèi)核類型。本工程采用的是NXP,cortexM4核心的S32k148芯片,選擇對(duì)應(yīng)的選項(xiàng)即可。這里的選擇不像Keil等編譯器那么詳細(xì),主要就是確定MCU的一些數(shù)據(jù)類型定義的位數(shù),是否支持長(zhǎng)整型等,點(diǎn)擊detail可以查看詳細(xì)信息。
3.自動(dòng)生成
完成以上步驟后,就可以生成代碼了,首先在APP選項(xiàng)中選擇內(nèi)嵌的coder功能卡,如下圖:
選擇進(jìn)入嵌入式編碼器APP
單擊“Build”按鈕生成嵌入式 C 代碼
代碼生成之后會(huì)自動(dòng)出現(xiàn)在右側(cè),方便我們查看。
因?yàn)槲覀児催x了生成報(bào)告選項(xiàng),所以會(huì)出現(xiàn)一個(gè)報(bào)告對(duì)話框,在報(bào)告中可以查看此模塊生成的代碼的相關(guān)內(nèi)容,包括代碼預(yù)覽,模型信息,內(nèi)存使用情況等信息。
在生成的代碼中我們可以看到很多文件,但是主要用到的是LowBeam.c和LowBeam.h這兩個(gè)文件,除了ert_main之外的其他文件大家可以忽略,直接復(fù)制到我們自己的代碼工程目錄下即可。我們不需要ert_main,使用我們自己的main函數(shù),但是大家可以參考ert_main中函數(shù)函數(shù)的調(diào)用方法。
3. 代碼集成
按照上面的方法自動(dòng)生成代碼之后,還差最后一步就能成功使用了,就是把這些文件添加到工程中,并與驅(qū)動(dòng)代碼進(jìn)行匹配。針對(duì)這個(gè)芯片,其他同事已經(jīng)進(jìn)行了平臺(tái)開發(fā),并提供了相關(guān)接口,包括ADC、GPIO、CAN等資源都已經(jīng)封裝好了,我們需要做的就是接口對(duì)應(yīng)。以近光功能模塊為例,LowBeam.c文件幾乎可以忽略不計(jì),它是Matlab軟件根據(jù)我們搭建的Simulink邏輯自動(dòng)生成的代碼,可讀性不是很強(qiáng),但是功能肯定是實(shí)現(xiàn)了的,我們會(huì)對(duì)應(yīng)好接口,只關(guān)注LowBeam.h文件就行。
在.h文件中找到以下代碼:
/* external inputs (root inport signals with default storage) */typedef struct { IGN IG; /* '/IGN' */ uint8_T Front_Power_Supply; /* '/Front_Power_Supply' */ uint8_T Work_Cmd; /* '/Work_Cmd' */ uint8_T IS_Opencircuit; /* '/DILAMP_Open' */ uint8_T IS_Shortcircuit; /* '/DILAMP_Short' */ uint8_T New_Can_Flag; /* '/New_Can_Flag' */} ExtU_LowBeam_T;/* External outputs (root outports fed by signals with default storage) */typedef struct { uint8_T Low_Beam_On; /* '/Low_Beam_On' */ uint8_T Can_Send_Flag; /* '/Can_Send_Flag' */ CAN_MESSAGE_BUS CAN_Msg_HighBeam; /* '/CAN_Msg_HighBeam' */} ExtY_LowBeam_T;
ExtU_LowBeam_T表示輸入信號(hào)的結(jié)構(gòu)體,ExtY_LowBeam_T表示輸出信號(hào)的結(jié)構(gòu)體,均以全局變量的形式賦值。
我們自己寫一個(gè)賦值函數(shù):
/*近光燈模塊*/ LowBeam_U.New_Can_Flag = (uint8_T)can_status_store.bit.store_Newflag_LowBeam; LowBeam_U.Front_Power_Supply = (FrontLampTogether_Y.Left_Together_ON & FrontLampTogether_Y.Right_Together_ON); LowBeam_U.Work_Cmd = CAN_Receive_Model_Y.LowBeam_WorkCmd; LowBeam_U.IG = CAN_Receive_Model_Y.IGN_Sig; LowBeam_U.IS_Opencircuit = (Output_Current_U.DILamp_FL_DRV < LOWBEAM_CURRENT_MIN) || (Output_Current_U.DILamp_FR_DRV < LOWBEAM_CURRENT_MIN) ? 1: 0; LowBeam_U.IS_Shortcircuit = (Output_Current_U.DILamp_FL_DRV > LOWBEAM_CURRENT_MAX) || (Output_Current_U.DILamp_FR_DRV > LOWBEAM_CURRENT_MAX) ? 1: 0;
涉及到一些其他模塊的信號(hào),但這些都是獨(dú)立的全局變量,可以直接用于邏輯判斷。
輸出信號(hào):
if(LowBeam_Y.Low_Beam_On == 1) { HSD_SET_LEFT_LOWBEAM_ON; //打開左近光燈 HSD_SET_RIGHT_LOWBEAM_ON; //打開又近光燈 } else { HSD_SET_LEFT_LOWBEAM_OFF; //關(guān)閉左近光燈 HSD_SET_RIGHT_LOWBEAM_OFF; //關(guān)閉右近光燈 }
輸出函數(shù)已經(jīng)封裝好了,這里直接調(diào)用就可以。
對(duì)于總線信號(hào),編寫一個(gè)賦值函數(shù):
void set_can_LowBeam_output(void) { if(LowBeam_Y.Can_Send_Flag) { if(can_send_output_set(CAN_INSTANCE_SET, &LowBeam_Y.CAN_Msg_HighBeam) == CAN_EOK) //發(fā)送報(bào)文 { LowBeam_Y.Can_Send_Flag = 0; } }}
這里我們直接使用發(fā)送消息的接口函數(shù)can_send_output_set()。
最后在main函數(shù)中調(diào)用該函數(shù),我們可以在生成的LowBeam.h文件中看到三個(gè)函數(shù)聲明:
/* Model entry point functions */extern void LowBeam_initialize(void);extern void LowBeam_step(void);extern void LowBeam_terminate(void);
實(shí)際上,我們唯一需要的函數(shù)是 LowBeam_step(void),它可以在主函數(shù)的主循環(huán)中每 10ms 調(diào)用一次:
if(Get1MsTickInterval(modeldely) >= 10){ modeldely = Get1MsTickVal(); LowBeam_step(); //近光燈}
其它功能模塊可以按照同樣的方法在近光燈函數(shù)下面添加_step函數(shù)。
總結(jié)
以上就是我們今天要講的內(nèi)容,本文簡(jiǎn)單介紹了如何通過(guò)Simulink搭建的邏輯框圖生成嵌入式代碼,并將生成的代碼添加到現(xiàn)有的MCU項(xiàng)目中,實(shí)現(xiàn)近光燈模塊的功能。
當(dāng)然,自動(dòng)代碼生成需要在項(xiàng)目調(diào)用時(shí)多一層封裝,占用一定的資源。而且對(duì)于一些精通業(yè)務(wù)的工程師來(lái)說(shuō),一些簡(jiǎn)單的手寫邏輯,用很簡(jiǎn)潔的C代碼量就可以實(shí)現(xiàn)同樣的功能。但是我們使用自動(dòng)代碼生成技術(shù)也有相應(yīng)的優(yōu)勢(shì),比如當(dāng)功能邏輯比較復(fù)雜時(shí),我們可以更清晰地理清思路,使用simulink可以很方便地進(jìn)行功能仿真。驗(yàn)證功能步驟可以放在代碼生成之前,而手寫代碼必須在編譯通過(guò)后,使用硬件設(shè)備進(jìn)行功能測(cè)試后,才能燒錄到sample中。這樣,使用simulink進(jìn)行功能仿真和自動(dòng)代碼生成,就省去了重復(fù)燒錄的過(guò)程。
當(dāng)然,Simulink 的代碼生成功能遠(yuǎn)不止本文所提到的這些,作者會(huì)在項(xiàng)目中進(jìn)行探索,并在后續(xù)的文章中與大家進(jìn)一步探討。