[Simulink] 从S函数到模块代码生成
文章目錄
- S函數
- S函數類型
- S函數的組成及執行順序
- 編寫S函數
- Level1 M S函數
- Level2 M S函數
- C Mex S函數
- mdlInitializeSizes
- C Mex S函數的實例
整理自《Simulink仿真及代碼生成技術入門到精通》
S函數
當Simulink默認提供的模塊不能夠滿足用戶的需求時,用戶可以通過S函數打造自己的模塊,實現自定義的算法或期望的動作。
S函數類型
S函數的類型,按照所支持的功能分類,可以分為
- Level 1 —— 編寫簡單的數學算法用來仿真
- Level 2 —— 所編寫的算法需要傳遞多個輸入輸出端口且每個端口數據都是多維矩陣時,需要使用該類型
除了仿真時對端口數據類型的要求之外,這兩類S函數還有一個區別
- Level 1的S函數不支持代碼生成
- Level 2的S函數支持代碼生成,但如果需要生成代碼,需要給S函數編寫同名的tlc文件
編寫支持目標硬件外設寄存器配置的驅動模塊時,C Mex S函數是一個不錯的選擇
S函數的組成及執行順序
S函數由幾個子方法構成
- 初始化mdlInitializeSizes()
- 采樣時間設定mdlInitializeSampleTimes()
- 系統輸出mdlOutputs()
- 仿真結束前終止方法mdlTerminate()
- mdlRTW()
其中,加粗部分為S函數能正常仿真的必要方法。
編寫S函數
Level1 M S函數
Level1 M S函數支持簡單的MATLAB接口及少數S函數的API,是結構簡單、功能最少的S函數
<后期補充吧>
Level2 M S函數
<后期補充吧>
C Mex S函數
使用C語言編寫S函數成為C Mex S函數,C語言編寫的S函數可執行文件為mex文件,是MATLAB環境下的動態鏈接可執行文件。
C Mex S函數中模塊屬性的設置和獲取,以及數據結構的訪問和操作都需要C Mex宏函數來實現。
C Mex S函數的編寫:
定義宏
#define S_FUNCTION_NAME demo #define S_FUNCTION_LEVEL 2包含頭文件如果需要使用Simluink內建的固定點數據類型,應該包括fixedpoint.h
#include "simstruc.h"C Mex S函數的各個子方法
其中,mdlRTW方法比較特別,負責傳遞模塊參數到rtw文件中,以便TLC文件在代碼生成階段使用RTW中的記錄。
注意:這個的各個子方法都是static子函數,其含義不是指存儲方式,而是指函數的作用于僅局限于本文件,而不會被其他S函數所調用
結尾部分
#ifdef MATLAB_MEX_FILE #include"Simulink.c"//用于仿真 #else #include"cg_sfun.h"//用于RTW代碼生成(非內嵌的S函數) #endifmdlInitializeSizes
定義S函數塊的基本特性,包括采樣時間、連續或離散狀態的初始條件以及sizes數組
| ssSetNumSFcnParams | 設定模塊參數個數,第2個參數表示參數個數 |
| ssGetNumSFcnParams | 獲取模塊參數的個數 |
| ssGetSFcnParamsCount | 獲取S函數實際擁有的參數個數 |
| ssSetNumInputPorts | 設置輸入端口的個數 |
| ssSetInputPortWidth | 設置某個輸入端口的位數,端口號從0開始,第3個參數是維度 |
| ssSetInputPortDirectFeedThrough | 設置某個輸入端口是狗直接饋入,通過第2個參數制定端口號,第3個參數1表示存在直接饋入,0則相反 |
| ssSetNumOutputPorts | 設置輸出端口的個數 |
| ssSetOutputPortWidth | 設置某個輸出端口的位數,端口號從0開始,第3個參數是維度 |
| ssSetNumContStates | 設置連續狀態變量個數,第2個參數表示連續狀態變量個數 |
| ssSetNumDiscStates | 設置離散狀態變量個數,第2個參數表示離散狀態變量個數 |
| ssSetNumSampleTimes | 設置采樣時間的個數,第2個參數表示采樣時間的個數 |
| ssSetOptions | 設置S函數的選項 |
| ssSetInputPortDataType | 設置輸入端口的類型 |
| … | … |
這里說一下ssSetInputPortDataType,默認情況下端口的數據類型為double,對應到C Mex S函數的SimStruct數據結構為SS_DOUBLE
| 0 | SS_DOUBLE | double |
| 1 | SS_SINGLE | single |
| 2 | SS_INT8 | int8 |
| 3 | SS_UINT8 | uint8 |
| 4 | SS_INT16 | int16 |
| 5 | SS_UINT16 | uint16 |
| 6 | SS_INT32 | int32 |
| 7 | SS_UINT32 | uint32 |
| 8 | SS_BOOLEAN | boolean |
使用方法:
ssSetInputPortDataType(S,0, SS_UINT32)
自定義數據類型
一般情況下,自定義數據類型可以通過M語言在workspace中創建Simulink.NumericType和Simulink.AliasType。
之后在C Mex S函數的mdlInitializeSizes子方法中注冊,并設置到輸入輸出端口或工作向量數據類型中去:
C Mex S函數的實例
用一個濾波器實例,其數學模型表述如下:
Y(t)=(U(t)?Y(t?1))×Lc+Y(t?1)Y(t) = (U(t) - Y(t-1)) \times L_c + Y(t-1)Y(t)=(U(t)?Y(t?1))×Lc?+Y(t?1)
- U(t)U(t)U(t)表示當前采樣時刻的輸入
- Y(t)Y(t)Y(t)表示當前采樣時刻的輸出
- Y(t?1)Y(t-1)Y(t?1)表示的上一個采樣時刻的輸出值
然后建立S-Function模塊,并封裝Mask,將封裝的Paramters與S-Function中的參數設置成一致的
建立Simulink模型如下:
如果這時選擇編譯的話,會報錯,如下:
這里,Nonline S Function就是指不具有TLC文件,不支持代碼生成的S函數。因此會報錯。
這里提供兩種內聯方法:
- Full inlined 完全內聯 ——在TLC的Output子方法中實現具體的算法,明確給出輸入/輸出關系
- wrapper inlined 封裝內聯 —— 在TLC的Output子方法中不是實現具體算法代碼,而是規定輸入/輸出端口變量如何調用已經存在的C代碼。
為C MEX S函數配置TLC
在配置TLC文件之前,需要先在sfun_c_filter.c中加入mdlRTW()函數。
模塊TLC編寫
%implements sfun_c_filter "C" %% Function :blockTypeSetup %% Purpose: add some macro defines. %function BlockTypeSetup(block,system) void%endfunction%% Function :Start %% Purpose: these code will appear at model.c initialization function %function Start(block,system) Output%endfunction%% Function :Outputs %% Purpose: these code will appear at model.c step function %function Outputs(block,system) Output%assign t_coef = SFcnParamSettings.r_coef%assign rollVars = ["U","Y","DWork"]%roll sigIdx = RollRegions, lcv = RollThreshold, block, "Roller" ,rollVars%assign u = LibBlockInputSignal(0,"",lcv, sigIdx)%assign y = LibBlockOutputSignal(0,"",lcv, sigIdx)%assign x = LibBlockDWork(dwork,"",lcv, sigIdx)/*Calculate the filter result*/% <y> = (%<u> - %<x>)*%<t_coef> + %<x>;%<x> = <y>;%endroll %endfunction【未完】
包含頭文件的部分,C Mex S函數使用用戶自定義數據類型有兩種方法:
- C Mex S函數中使用外部結構體數據類型,保存在head.h文件中。
然后將S函數的頭文件部分修改為:
#include "simstruc.h" #include "head.h"總結
以上是生活随笔為你收集整理的[Simulink] 从S函数到模块代码生成的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PHP7 学习笔记(十一)使用phpst
- 下一篇: tornado 第一篇