Legacy Code Tool
Legacy Code Tool是Matlab中的一個命令行工具,它可以很方便的將已有的C代碼或者C++代碼(注:不支持C++對象)與模型結合起來。
可以將C或C++代碼編譯生成用于仿真的S-fuction;也可以生成一個封裝了外部C代碼參數化的S-fuction模塊。使用過程非常的簡便,但是也有一些限制,所以當你已有的代碼不是C或者系統比較復雜,比如包含了控制器和運行環境的混合系統,關于代碼的集成可能還是要求助于S-Fuction builder活著手寫S-fuction來解決。
好了別的不多講,下面先簡單介紹一下Legacy Code Tool的工作步驟:
1 、首先生成一個特定的Legacy Code Tool的參數集(其實也就是一個結構體變量),這個參數集指定了你要包含的C代碼,頭文件,以及生成s-fuction的名稱等等諸多信息。
2、通過Legacy Code Tool的命令行語句調用第一步配置好的參數集變量,生成相應的S-fuction源文件;
3、通過Legacy Code Tool的命令行語句編譯生成的S-fuction源文件,使其變為可動態加載的執行文件,在32位windows系統中也就是mexw32文件;
4、如果需要還可以使用Legacy Code Tool的命令行語句將上面生成s-fuction執行文件封裝成simulink模塊。
基本上用Legacy Code Tool來集成C代碼的應用也就是上面這么四步,大致有個概念后我們實際先來看一個簡單的例子,之后我們在對每一個步驟進行詳細的介紹,然后再做一些復雜點的應用。
這里說的例子是matlab的help中的一個簡單例子,用C語言寫的將輸入放大兩倍的函數:
1、準備好你的C文件和相應的頭文件,如下: doubleIt.c doubleIt.h
#include “doubleIt.h”
double doubleIt(double inVal)
{
return(2*inVal);
}
#ifndef DOUBLEIT_H
#define DOUBLEIT_H
double doubleIt(double inVal);
#endif
2、定義一個Legacy Code Tool參數集變量,變量名為def,在matlab命令行中輸入如下命令 def = legacy_code(‘initialize’)
legacy_code()就是matlab中Legacy Code Tool的功能函數,'initialize’是該函數其中的一個功能參數,即初始化一個參數集變量,如果上述語句在輸入回車時沒有打分號,可以看到matlab命令行中反饋的如下內容:
def =
InitializeConditionsFcnSpec: ‘’
OutputFcnSpec: ‘’
StartFcnSpec: ‘’
TerminateFcnSpec: ‘’
HeaderFiles: {}
SourceFiles: {}
HostLibFiles: {}
TargetLibFiles: {}
IncPaths: {}
SrcPaths: {}
LibPaths: {}
SampleTime: ‘inherited’
Options: [1x1 struct]
3、針對我們這個小例子,只需要指定其中的四項:源文件、頭文件、S-fuction的名字、S-fuction的輸出函數,同樣使用命令行的方式進行參數的配置,如果源文件和頭文件在當前目錄下,可以在matlab命令行中輸入下面語句:
def.SourceFiles = {‘doubleIt.c’};
def.HeaderFiles = {‘doubleIt.h’};
def.SFunctionName = ‘ex_sfun_doubleit’;
def.OutputFcnSpec = ‘double y1 = doubleIt(double u1)’;
4、完成上述配置后,在matlab命令行輸入下面的命令,生成相應的S-fuction源文件 legacy_code(‘sfcn_cmex_generate’, def);
可以看到在matlab當前工作目錄下生成了相應的S-fuction源文件:ex_sfun_doubleit.c
5、然后,繼續在matlab命令行輸入下面的命令,對生成相的S-fuction源文件進行編譯 legacy_code(‘compile’, def);
這里要注意,必須事先配置matlab所要使用的C語言編譯器,否則這一步會無法執行,一般32位matlab安裝的時候會附帶有一個LCC的編譯器,也可以安裝任何matlab可識別的編譯器,然后使用 mex -setup命令,按照matlab中的提示設定好默認的編譯器。
在編譯的過程中,Matlab的命令行中會輸出相應的文字提示,例如:
###Start Compiling……
……
Finish Compiling ex_sfun_doubleit
Exit
6、最后,在matlab命令行輸入下面的命令,可以利用前面編譯的可執行文件生成一個S-fuction的simulink模塊。 legacy_code(‘slblock_generate’, def);
生成的模塊如下圖所示:
大家可以分別給模塊加上輸入信號和示波器,看一下模塊運行的結果應該和C語言的意圖一致。
這一部分的內容基本上來自于Matlab的Help,第二部分講會詳細介紹下legacy_code命令的使用方法和參數集中參數的含義。
經過前一篇文章的介紹,基本上Matlab的LegacyCodeTool能干什么有個大概的了解。下面對LegacyCodeTool的命令和參數集做一些介紹。
LegacyCodeTool的命令集如下:
legacy_code(‘help’)
specs = legacy_code(‘initialize’)
legacy_code(‘sfcn_cmex_generate’, specs)
legacy_code(‘compile’, specs, compilerOptions)
legacy_code(‘slblock_generate’, specs, modelname)
legacy_code(‘sfcn_tlc_generate’, specs)
legacy_code(‘generate_for_sim’, specs, modelname)
legacy_code(‘rtwmakecfg_generate’, specs)
legacy_code(‘backward_compatibility’)
含義分別如下:
1、legacy_code(‘help’)顧名思義打開legacy的Help文檔。
2、specs = legacy_code(‘initialize’),生成并初始化一個specs參數集變量,后面會詳細介紹該參數集。
3、legacy_code(‘sfcn_cmex_generate’, specs)根據specs配置參數生成相應的s-fuction源文件。
4、legacy_code(‘compile’, specs, compilerOptions),根據specs配置參數對s-fuction源文件進行編譯和關聯,形成可執行文件,compilerOptions指的是編譯器的選項,如果編譯器沒有提供附加選項可以為空,也可以根據不同的編譯器進行相應的參數指定格式為’-DCOMPILE_VALUE1=1’,或者有多個參數時格式為{’-DCOMPILE_VALUE1=1’, ‘-DCOMPILE_VALUE2=2’, ‘-DCOMPILE_VALUE3=3’,…}
5、legacy_code(‘slblock_generate’, specs, modelname),根據specs配置參數將編譯后的s-fuction執行文件封裝成simulink模塊,并添加到當前名稱為modelname指定的模型中,如果沒有將名稱為modelname的模型將生成一個名稱為modelname的模型文件,里面包含相應封裝好的s-fuction模塊。當然如果這里不指定modelname,也將會新建一個默認的模型文件。
6、legacy_code(‘sfcn_tlc_generate’, specs)可以根據specs配置參數生成相應的tlc文件,通過對生成的tlc文件應用,可以訂制代碼集成到s-fuction中的模式進而模型的加速仿真或者自動代碼生成時控制生成的代碼形式、分布等。
7、legacy_code(‘generate_for_sim’, specs, modelname),根據specs配置參數,一步完成s-fuction的代碼生成、編譯、模塊封裝,基本上等同于3、4、5條命令一起執行,當specs配置參數中的Options.useTlcWithAccel配置為1(真)時,也一并執行了第6條命令,生成了用于加速仿真的tlc文件。
命令中的第三個參數modelname的用法和第5條命令相同。
8、legacy_code(‘rtwmakecfg_generate’, specs)本命令僅和自動代碼生成simulink coder相關,會生成一個 rtwmakecfg.m文件,可以根據其中的一些接口函數對代碼生成的過程進行控制(這里就涉及到另外的話題了)。
9、legacy_code(‘backward_compatibility’)該命令自動更新legacy_code的相關語法使得LegacyCodeTool可以向后兼容。
在這些命令中,如果僅是將代碼集成到模型中,那么常用的命令也就是2、3、4、5、7。使用的順序為2-(配置參數集)-3-4-5或者2-(配置參數集)-7;
下面說一下參數應該怎么配置,根據前面講的使用第2條命令可以生成一個參數集變量,名稱是可以自己定義的,只要在matlab輸入相應格式的命令,既可以獲得如下結構的參數集變量。
SFunctionName: ‘’
InitializeConditionsFcnSpec: ‘’
OutputFcnSpec: ‘’
StartFcnSpec: ‘’
TerminateFcnSpec: ‘’
HeaderFiles: {}
SourceFiles: {}
HostLibFiles: {}
TargetLibFiles: {}
IncPaths: {}
SrcPaths: {}
LibPaths: {}
SampleTime: ‘inherited’
Options: [1x1 struct]
其中,源文件和頭文件是必須要定義的——HeaderFiles: {}; SourceFiles: {};在指定文件的時候可以使用絕對地址也可以使用相對地址;
此外SFuction的名稱也一定要定義 SFunctionName: ‘’;
初始條件函數、輸出函數、啟動函數、停止函數四個中至少定義其中的一個:InitializeConditionsFcnSpec: ‘’; OutputFcnSpec: ‘’; StartFcnSpec: ‘’; TerminateFcnSpec: ‘’;
稍后詳細解釋函數具體的定義格式。
再看剩下幾個可以選擇進行配置的參數項,IncPaths: {};SrcPaths: {};LibPaths: {};分別可以指定和程序相關聯的頭文件地址,源文件地址,庫文件地址; Legacy Code Tool 在處理相應的代碼時除了會在當前工作文件夾,以及Matlab已定義的搜索文件夾內進行相關文件的搜索,也會在IncPaths: {};SrcPaths: {};LibPaths: {};定義的文件夾內進行搜索。(地址都可以使用相對地址或者絕對地址,同樣采用命令行直接賦值的方式進行設置。)
( HostLibFiles: {};和 TargetLibFiles: {}應該也是類似的功能,但目前我還沒用過,根據Help文件說的是一個是主編譯器的相關庫文件,一個是目標編譯器的相關庫文件,等后續有時間我再弄明白,會再寫出來)。
接下來是 SampleTime:,其默認值為’inherited’,即后續生成的s-fuction及其模塊都將繼承調用它的模型或函數的仿真采樣時間,當然也還有其他兩個選項,一個是’parameterized’,可以將采樣時間參數化,通過C-MEX的API函數進行設定;另外一個是指定固定的采樣時間,采樣時間的表述格式需要參看Help中Specify Sample Time一章。
這里需要注意的是,SampleTime這個參數的設置,必須其他的參數項賦值完之后,最后進行,否則可能會出現異常。
另外,還有一個參數設置項,Options,如果已經通過第2條命令定義了參數集變量,例如lctspc,則可以直接在命令行中輸入: lctspc.Options
按下回車鍵后,可以看到
ans =
以上分別為選項參數的默認值,如果集成的代碼時C++,則需要將language定義為’C++’;
如果需要集成的函數為C語言的宏定義函數則 isMacro需要定義為真(1),默認時為(0);
其他幾個選項和s-fuction處理函數的方式有關,一般情況下保持默認即可,此處不展開解釋(需要了解可以看考Help文件),下一次將詳細介紹初始條件函數、輸出函數、啟動函數、停止函數具體的定義格式。
根據前面講過的使用命令 specs = legacy_code(‘initialize’) 生成的結構體變量中specs要定義一系列函數:初始條件函數、輸出函數、啟動函數、停止函數( InitializeConditionsFcnSpec: ‘’,OutputFcnSpec: ‘’,StartFcnSpec: ‘’,TerminateFcnSpec: ‘’)。
在定義這些函數時要注意:
1、輸入參數在函數中不能被改變
2、函數體的返回值不能為指針(可以為指針指向的值)
3、初始條件函數、啟動函數、停止函數不能通過輸入輸出參數來定義。
這些函數的定義方式都是通過帶關鍵字的字符串來定義的,關鍵字如下:
y1,y2,……,yn用來表示輸出變量
u1,u2,……,un用來表示輸入變量
p1,p2,……,pn用來表示參數變量
work1,work2,……,workn用來表示工作向量參數
(個人理解:C語言中一般沒有p,work的概念,之所以會有這兩種形式的函數變量,是因為matlab本身是處理矩陣運算的,一般來說函數都可以理解或翻譯為矩陣運算的形式,都可以轉換為狀態方程,所以有了參數變量和工作向量的概念。個人理解歡迎指正。)
下面列出,C語言中常見的函數形式,對應LegacyCodeTool應該使用的表達方法
C語言 對應字符串
void fuction(void) ‘void fuction(void)’
void fuction(TYPE x1,TYPE x2,…) ‘void fuction(TYPE u1,TYPE u2,…)’
TYPE fuction(void) ‘TYPE y1 = fuction(void)’
TYPE fuction(TYPE x1,TYPE x2,…) ‘TYPE y1 = fuction(TYPE u1,TYPE u2,…)’
TYPE fuction(TYPE *x1,TYPE x2[],…) ‘TYPE y1 = fuction(TYPE u1[1],TYPE u2[],…)’
void fuction(TYPE *y1,TYPE y2[],…) ‘void fuction(TYPE y1[n],TYPE y2[n],…)’
%n為實際應返回的值的大小,個數
TYPE fuction(TYPE *y2,TYPE y3[],…) ‘TYPE y1 = fuction(TYPE y2[n],TYPE y3[n],…)’
…
其他可以依次類推,其中TYPE為數據類型,一般常見的數據類型,LegacyCodeTool的y,u,p,work都支持,空指針只有work可以支持。
所以使用,LegacyCodeTool的基本過程就是下面三步:
1、初始化一個參數化的結構體變量
2、對結構體變量中的參數及參數表達式進行賦值
3、使用相應的命令集生成sfun或者編譯等等
下面根據之前講的LegacyCodeTool再舉一個例子:
底層在進行通信時常會遇到一些數據解析或分解情況,可能的函數如下:
test.c
#include “test.h”
void testcan(unsigned char * phval, unsigned char *sg1,unsigned int *sg2,unsigned int *sg3,unsigned int *sg4,unsigned char *sg5)
{
*sg1=phval[0];
*sg2=(((unsigned short int)phval[2])<<8)+(unsigned short int)phval[1];
*sg3=(unsigned short int)phval[3]+(unsigned short int)phval[4];
*sg4=(unsigned short int)phval[5]*2;
*sg5=phval[6]|phval[7];
};
test.h
#ifndef ____testcan_H
#define ____testcan_H
extern void testcan(unsigned char *phval, unsigned char *sg1,unsigned int *sg2,unsigned int *sg3,unsigned int *sg4,unsigned char *sg5);
#endif
可以編輯如下m腳本或依次在Matlab中輸入下列命令:
%% Define Legacy Code Tool options
testdecode = legacy_code(‘initialize’); %Create specifications structure
testdecode.OutputFcnSpec = 'void testcan(uint8 u1[8], uint8 y1[1],uint16 y2[1],…
testdecode.HeaderFiles = {‘test.h’}; %Necessary external header files
testdecode.SourceFiles = {‘test.c’}; %Necessary external source files
testdecode.SFunctionName = ‘testmycode’; %S-function name
%% Create S-function, TLC file, etc.
legacy_code(‘sfcn_cmex_generate’, testdecode); %Generate S-function code
legacy_code(‘compile’, testdecode) %Compile S-function
legacy_code(‘slblock_generate’,testdecode) %Create block for S-function
%legacy_code(‘sfcn_tlc_generate’, testdecode) %Inline S-function by creating TLC file
%legacy_code(‘rtwmakecfg_generate’, testdecode) �d path info to RTW make file
然后會自動生成相應的slx模型如下:
然后,該模塊可以正常用于simulink仿真,可以聯合模型和底層代碼一起進行仿真驗證。
另外輸入輸出可以可以使用結構體的形式,但是需要事先在h頭文件中定義好相應的結構體聲明,大家可以自己試驗一下,紙上得來終覺淺,絕知此事要躬行。
總結
以上是生活随笔為你收集整理的Legacy Code Tool的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Compose Multiplatfor
- 下一篇: C语言算法小实例3