17.1 基於模型的設計
基於模型設計是一種流程,較之傳統軟件開發流程而言,使開發者能夠更快捷、更高效地進行開發。適用范圍包括汽車電子信號處理、控制系統、通信行業和半導體行業。
V字模型開發流程整體描述:
模型本身就是一個可執行的規划書,開發者修改優化模型就是對設計的修繕,修繕之時立刻可以進行設計的驗證,無需到編碼實現之后通過測試再進行系統驗證。
使用基於模型設計流程開發軟件有以下優勢:
- 在整個項目開發過程中使用統一的設計環境;
- 可以直接將需求與設計鏈接起來,易於對比變更點,降低設計遺漏的可能性;
- 將測試集成到設計中以持續驗證並糾正錯誤;
- 通過多域仿真優化算法;
- 自動產生嵌入式軟件代碼;
- 開發標准模塊庫便於重用;
- 自動生成文檔;
- 支持針對硬件目標的設計重用。
17.1.1 需求文檔
Requirements for a fast filter
1. Two input
One for signal input and the other for filter coefficient.
2. One output
The output for signals filterd by the filter.
3. Title
There should be a title in the model.
4. Alogrithm
The calculation equation should be display in the model.
17.1.2 根據需求進行設計
17.1.3 需求與設計的掛接
通常需求文檔使用Word或者Doors管理,MATLAB為了能將設計規划書與模型關聯起來,通過rmi setup注冊Active-X controls后Simulink Model菜單欄增加了需求追蹤功能,通過這個功能追加Simulink鏈接到需求設計規划書的Word文檔中,在每一項需求設計條目后都會出現Simulink的小圖標,能夠從需求文檔鏈接到模型;可通過鏈接檢查需求變更是否及時反映到所設計的模型中,以保持設計文檔和模型的一致性。
17.1.4 模型的仿真
17.1.5 模型的性能分析及修正
使用模型生成代碼,特別是產品級代碼生成時,所用模型必須按照特定規則進行審查。在工業自動化生產、汽車電子開發過程中,隨着模型復雜度的提高,人工檢查模型屬性、配置及對於MAAB標准的遵守度逐漸成為負擔,使用Simulink工具欄中的Model Advisor工具可以自動進行標准及模型參數配置和屬性的檢查,並產生檢查報告。
檢查的內容有:
- 是否會導致系統仿真出錯;
- 是否會導致生成的代碼無效;
- 生成的代碼是否符合安全標准。
17.1.6 模型效率分析與優化
使用Profile Report了解模型每個環節的時間消耗和各種子方法的調用次數。
17.1.7 模型的代碼生成
Simulink的Simulink Coder工具箱提供了將模型轉換為可優化的嵌入式C代碼的功能,將模型的信號源和信號接收部分模塊替換為輸入/輸出端口,系統文件使用ert.tlc,負責統籌調用代碼生成的整個過程,將模塊轉換為相應的C代碼,只不過這時的C代碼並非專門面向某種嵌入式芯片的,而是未經過優化的通用性嵌入式代碼,可讀性不強。
17.1.8 模型生成代碼的優化
Simulink的Embedded Coder工具箱提供了兩方面的優化,一是通過對信號線的存儲類型進行設置改變代碼生成時的變量生成方式,二是通過結構化的思想將算法模型構成一個原子子系統,並將代碼生成在指定文件的指定函數內,便於移植或重用。
17.1.9 代碼的有效性驗證
Processor In the Loop Simulation(PILS,處理器在環仿真)提供了驗證算法有效性的方法。
17.2 Simulink代碼生成流程及技巧
在Simulink環境中,嵌入式代碼是由Embedded Coder、Simulink Coder為主導,MATLAB Coder輔助器進行生成代碼優化。主要應用目標為嵌入式MCU,片上快速原型開發板,以及應用於民生電子、工業領域的MCU微處理器等。
17.2.1 代碼生成時的模型配置方法
example.slx
Configuration Parameter中集中管理着模型的代碼生成方法、格式等約束條件。為了生成嵌入式代碼,至少需要配置3部分:解算器Solver、系統目標文件(如ert.tlc)、硬件實現規定Hardware Implementation。
solver
解算器必須采用固定點類型,沒有連續狀態時可選discrete,步長默認為auto,在簡單通用嵌入式代碼生成過程中此參數沒有實際作用。
當模型中使用參數變量,如Gain的增益值,在生成代碼是,如果希望使用該參數的值直接展開到代碼中,就需要設置參數內聯選項,在Code Generation→Optimization中有Default parameter behavior選項。
可調:
P_example_T example_P = { 5.0 /* Variable: k * Referenced by: '<Root>/Gain' */ }; void example_step(void) { example_Y.Out1 = (example_P.k * example_U.In1 + example_U.In2) * example_U.In3; }
內聯:(此時缺少model_data.c文件)
void example_step(void) { example_Y.Out1 = (5.0 * example_U.In1 + example_U.In2) * example_U.In3; }
當選擇Inlined后,代碼生成時模型的參數將以常數方式直接生成到代碼邏輯中,不再以一個參數變量的形式生成。當模型中的參數需要作為實時可以調節的參數生成到代碼中時,選擇Tunable,參數將作為變量生成。如果不需要實時調節參數,可以選擇節省存儲空間的方式Inlined。
MATLAB2014a中該選項以勾選框的形式給出。
Hardware Implementation
Hardware Implementation選項是規定目標硬件規格的選項。在這個選項卡中可以配置芯片的廠商和類型,設置芯片的字長、字節順序等。
另一個關鍵的設置選項是控制整個代碼生成過程的系統目標文件System Target File,ert.tlc文件是Embedded Coder提供的能夠生成專門用於嵌入式系統C代碼的系統目標文件。在Code Generation頁面中的Browser按鈕可以選擇系統目標文件。
Code Generation對比:
另外2018a擁有搜索功能:
Report
在Report子標簽中有關於生成代碼報告的頁面,通過勾選框可以選擇是否在模型編譯結束后自動打開。
在Advanced parameters中可以選擇是否在代碼報告中追加模型與代碼的雙向追蹤,並選擇追蹤的內容
勾選Metrics中的Static code metrics時,將會在代碼生成報告中包含靜態代碼的參數指標。
Comments
在comments子標簽中包含對生成代碼中注釋內容的配置。
Include comments選項的勾選決定是否在生成代碼中添加Simulink自帶的注釋。注釋中帶有可以從代碼跳轉到對應模塊的超鏈接,方便讀者追溯模塊與代碼的對應關系,建議勾選。
Symbol
symbol子標簽頁面用於設置ert.tlc一族系統目標文件控制下的代碼生成不變定義規則。這些符號包括數據變量和數據類型定義、常亮宏、子系統方法、模塊的額輸出變量、局部臨時變量及命令的最長字符數等。
控制代碼生成的標示符:
標示符 | 作用說明 |
$R | 表示根模型的名字,將C語言不支持的字符替換為下划線 |
$N | 表示Simulink對象:模塊、信號或信號對象、參數、狀態等的名字 |
$M | 為了避免命名沖突,必要時追加后綴以示區分 |
$A | 表示數據類型 |
$H | 表示系統層級標示符,對於根層次模塊root_,對於子系統模塊sN_,N是Simulink分配的系統編號 |
$F | 表示函數名,如表示更新函數時使用_Update |
$C | 校驗和標示符,用於防止命名沖突 |
$I | 表示輸入/輸出標示符,輸入端口使用u表示,輸出端口則用y表示 |
通過上表中各種標示符的不同組合,即可規定生成代碼中各部分的名稱的生成規則。推薦使用默認設置。
Custom Code
Custom Code子標簽主要用於添加用戶自定義的或者編譯模型時必需的源文件、頭文件、文件夾或者庫文件等。
Debug
原Debug子標簽頁面,新版Code Generation→Advanced parameters中,可以對編譯過程和TLC過程的相關選項進行設置。
Verbose build的勾選可以將編譯過程信息顯示在Command Window中。Retain .rtw file則能夠保留編譯模型生成的rtw文件。rtw文件是代碼生成過程中從Simulink模型得到的中間文件,它記錄了模型相關的所有需要被TLC文件使用的信息。下面關於TLC的幾組參數能夠啟動TLC文件的profile功能和調試功能,使得開發者能夠對TLC語言文件進行斷點調試、單步調試等動作,以及了解TLC語句的覆蓋度等情況。
Interface
Software E、environment組的參數中提供CPL(Code replacement library)的選擇,CPL中定義一個表,根據表格將Simulink模塊與所對應的目標語言的數學函數及操作函數庫掛接,以便從模型生成代碼。Support參數組中每個選擇框代表一種嵌入式編碼器對代碼生成的支持功能,其中一些功能需要Simulink提供的頭文件來支持才能編譯為目標文件的,這些頭文件一部分存儲在MATLABroot\simulink\include文件夾中,一部分是在模型生成代碼的過程中自動生成的(rt_開頭的文件)。
選擇框條目 | 所需頭文件 |
floating-point numbers | rtw_solver.h |
non-finite numbers | rt_nonfinite.h |
complex numbers | - |
absolute time | - |
continuous time | rt_continuous.h |
variable-size signals | - |
Code interface與Data Exchange參數組用來配置生成代碼的接口及數據記錄的方式,如無特殊要求建議使用默認配置。
Verification
Verification子標簽頁面主要是關於代碼驗證方式SIL與PIL的配置,是否使能代碼中函數執行時間記錄、代碼覆蓋度記錄,以及是否創建用於SIL與PIL的模型等。
Code Style
Code Style子標簽頁面提供了一些關於代碼風格的選擇框選項,如if else分支的完整性確保,if else與switch case語句的選用,生成括號的頻度,是否保留函數聲明中extern關鍵字等。
Template
Template子標簽頁面內為嵌入式編碼器提供了一族默認的代碼生成模板。
ert_code_template.cgt中使用TLC變量方式規定了文件生成的順序及添加模型信息注釋的位置。模型生成的源文件、頭文件及全局數據存儲和外部方法聲明文件的生成可以使用統一模板。
File customization Template則提供給用戶自定義代碼生成過程的文件輸入,用戶根據應用場景需要可以調用讀入/寫入目標硬件的TLC文件、自定義函數或注釋,甚至根據模型的單速率/多速率不同分別調用不同的主函數模板等。
ert_code_template.cgt中主要規定了代碼段的順序。
Generate an example main program提供是否生成一個示例主函數的選項。這個示例主函數名為ert_main.c,包含一個main()函數和一個調度器代碼。主函數調用模型初始化函數model_initialize()初始化模型需要的數據,以及復位異常狀態標志;調度器代碼僅提供一個模型每個采樣時間點應該執行的函數模板rt_Onestep(),此函數應該綁定到目標硬件的定時器中斷上作為其中斷服務函數(ISR),執行周期應該與模型基頻(即固定點解算器的步長)一致,內部應該調用模型單步函數model_step()。另外,rt_Onestep()內部應該對其調用進行溢出檢測。
Code Placement
Code Placement子標簽頁面提供的選項將影響生成代碼的組織方式和數據存儲方式及頭文件包含的分隔符選擇等。
File packaging format表示文件的組織方式。
File packaging format | 生成的文件列表 | 省去的文件列表 |
Modular | model.c subsystem files(optional) model.h model_types.h model_private.h model_data.c(conditional) |
- |
Compact(with separate data file) | model.c model.h model_data.c(conditional) |
model_types.h model_private.h |
Compact | model.c model.h |
model_types.h model_private.h model_data.c |
省去的只是文件個數,其內容被合並到了其他文件中。
省去的文件 | 內容轉移目標 |
model_data.c | model.c |
model_private.h | model.c和model.h |
model_types.h | model.h |
Data Type Replacement
該子標簽頁提供一個選擇框,勾選之后出現3列數據類型列表。
前兩列按照數據類型的對應關系給出了每種數據類型在Simulink和嵌入式編碼器生成代碼中的類型名,第3列工用戶設置,填入自定義的類型名之后 ,生成代碼時將使用自定義的類型名替換Code Generation Name。用戶填入的自定義類型名不僅是一個別名字符串,還必須在Base Workspace中定義其作為Simulink.AliasType類型對象才可以。第3列不必全部填滿。
Memory section
Memory section(新版Code Generation→Advanced parameters中)可以設置函數、常數、輸入/輸出、數據和參數的存儲段。存儲段的設置主要面向模型等級函數和頂層模型的內部數據。
完成配置后按下Ctrl+B或者在Command Window中輸入rtwbuild(gcs),即啟動模型編譯。
>> rtwbuild(gcs) ### Starting build procedure for model: example ### Generating code and artifacts to 'Model specific' folder structure ### Generating code into build folder: C:\Users\lenovo\Desktop\example_ert_rtw ### Invoking Target Language Compiler on example.rtw ### Using System Target File: D:\matlab2018a\rtw\c\ert\ert.tlc ### Loading TLC function libraries ...... ### Initial pass through model to cache user defined code . ### Caching model source code ....................... ### Writing header file example_types.h ### Writing header file example.h . ### Writing header file rtwtypes.h ### Writing source file example.c ### Writing header file example_private.h ### Writing source file example_data.c ### Writing source file ert_main.c ### TLC code generation complete. .### Creating HTML report file example_codegen_rpt.html ### Using toolchain: LCC-win64 v2.4.1 | gmake (64-bit Windows) ### Creating 'C:\Users\lenovo\Desktop\example_ert_rtw\example.mk' ... ### Successful completion of code generation for model: example
若勾選了生成報告的選項,則編譯完成會自動彈出Code Generation Report。
若配置無誤,編譯成功,在與模型名相同的.c文件中會包含model_step()函數,此處為example_step(),這里的代碼表示模型所搭建的邏輯。
17.2.2 代碼生成的流程
模型生成代碼的順序之前已經提及,首先通過 rtwbuild命令將模型編譯為rtw文件,Simulink Coder中的目標語言編譯器(Target Language Compiler)將rtw文件轉換為一系列的源文件,在這個過程中TLC所使用的文件包括3類:系統目標文件(ert.tlc、grt.tlc等)、模塊的目標文件(如與S函數配套的TLC文件)和支持代碼生成的TLC函數庫等文件。
模型的源代碼全部生成之后,可以使用Simulink提供的模板自動生成makefile來編譯鏈接得到目標文件,也可以將生生成的源代碼加入到目標芯片所使用的編譯集成環境IDE的工程項目中去,使用IDE編譯鏈接,最終通過仿真器下載到目標硬件中進行實機運行。
6個更細致的階段:Entry、Before TLC、After TLC、Before Make、After Make和Exit。在保持順序執行的前提下,每個階段都可以由用戶追加一些自定義行為,進行模型內部約束關系的檢查,或者是鏈接外部第三方開發工具等。
在Entry階段,可以對自定義目標進行預配置參數配置和檢驗等操作;Before TLC是代碼生成之前的階段,可以將需要用到的編譯信息存儲到一個結構體中管理,或者將編譯需要的頭文件、源文件和庫文件等進行路徑定位和添加;After TLC是代碼生成之后的階段,可以將生成代碼文件夾需要的文件拷貝到目標芯片的集成編譯環境工程文件夾內以備使用;在Before Make階段可以對代碼進行分析、驗證和模型或模塊的用戶設置檢測等;After Make則可以通過MATLAB控制集成編譯環境自動生成工程文件,更新其中生成的代碼列表,並自動編譯鏈接及下載到目標硬件中;Exit階段則可以將整個過程是否順利執行的信息進行顯示或臨時變量清除等操作。
rtw文件
rtw文件作為模型編譯器的輸入文件和編譯過程的中間產物,記錄了模型創建信息和編譯信息、名字與版本號、配置參數集、輸入輸出、參數等所有信息。在原Debug子標簽頁面,新版Code Generation→Advanced parameters中,可以選擇保留。
rtw文件的構成元素是record,稱為記錄,格式如下:
recordName{itemName itemValue}
rtw文件的這一條條記錄是按照層次進行划分的,最上層是CompiledModel,具有全局的訪問范圍,向內注冊呢個分別是System、block,每條記錄都由一個統領關鍵字和一對{ }構成,{ }內部成為統領關鍵字的域,訪問域中成員與結構體訪問的方法一致。如:
CompiledModel.Subsystem[0].Block[0].Parameter.Value;
追加信息使用addtorecord命令,如:
% addtorecord CompiledModel Author{Name "Custom"}
TLC文件
tlc文件即TLC編譯器所編譯的目標文件。
- 系統目標文件:規定生成代碼的全局結構,以匹配所支持的目標芯片群及目標語言。
- 模塊目標文件:規定Simulink模塊生成代碼時的代碼實現,一般與模塊的S函數同名,存儲在同一文件夾下,並從S函數中獲取參數信息以生成代碼。
在TLC運行階段,首先運行的就是系統目標文件,如ert.tlc,系統目標文件是TLC運行的起點,其他TLC文件會被其調用,整個執行過程按照TLC命令行逐一執行。TLC文件執行過程中,會讀取、增加或修改rtw文件中的記錄信息。
17.2.3 代碼生成方法與技巧
Simulink模代碼生成的結構
Simulink信號線在不同存儲類型下的代碼生成
右擊某根信號線,打開屬性對話框,第2個標簽頁是關於信號線代碼生成的配置頁面。
Configuration Parameter→Simulation Target→Signal storage reuse
勾選此項時,生成代碼會為了節省存儲用量而不為中間信號生成中間變量;反之,不勾選時,Simulink為每一個模塊的額輸出生成一個中間變量。在模型規模很大時,不勾選Signal storage reuse將會增加很多存儲用量,建議勾選。
Signal object class默認時部分不同存儲類型下信號線生成代碼比較方式:
信號線存儲類型 | 生成代碼聲明方式 | 生成代碼 |
Auto(signal storage reuse:on) | - | codegen_01_Y.Out1=(codegen_01_P.Gain_Gain*codegen_01_U.In1+codegen_01_U.In2)*codegen_01_U.In3; |
Auto(signal storage reuse:off) | In model.h: typedef struct{ real_T Gain real_T line }B_codegen_01_T; |
codegen_01_B.Gain=codegen_01_P.Gain_Gain*codegen_01_U.In1; codegen_01_B.line=codegen_01_B.Gain+codegen_01_U.In2; codegen_01_Y.Out1=codegen_01_B.line*codegen_01_U.In3; |
ExportedGlobal | In model.h:
extern real_T line; In model.c: real_T line; |
line=codegen_01_P.Gain_Gain*codegen_01_U.In1+codegen_01_U.In2;
codegen_01_Y.Out1=line*codegen_01_U.In3; |
ImportedExtern | In model_private.h:
extern real_T line; |
line=codegen_01_P.Gain_Gain*codegen_01_U.In1+codegen_01_U.In2;
codegen_01_Y.Out1=line*codegen_01_U.In3; |
ImportedExternPointer | In model_private.h: extern real_T *line; |
*line=codegen_01_P.asg_Gain*codegen_01_U.In1+codegen_01_U.In2;
codegen_01_Y.Out1=*line*codegen_01_U.In3; |
Simulink模塊代碼生成的接口
默認ert.tlc作用下生成的接入點函數有2個:model_initialize()和model_step(),model_initialize()將在model_step()函數運行之前調用一次對模型進行初始化,model_step()函數將在每個rt_Onestep中被周期性調用(需要綁定到目標硬件上實現)。其實model_step()函數內部包含2個子函數model_update()和model_output(),分別用於計算模型中的離散狀態變量及模型的輸出,通過Single output/update function選項可以選擇合並生成或分開生成。
通過勾選Terminate function required,可以生成model_terminate()函數。
Classic call interface默認不勾選,生成的代碼層次較少,執行效率較高;若勾選此選項,模型生成的代碼將按照C MEX S函數的各個子方法組織,得到非常復雜的處理機制。
模型的信號和狀態,二者相輔相成,信號作為模型輸入/輸出和連接的橋梁,狀態則為模型不同時刻的數據緩沖提供支持。默認情況下它們會分別生成到各自的結構體中,如果勾選了Combine signal/state structures,那么生成代碼時模型中的信號變量和狀態變量會結合在一個結構體變量中。
Configure Model functions按鈕在真正意義上提供了一個自定義模型入口函數和子系統函數接口的方式,這個按鈕僅在系統目標文件為ert.tlc及以ert.tlc為基礎系統目標的文件中存在。
(1)Simulink模型入口函數接口自定義
在這里用戶可以修改模型初始化函數名及Step函數名。Get default能夠獲取自定義默認參數列表。Port Name為端口名,只讀;Port Type為端口類型,只讀;C Type Qualifier為變量限定符,C Identifier Name為參數變量名。
Validate按鈕會對模型進行檢驗。
(2)Simulink模型子系統函數接口自定義(原子子系統)
子系統的代碼生成:右擊子系統→C/C++ Code→Build This Subsystem。
RTW.configSubsystembuild(gcbh)
為了定義子系統的入口函數,使用該命令啟動子系統Model Interface對話框,使用這個命令的前提是模型系統目標文件是ert.tlc。
整個模型生成時,上述配置完全不起作用,要使在整個模型編譯生成代碼時自定義子系統的函數接口,需要右擊子系統→Block Parameters(Subsystem)。
Function packaging:
選項 | 功能 |
Auto | Simulink Coder基於模型中子系統的個數和類型自動選取最優的代碼生成格式,此時不能控制子系統生成的函數名及所存放的文件 |
Inline | 直接將子系統代碼內聯展開 |
Nonreusable function | 子系統生成一個函數,函數的參數列表由Function Interface參數決定,函數名及函數所存放的文件都可以指定 |
Reusable function | 當模型中存在同一個子系統的多個實例時,Simulink Coder為其生成帶有可重用參數列表的函數,函數名及函數所存放的文件都可以指定 |
Simulink自定義存儲類型與信號/參數數據對象
信號是信號線中傳遞的數據,隨着模型的采樣時刻不斷變化,通常都是計算得出的量;參數是模型中的各種常數,如Gain的增益,既可以是算法的參數也可以是實驗得到的數據,在模型執行過程中不發生變化。在MCU中,信號存儲在RAM中,參數存儲在ROM中。
(1)Simulink包與數據對象
CSC名 | 功能 | 是否可用於信號 | 是否可用於參數 |
Default | 數據對象的屬性CoderInfo.CustomStorageClass的默認設置,直接使用模型中的變量或參數名到代碼中 | 是 | 是 |
Bitfield | 聲明支持布爾類型的位域結構體類型 | 是 | 是 |
Volatile | 生成Volatile類型標示符變量 | 是 | 是 |
ExportToFile | 生成一個頭文件,用戶指定其名稱,內部包含全局變量聲明,model.h中會生成包含此頭文件的#include命令 | 是 | 是 |
ImportFormFile | 生成頭文件包含命令,include包含全局變量聲明的頭文件,所包含的文件名由用戶指定,在model_private.h中生成#include命令 | 是 | 是 |
FileScope | 為變量聲明時生成靜態后綴以限定訪問范圍在當前文件 | 是 | 是 |
Struct | 將信號或變量生成結構體結構 | 是 | 是 |
GetSet | 跟Data Store Memory Block聯合使用支持特殊函數調用,如對某地址的讀取與寫入接口函數 | 是 | 是 |
Reusable | 當一對I/O信號設置為Reusable並且有相同信號名時 | 是 | 否 |
位域是嵌入式C代碼中常用的數據結構。對於有些變量,它不需要占據一個完整的字節,如果單獨給它分配一個字節太過浪費,特別對於嵌入式MCU芯片而言,資源緊張,必須使用緊湊的存儲空間排布。位域可以將一個完整的字節划分為多個不同的二進制位區域,每個二進制位域存放一個0或1。
也可以通過在Base Workspace中創建數據對象,再將其綁定到信號線上以生成代碼。
dataobj=Simulink.Signal;
雙擊這個變量啟動數據對象的屬性對話框。
通過k=Simulink.Parameter可以創建一個參數的數據對象。
in1 = Simulink.Signal; in1.InitialValue = '0'; in1.StorageClass = 'Struct (Custom)'; in1.CoderInfo.CustomStorageClass = 'Struct'; in1.CoderInfo.CustomAttributes.StructName = 'input'; in2 = Simulink.Signal; in2.InitialValue = '0'; in2.StorageClass = 'Struct (Custom)'; in2.CoderInfo.CustomStorageClass = 'Struct'; in2.CoderInfo.CustomAttributes.StructName = 'input'; out = Simulink.Signal; out.InitialValue = '0'; out.StorageClass = 'Struct (Custom)'; out.CoderInfo.CustomStorageClass = 'Struct'; out.CoderInfo.CustomAttributes.StructName = 'output'; line_h = find_system(gcs, 'findall' , 'on', 'Type', 'line'); set(line_h, 'MustResolveToSignalObject', 1);
將信號線綁定同名數據對象后,信號線張有一個藍色三叉標記。
取消綁定通過set(line_h, 'MustResolveToSignalObject', 1);實現。
GetSet這個存儲類型的使用有些特殊,需要Data Store Memory模塊、Data Store Read/Write模塊配合使用。Data Store Memory模塊定義一個變量名指向一片存儲區域,在同一層模型或子模型的Data Store Read/Write模塊都可以對這塊存儲區域進行讀/寫操作。Data Store Memory中的信號名與Base Workspace中定義的信號數據對象綁定以后,可以設置生成代碼中讀取/寫入此信號的接口函數。當數據對象的存儲類型被設置為GetSet之后,其CustomAttribute屬性的3個子屬性用於設置生成代碼時的函數接口。
屬性名 | 功能 |
GetFunction | 讀取存儲地址的函數名 |
SetFunction | 寫入存儲地址的函數名 |
HeaderFile | 可選項,設置需要包含的頭文件全名,該頭文件中應該聲明上述2個參數中配置的函數原型 |
(2)mpt包CSC與數據對象
mpt包是Simulink軟件提供的另一個內建類,包括信號與參數2中數據對象,分別使用mpt.Signal和mpt.Parameter創建。
它比Simulink能夠提供更多的CSC類型,如Global和StructVolatile。
Global存儲類型將信號或參數數據對象作為全局變量聲明及定義在代碼中,是mpt包的默認CSC選項。HeaderFile和DefinitionFile即為聲明和定義全局變量的文件名。全局變量聲明時以extern作為限定符。MemorySection提供了數據對象生成代碼時的限定符。
StructVolatile存儲類型將在生成的機構體變量前面增加Volatile限定符。
數據對象的創建和設定既可以通過信號線屬性對話框、Data Store Memory參數對話框或M代碼,也可以使用Model Explorer創建和管理。啟動Model Explorer有3種方式。
- 工具欄
;
- 在Command Window中輸入sfexplr或者slexplr命令;
- 選中模型Ctrl+H。
Model Explorer為Simulink模塊、信號、工作空間的變量和數據對象提供了一個集中管理和編輯的場所。
通過這些按鈕可以新建一個變量、信號數據對象或參數數據對象。
Simulink其他數據對象
除了Simulink.Signal和Simulink.Parameter這兩個數據對象以外,Simulink類還有AliasType、NumericType和Bus等子類。
其中Simulink.Bus和Simulink.BusElement用來配合Bus Creator模塊創建和管理Bus變量對象及其成員。
Simulink.AliasType是為一個數據類型定義別名的類;Simulink.NumericType提供了一個定義數據類型的功能。
custom_float=Simulink.AliasType;
Base type是別名對象的基礎類型;Data scope是代碼生成的相關屬性,表示這個別名數據類型的定義所存放的位置;Header file中填寫定義數據類型別名的頭文件名;Description中可以添加此別名對象相關的文本信息,對模型生成沒有影響。
模型開啟Replace data type names in the generated code時,即可使用數據類型別名定義功能,這樣做的好處是方便代碼移植。
例如,下面提供了一種替換樣例:
replaced_type = {'FLOAT64','FLOAT32','INT32','INT16','INT8','UINT32','UINT16','UINT8','BOOL','INT32','UINT32','CHAR'}; base_type = {'double','single','int32','int16','int8','uint32','uint16','uint8','boolean','int32','uint32','uint8'}; type_num = length(replaced_type); for ii = 1: type_num eval([replaced_type{ii},' = Simulink.AliasType; ']); eval([replaced_type{ii},'.BaseType = base_type{ii};']); assignin('base', replaced_type{ii}, eval(replaced_type{ii})); end
此時工作區可以查看這些定義好的數據類型別名對象。
定義后在信號屬性對話框中Data Type下拉框中可以使用自定義的數據類型別名對象。。
Simulink.NumericType數據對象比Simulink.AliasType功能更多一些,不僅可以創建一個數據別名對象繼承既有數據類型,也可以創建一個全新的自定義數據類型。
Simulink模型創建數據詞典
當模型所包含的Simulink包和mpt包的數據對象個數較少時,使用M語言或者屬性對話框及Model Explorer來創建數據對象都可以。當一個模型結構復雜,包含成百上千個信號和參數時,其數據對象的創建和存儲可以通過數據詞典(Data Dictionary,簡稱DD)管理。
數據詞典的內容包括信號量和參數量,可根據信號/參數數據對象的屬性編制DD的表頭,例如:
clc clear % read dd [sig_data, sig_str] = xlsread('DataDic.xls',1); sig_name = sig_str(2:end, 1); sig_dimensions = sig_data(:,1:2); sig_description = sig_str(2:end,4); sig_min = sig_data(:,4); sig_max = sig_data(:,5); sig_initval = sig_data(:,6); sig_units = sig_str(2:end, 8); sig_datatypes = sig_str(2:end, 9); sig_csc = sig_str(2:end, 10); % get num of signals sig_num = size(sig_data, 1); % create signal ojects for ii = 1: sig_num eval([sig_name{ii}, ' = Simulink.Signal;']); eval([sig_name{ii}, '.Dimensions = [', num2str(sig_dimensions(ii,:)),'];']); eval([sig_name{ii}, '.Description = ''', sig_description{ii},''';']); eval([sig_name{ii}, '.Min = ', num2str(sig_min(ii)),';']); eval([sig_name{ii}, '.Max = ', num2str(sig_max(ii)),';']); eval([sig_name{ii}, '.InitialValue = ''', num2str(sig_initval(ii)),''';']); eval([sig_name{ii}, '.DocUnits = ''', sig_units{ii},''';']); eval([sig_name{ii}, '.DataType = ''', sig_datatypes{ii},''';']); eval([sig_name{ii}, '.CoderInfo.StorageClass = ''', sig_csc{ii},''';']); end %% if user create model with lines named as Simulink.Signal name then it is ok to run codes below. % line_h = find_system(gcs, 'findall' , 'on', 'Type', 'line'); % set(line_h, 'MustResolveToSignalObject', 1);
Simulink中的實時任務調度及代碼生成
模式 | 單速率 | 多速率 |
單任務 | 支持 | 支持 |
多任務 | 不支持 | 支持 |
當模型中所有模塊都按照同一個采樣時間設置時,成為單頻率系統,當存在多個不同的采樣時間時,稱為多頻率系統。所謂任務,在模型中由不同的子系統來表現。
(1)單速率單任務系統調度代碼生成
這種情況下rt_OneStep()將在每一個采樣時刻調用model_step()函數一次。
(2)多速率多任務系統調度代碼生成
在多速率多任務系統中,生成的代碼采用一種按優先級分類的可搶占式的機制。模型中包括了NumTask個任務,與模型的固定解算器步長相同周期的任務為基速率,其他任務的執行周期都是基速率的整數倍,稱為子速率。基速率的子系統生成的代碼為model_step0,其余子速率的任務按照執行周期的快慢生成的代碼為model_step1~model_stepNumTask-1。
在NumTask個任務中,基速率的任務是周期最短,執行頻率最高的一個,同時也具有最高的優先級;其他子任務則按照執行周期從短到長依次具有逐漸降低的優先度。
在每個MCU定時器中斷時刻,對每個子速率系統是否需要被執行進行檢測,這些標志位存儲在eventFlags數組中,數組中每個成員表示一任務的執行標志,只有eventFlags[n]為真時,才會在當前rt_OneStep()中執行model_stepn。是否將eventFlags數組中的元素置位,取決於數組taskCounter,其元素表示各個任務的計數值。taskCounter在每次rt_Onestep()被調用時對各子速率對應的計數值+1,當達到該子速率周期/基速率周期值時taskCounter被清零,接着eventFlags的對應位變為1,從而形成了rt_OneStep()調用對應model_stepn()函數的條件。
(3)多速率單任務系統調度代碼生成
模型生成的rt_OneStep()函數的代碼同單速率單任務的代碼相似,區別在於model_step()函數的內部,不同速率的調度代碼在內部生成。代碼通過數組對多個子速率分別進行計數,當計數值達到閾值后被清零並執行對應的子速率代碼。