基于Simulink模型的嵌入式代码生成与实际工程应用
提示:文章寫完后,目錄可以自動生成,如何生成可參考右邊的幫助文檔
文章目錄
- 前言
- 一、工程創建
- 二、代碼生成
- 1.搭建模塊
- 2.設置參數
- 3.自動生成
- 三、代碼整合
- 總結
前言
在嵌入式開發中,利用Simulink的相關功能模塊搭建邏輯流程以后,一個非常重要的步驟就是利用代碼生成功能將我們搭建的功能轉化為代碼,并且和嵌入式平臺的芯片軟件工程融合,使我們開發的功能在單片機上跑起來,從而實現產品的功能要求。
一、工程創建
這次使用Simulink搭建的工程的目標產品是車載智能保險盒,前兩篇文章中的CAN模塊、雨刮模塊等都是其中的功能,這些功能組裝起來通過一個完整的simulink project進行管理。以功能為文件夾,把相關的功能文件進行統一歸類。我的理解這樣創建的工程類似于代碼編輯時在編譯器中創建的工程。
就像KEIL或者IAR中可以進行編譯,運行操作一樣,simulink項目也可以進行model test、依存關系查看、運行檢查等操作。版本管理也集成了SVN或git,只需要進行簡單的設置也可以實現。我用的就是SVN進行版本管理,但是習慣上還是直接拷貝文件夾進行update和commit。
二、代碼生成
1.搭建模塊
生成代碼每個模塊的操作是一樣的,設置參數和操作。本文采用近光燈模塊進行解釋,主要因為近光模塊功能比較簡單。信號量較少,且邏輯簡單。主要信號如下:
輸入信號:
1、點火開關IGN信號
2、大燈供電信號
3、近光燈開關信號
4、短路判斷信號
5、開路判斷信號
6、報文刷新標志
輸出信號:
1、近光燈繼電器的控制信號
2、CAN報文信號
3、報文發送標志位
其中報文刷新標志和報文發送標志是系統內部的判斷信號,不作為對外的輸出,相當于寫代碼時設置的標志位是一個局部變量。
工能邏輯結構如下:
一 整體結構
二 內部結構
三 stateflow
功能搭建完成以后,點擊RUN圖標,若未報錯證明語法上結構正確是符合了生成代碼的前提條件,至于控制邏輯是否正確可以通過dashboard搭建指示燈進行仿真,仿真的方法可參考前文《Simulink模型實現汽車雨刮基本功能并仿真》。
2.設置參數
點擊工具欄上面model setting的齒輪圖標,進入設置參數界面
以本項目生成嵌入式代碼為例,主要需要調節的參數設置如下:
solver解算器下,Solever selection解算器選擇,type選fixed-step(定步長),solver選discrete(離散型)
細節選項fixed-step size設置為0.01,采樣步長為0.01s,這個參數關系到在嵌入式工程中多久調用一次功能循環,以本項目為例,設置為0.01s也就意味著,每10ms調用一次功能函數,要是不按照設定值進行定時中斷,那么會影響模塊中的計時操作。
code generation選項中主要需要注意的是兩個參數,一個是System target file要選為ert.tlc,另一個就是Language要選C語言。
Report選項中選擇生成代碼報告,一般勾選前兩項分別是生成報告和自動打開,第三個web view可選可不選。
根據所用單片機型號我們要在Hardware Implementation中選擇相對應的單片機廠商和內核類型,本項目所用的是NXP,cortexM4內核S32k148芯片,選擇相應選項。這里選擇不像Keil這類編譯器那么詳細,主要作用就是確定單片機一些數據類型定義的位數,以及是否支持長整型等,點開detail可以看到詳細。
3.自動生成
在完成以上步驟以后,就可以進行生成代碼操作了。首選在APP選項中選擇embedded coder功能卡,如下:
選擇以后進入embedded coder APP
點擊Build按鈕,生成嵌入式C代碼
代碼生成以后會自動出現在右側,方便我們查看。
因為我們勾選了生成Report選項,所以還會出現一個報告對話框,在報告里面可以查看本模塊生成代碼的相關內容,包括代碼預覽,模型信息,占用內存多少等信息。
我們在生成的代碼中可以看到很多文件,但又用的主要就是功能相關的 LowBeam.c 和 LowBeam.h 這兩個文件,其他的文件除了ert_main以外的可以不用管,直接拷貝放到我們自己的代碼工程目錄下。ert_main不用,我們用自己的main函數,不過可以參考ert_main中對功能函數的調用方法。
三、代碼整合
按照上述的方法自動生成了代碼以后,離成功使用還有最后一步操作,那就是將這些文件添加到工程并且與驅動代碼相配合。針對這款芯片,其他同事已經進行了平臺化的開發,提供了相關的接口,包括ADC、GPIO、CAN等資源都已經進行了封裝,我們所需要做的就是接口對應。還是以本近光燈功能模塊為例,LowBeam.c文件,幾乎可以不用去管,那是Matlab軟件根據我們搭建的Simulink邏輯自動生成的代碼,可讀性不是很強,但功能肯定是實現的。我們進行接口對應,關注LowBeam.h文件就好。
在.h文件中找到如下代碼:
ExtU_LowBeam_T代表輸入信號的結構體;ExtY_LowBeam_T代表輸出信號的結構體。都是以全局變量的形式進行賦值。
我們自己寫一個賦值函數:
其中涉及到其他模塊的一些信號,但這些都是獨立的全局變量,可以直接拿來進行邏輯判斷。
輸出信號:
if(LowBeam_Y.Low_Beam_On == 1){HSD_SET_LEFT_LOWBEAM_ON; //打開左近光燈HSD_SET_RIGHT_LOWBEAM_ON; //打開又近光燈} else{HSD_SET_LEFT_LOWBEAM_OFF; //關閉左近光燈HSD_SET_RIGHT_LOWBEAM_OFF; //關閉右近光燈}對輸出函數進行了封裝,這里直接調用即可。
針對總線信號,寫一個賦值函數:
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) //發送報文{LowBeam_Y.Can_Send_Flag = 0;}} }這里直接用了can_send_output_set()這個發送報文用的接口函數。
最后是在main函數中調用功能函數,我們在生成的LowBeam.h文件中可以看到三個函數申明:
/* Model entry point functions */ extern void LowBeam_initialize(void); extern void LowBeam_step(void); extern void LowBeam_terminate(void);實際我們需要用到的只有LowBeam_step(void)這個函數,在main函數的主循環中每10ms調用一次該函數即可:
if(Get1MsTickInterval(modeldely) >= 10) { modeldely = Get1MsTickVal(); LowBeam_step(); //近光燈 }其他的功能模塊都可以按照這樣的方法把_step函數添加在近光燈函數的下面。
總結
以上就是今天要講的內容,本文簡單介紹了通過Simulink搭建的邏輯框圖如何生成嵌入式代碼,并且將生成的代碼添加到已有的單片機工程中實現近光燈模塊的功能。
當然,自動代碼生成在工程的調用需要多一層封裝,占用了一定的資源。且對于一些業務熟練的工程師來說,一些簡單的邏輯手寫可以用很精簡的C代碼量實現同樣的功能。不過,我們采用自動代碼生成技術也有相應的好處,比如在功能邏輯較為復雜時可以更清楚的理清思路,而且simulink可方便的進行功能仿真,驗證功能步驟可以放在生成代碼之前,而手寫代碼則必須在編譯通過以后燒錄到樣件中利用硬件設備進行功能測試。這樣一來,自動利用simulink進行功能仿真和代碼自動生成,就省去了反復的燒錄過程。
當然,simulink的代碼生成功能遠不止本文所提到的部分,筆者還會在項目中探索,在以后的文章中和大家進一步探討。
總結
以上是生活随笔為你收集整理的基于Simulink模型的嵌入式代码生成与实际工程应用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [渝粤教育] 南昌大学 现场生命急救知识
- 下一篇: 出现这个错误: No converter