Simulink代碼生成: Storage Class配置

之前一篇博客《Simulink代碼生成: 信號線、參數配置》中,提及了一部分Storage Class(存儲類型)的配置及其代碼。本文更加詳細地研究Storage Class中各個選項的含義以及生成的代碼。

1 示例模型

首先打開Simulink,建立一個簡單的具有輸入、輸出和Gain模塊的模型。將輸入信號線命名爲Input1,並Resolve to Simulink Signal object,也就是左邊的藍色小叉子。
在這裏插入圖片描述
然後在Matlab命令行輸入:

>> Input1 = Simulink.Signal;

此時在Matlab工作區就會建立一個名爲Input的信號對象。雙擊Input1,就可以編輯該對象,包括編輯Storage Class。
在這裏插入圖片描述
將Data Type配置爲single,然後本文開始研究Storage Class中的各個選項,以及對應生成的代碼。

2 Storage Class配置及其代碼

2.1 Auto

Storage Class的第一個選項就是Auto,也就是自動的意思。字面上看不出來自動的存儲類型究竟是什麼樣,所以Ctrl + B生成代碼看一下。
在這裏插入圖片描述
觀察生成的c文件可以看出,Input1是作爲demo_U這個結構體變量的一個成員出現的。這個結構體的定義又是在demo.h中完成的,見下圖。如果模型由多個輸入,那麼這個結構體中就會有多個一一對應的成員。
在這裏插入圖片描述
這種Auto的方式一般是不會使用的。如果需要了解更多Auto配置的生成代碼的機制,可以參考Matlab幫助文檔《Standard Data Structures in the Generated Code》。

2.2 Model Default

將Storage Class選爲Model Default後,會多出兩個文本框可以填寫。
在這裏插入圖片描述
其中,Alias表示該存儲對象的別名。也就是說,該信號無論在Simulink裏面叫什麼名字,生成代碼的時候都會換成這個名字。Alignment表示數據對齊邊界,但博主也並不是很瞭解,可以參考幫助文檔。一般設爲-1的默認值,生成代碼的時候會採用最佳的對齊方式。

如果Alias和Alignment這兩項默認不改,生成的代碼就會和Auto一致。假設將Alias改爲Input1_Alias,並生成代碼,代碼中所有原來的Input1,就會被替換成Input1_Alias,如下圖。
在這裏插入圖片描述

2.3 Exported Global

將Storage Class選爲Exported Global。字面上意思是將其輸出爲全局變量。
在這裏插入圖片描述
生成代碼如下:
在這裏插入圖片描述
這裏可以看到,生成的代碼直接把Input1這個變量定義出來了,而不象是之前的結構體。而且,定義Input1的時候是在模型對應的c文件內定義的。接着再打開demo.h頭文件。
在這裏插入圖片描述
可以看出,在demo.h中用extern關鍵字對Input1這個變量進行外部聲明。也就是說,只要別的C文件包含了這個demo.h,就可以給Input1這個全局變量賦值。

這一點非常有價值,可以通過這個特性,在一個項目中用很多模塊分別生成代碼,分別編譯代碼,最後再鏈接到一起,從而實現了一個團隊的分佈式開發。而不需要將所有人的模型先集中成爲一個大模型,再生成代碼。

博主認爲,Exported Global比較適合用於Outport的信號線,因爲Inport的輸入量一般是別的模型產生的,Outport是自己的模型產生的。

2.4 Imported Extern

將Storage Class選爲Imported Extern。字面上意思是這個變量是外部引入的。
在這裏插入圖片描述
生成代碼如下:
在這裏插入圖片描述
可以看出,step函數中用到了這個Input1,但是並沒有在本文件中定義這個變量。

打開demo_private.h可以看到,在這個頭文件中外部聲明瞭Input1。也就是說,別的文件中定義了Input1。
在這裏插入圖片描述
這個選項還是比較適用於輸入端口的代碼生成的。

2.5 Imported Extern Pointer

將Storage Class選爲Imported Extern Pointer,字面上意思是引入外部指針。
在這裏插入圖片描述
觀察生成的step函數和private頭文件可以發現,除了Input1是個指針,其餘的和Imported Extern選項一樣,這裏不做贅述。
在這裏插入圖片描述

2.5 Bitfield

這個確實不太懂,工作中也沒遇到過。爲了不誤導大家,就不寫了,只佔個坑。如果有了解的朋友,還望不吝賜教哈。

2.6 Volatile

將Storage Class選爲Volatile,字面上意思是可變的。選完以後,會多出3個用戶參數可以填。HeaderFile指的是頭文件,這裏寫headerfile.h,變量的外部聲明就在這;DefinitionFile指的是C文件,這裏寫definitionfile.c,變量的定義在這個c文件中;Owner寫chhttty(也就是博主的網名),也可以不寫。
在這裏插入圖片描述
生成代碼如下:
在這裏插入圖片描述
在這裏插入圖片描述
可以看出改變了的定義和聲明是在headerfile.h和definitionfile.c中的。這裏要注意到,Input1這個變量是被volatile修飾的,也就是告訴編譯器,這個變量的值要從內存中讀取。

搞汽車軟件開發的肯定會馬上想到標定量的概念。但是標定量定義的時候,一般還需要加上一個const關鍵字,以免程序其他地方修改這個變量值。如果要生成const這個關鍵字,可以通過腳本替換,也可以通過自定義用戶自己的storageclass類型來實現。

2.7 ExportToFile

將Storage Class選爲ExportToFile,同時設定HeaderFile和DefinitionFile。
在這裏插入圖片描述
這個選項和Exported Global相似,會定義這個變量。區別在於,定義的文件不是在demo.c本身,而是用戶自己指定的文件HeaderFile和DefinitionFile中。DefinitionFile代碼如下:
在這裏插入圖片描述

2.8 ImportFromFile

將Storage Class選爲ImportFromFile,同時設定HeaderFile。
在這裏插入圖片描述
這個選項和ImportExtern類似,只是這裏需要指定headerfile。生成代碼如下:
在這裏插入圖片描述
注意觀察private頭文件,這裏和ImportExtern選項不同,不再是extern修飾Input1變量,而是直接用#include包含了我們指定的頭文件。

2.9 FileScope

將Storage Class選爲FileScope。這個選項會生成靜態全局變量,只在本文件內調用。如果還是把之前的Input1變量設爲FileScope,生成代碼會報錯,應該是和模塊輸入的性質有衝突。所以這裏就用Gain模塊的增益參數來演示。

將Gain模塊的參數設爲gain1,如下圖。
在這裏插入圖片描述
然後再Matlab命令行執行以下命令:

>> gain1=Simulink.Parameter;
>> gain1.Value = 3;

此時在Matlab工作區會生成gain1參數對象。將其Value值改爲3,StorageClass改爲FileScope,保存。
在這裏插入圖片描述
然後生成代碼如下:
在這裏插入圖片描述
可以觀察到,在本代碼中,用static關鍵字修飾gain1這個參數,並將其賦值爲3。也就是說,gain1是個靜態的全局變量。

這就表明,gain1這個參數只有在demo.c這個c文件中才能用,其他文件用到了就會報錯。

2.10 Localization

這個選項和ExportedGlobal的結果一樣,有可能是模型太簡單沒有反映出區別。待進一步研究。

2.11 Struct

將Storage Class選爲Sturct。這個選項生成的代碼和默認的Auto類似,都會有一個結構體來包含成員Input1,只是這個結構體是用戶自定義的,比如下圖中定義爲struct1。
在這裏插入圖片描述
生成代碼中可以看到自定義的結構體:
在這裏插入圖片描述
不過博主確實想不到需要這麼搞的需求,畢竟結構體這個不夠簡潔直觀。

2.12 GetSet

將Storage Class選爲GetSet。這裏和之前都不同,代碼會生成一個函數來獲取輸入值或者設置輸出值。定義一個頭文件headerfile.h,同時會默認GetFunction和SetFuction函數。
在這裏插入圖片描述
生成代碼如下:
在這裏插入圖片描述
可以理解成從headerfile.h中調用get_Input1()這個函數。另外,也可以自定義get函數。

3 總結

Simulink的StorageClass配置選項很多,可以按照項目需求自己定義。

>>返回個人博客總目錄

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章