Simulink代码生成(二十一)——TSP开发之主函数定制
一、ert模板文件解读
代码生成文件的顺序分为以下几个部分
File and Function Banner 生成文件的注释部分,这里可以修改系统目标文件,增加一些自己的信息,如author等
ert.tlc代码生成main文件的模板入下,该文件是以timestwo模型代码生成为例
example_file_process.tlc文件解读如下:
- %% Add a new C file timestwo.c and put a simple function in it
%assign cFile = LibCreateSourceFile(“Source”, “Custom”, “timestwo”)
创建一个timestwo.c的文件- %openfile typesBuf
#include “rtwtypes.h”
%closefile typesBuf
%<LibSetSourceFileSection(cFile,“Includes”,typesBuf)>
进行文件流操作,将需要添加的头文件放在c文件的Includes部分。- %openfile tmpBuf
/* Times two function */
real_T timestwofcn(real_T input) {
return (input * 2.0);
}
%closefile tmpBuf
%<LibSetSourceFileSection(cFile,“Functions”,tmpBuf)>
这里是将tmpBuf放在源文件的Functions部分- %openfile tmpBuf
/* Times two function */
extern real_T timestwofcn(real_T input);
%closefile tmpBuf
%<LibSetSourceFileSection(hFile,“Includes”,typesBuf)>
%<LibSetSourceFileSection(hFile,“Declarations”,tmpBuf)>
这里是将typesBuf放在h文件的Includes部分,将tmpBuf放在Declarations部分,进行函数定义- %% Add a #define to the model’s public header file model.h
%assign pubName = LibGetMdlPubHdrBaseName()
%assign modelH = LibCreateSourceFile(“Header”, “Simulink”, pubName)
%openfile tmpBuf
#define ACCELERATION 9.81
%closefile tmpBuf
%<LibSetSourceFileSection(modelH,“Defines”,tmpBuf)>
这里是将tmpBuf放在Defines部分- %% Add a #define to the model’s private header file model_private.h
%assign prvName = LibGetMdlPrvHdrBaseName()
%assign privateH = LibCreateSourceFile(“Header”, “Simulink”, prvName)
%openfile tmpBuf
#define STARTING_POINT 100.0
%closefile tmpBuf
%<LibSetSourceFileSection(privateH,“Defines”,tmpBuf)>
这是将tmpBuf添加到model_private.h中的Defines部分- %% Add a #include to the model’s C file model.c
%assign srcName = LibGetMdlSrcBaseName()
%assign modelC = LibCreateSourceFile(“Source”, “Simulink”, srcName)
%openfile tmpBuf
/* #include “mytables.h” */
%closefile tmpBuf
%<LibSetSourceFileSection(modelC,“Includes”,tmpBuf)>
这里是将tmpBuf添加到 model.c的Includes部分- %% Create a simple main. Files are located in MATLAB/rtw/c/tlc/mw.
%if LibIsSingleRateModel() || LibIsSingleTasking()
%include “bareboard_srmain.tlc”
%<FcnSingleTaskingMain()>
%else
%include “bareboard_mrmain.tlc”
%<FcnMultiTaskingMain()>
%endif
这里实际用处暂时不知。
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%%
%%
%%
%% Abstract:
%% Example Embedded Coder custom file processing template.
%%
%% Note: This file can contain any valid TLC code, which Embedded Coder
%% executes just prior to writing the generated source files to disk.
%% Using this template "hook" file, you are able to augment the generated
%% source code and create additional files.
%%
%% Copyright 1994-2021 The MathWorks, Inc.
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%selectfile NULL_FILE
%% Uncomment this TLC line to execute the example
%% || ||
%% || ||
%% \/ \/
%% %assign ERTCustomFileTest = TLC_TRUE
%if EXISTS(ERTCustomFileTest) && ERTCustomFileTest == TLC_TRUE
%% Add a new C file timestwo.c and put a simple function in it
%assign cFile = LibCreateSourceFile("Source", "Custom", "timestwo")
%openfile typesBuf
#include "rtwtypes.h"
%closefile typesBuf
%<LibSetSourceFileSection(cFile,"Includes",typesBuf)>
%openfile tmpBuf
/* Times two function */
real_T timestwofcn(real_T input) {
return (input * 2.0);
}
%closefile tmpBuf
%<LibSetSourceFileSection(cFile,"Functions",tmpBuf)>
%% Add a corresponding H file timestwo.h
%assign hFile = LibCreateSourceFile("Header", "Custom", "timestwo")
%openfile tmpBuf
/* Times two function */
extern real_T timestwofcn(real_T input);
%closefile tmpBuf
%<LibSetSourceFileSection(hFile,"Includes",typesBuf)>
%<LibSetSourceFileSection(hFile,"Declarations",tmpBuf)>
%% Add a #define to the model's public header file model.h
%assign pubName = LibGetMdlPubHdrBaseName()
%assign modelH = LibCreateSourceFile("Header", "Simulink", pubName)
%openfile tmpBuf
#define ACCELERATION 9.81
%closefile tmpBuf
%<LibSetSourceFileSection(modelH,"Defines",tmpBuf)>
%% Add a #define to the model's private header file model_private.h
%assign prvName = LibGetMdlPrvHdrBaseName()
%assign privateH = LibCreateSourceFile("Header", "Simulink", prvName)
%openfile tmpBuf
#define STARTING_POINT 100.0
%closefile tmpBuf
%<LibSetSourceFileSection(privateH,"Defines",tmpBuf)>
%% Add a #include to the model's C file model.c
%assign srcName = LibGetMdlSrcBaseName()
%assign modelC = LibCreateSourceFile("Source", "Simulink", srcName)
%openfile tmpBuf
/* #include "mytables.h" */
%closefile tmpBuf
%<LibSetSourceFileSection(modelC,"Includes",tmpBuf)>
%% Create a simple main. Files are located in MATLAB/rtw/c/tlc/mw.
%if LibIsSingleRateModel() || LibIsSingleTasking()
%include "bareboard_srmain.tlc"
%<FcnSingleTaskingMain()>
%else
%include "bareboard_mrmain.tlc"
%<FcnMultiTaskingMain()>
%endif
%endif
二、arduino文件模板解读
arduino采用的模板和ert的基本一致,除了这里的自定义模板
arduino_ec_file_process.tlc文件内容如下,主要是将arduino_ec_srmain.tlc文件inline进来,所以重点是解读 arduino_ec_srmain.tlc文件
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Abstract:
%% Code generation custom file processing template.
%%
%% Note: This file can contain any valid TLC code, which is
%% executed just prior to writing the generated source files to disk.
%%
%% Copyright 1994-2014 The MathWorks, Inc.
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%selectfile NULL_FILE
%% Need to set the template compliance flag before you can use the API
%<LibSetCodeTemplateComplianceLevel(1)>
%% Create a simple main.
%if UseRTOS == 0
%if LibIsSingleRateModel() || LibIsSingleTasking()
%if ExtMode
%assign board = FEVAL("arduino_ec.Prefs.getBoard")
%if (board != "mega") && (board != "mega2560")
%assign errTxt = "External Mode is supported on Mega/Mega2560 only (8kB RAM necessary)."
%<LibReportError(errTxt)>
%endif
%% We use extra file for main generation with External Mode
%include "arduino_ec_srmain_ExtMode.tlc"
%else
%% Simplified main generation w/o External Mode
%include "arduino_ec_srmain.tlc"
%endif
%<FcnSingleTaskingMain()>
%else
%% For the moment, multitasking is not supported
%include "arduino_ec_srmain.tlc"
%<FcnSingleTaskingMain()>
%endif
%else
%% Prepared for the future
%include "arduino_ec_RTOS_main.tlc"
%<FcnSingleTaskingMain()>
%endif
arduino_ec_srmain.tlc文件内容如下:
- %if GenerateSampleERTMain
%assign CompiledModel.GenerateSampleERTMain = TLC_FALSE
%endif
这里表示不生成ert的main文件
-%assign cFile = LibCreateSourceFile(“Source”, “Custom”, “arduino_main”)
%openfile tmpBuf
#include “%<LibGetMdlPubHdrBaseName()>.h”
#include “Arduino.h”
%closefile tmpBuf
%<LibSetSourceFileSection(cFile, “Includes”, tmpBuf)>
这里表示生成arduino_main.c或者arduino_main.cpp文件,然后将tmpBuf放入arduino_main文件中的Includes部分
#include "%<LibGetMdlPubHdrBaseName()>.h"表示的是模型名字的头文件- %openfile tmpBuf
%closefile tmpBuf
%<LibSetSourceFileSection(cFile, “Declarations”, tmpBuf)>
这里表示arduino_main的Declarations部分为空
%openfile tmpBuf
…
%closefile tmpBuf
%<LibSetSourceFileSection(cFile, “Functions”, tmpBuf)>
这部分是将tmpBuf放入arduino_main的Functions部分
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Abstract:
%% Custom file processing to generate a "main" file.
%%
%% Copyright 1994-2014 The MathWorks, Inc.
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%selectfile NULL_FILE
%function FcnSingleTaskingMain() void
%if GenerateSampleERTMain
%assign CompiledModel.GenerateSampleERTMain = TLC_FALSE
%endif
%if LibIsModelReferenceTarget()
%return
%endif
%assign cFile = LibCreateSourceFile("Source", "Custom", "arduino_main")
%openfile tmpBuf
#include "%<LibGetMdlPubHdrBaseName()>.h"
#include "Arduino.h"
%closefile tmpBuf
%<LibSetSourceFileSection(cFile, "Includes", tmpBuf)>
%openfile tmpBuf
%closefile tmpBuf
%<LibSetSourceFileSection(cFile, "Declarations", tmpBuf)>
%openfile tmpBuf
/* Overrun counter */
static uint8_t uOverrunCounter;
uint8_t GetOverrunCounter(void)
{
return uOverrunCounter;
}
%% Get fundamental step time
%assign SAMPLETIME = CompiledModel.FundamentalStepSize
%if SAMPLETIME < 0.00005
%% Even 50 microseconds is too quick for Arduino
%<LibReportError("The minimum supported sample time is 50 microseconds. Change the Sample time parameter in blocks that use incorrect sample times.")>
%endif
%assign SampleRate = CAST("Number", %<SAMPLETIME> * 1000000)
#define STEP_SIZE %<SampleRate>UL /* Sample Time in microseconds */
int main(void)
{
unsigned long oldTime;
unsigned long actualTime;
/* Initialize Arduino */
init();Init_Hyo_Peri();
/%
%/
/* Initialize model */
%<LibCallModelInitialize()>\
oldTime = micros();
while (true) {
%<LibCallModelStep(0)>\
actualTime = micros();
/* Overrun check */
if ((actualTime - oldTime) >= STEP_SIZE) {
/* We missed our time slot for actual step, report it! */
if(uOverrunCounter < 255U){
uOverrunCounter++;
}
oldTime = actualTime; /* Update time stamp of last step */
continue; /* We are late, continue with next step */
}
/* Waiting with pooling method */
while((actualTime - oldTime) < STEP_SIZE){
actualTime = micros(); /* Get actual time */
}
oldTime = actualTime; /* Update time stamp of last step */
}
%<LibCallModelTerminate()>\
return 0;
}
%closefile tmpBuf
%<LibSetSourceFileSection(cFile, "Functions", tmpBuf)>
%endfunction
三、arduino_main.cpp文件
最终得到的arduino_main.cpp文件如下
//
// File: arduino_main.cpp
//
// Code generated for Simulink model 'hyo_7sec_count_demo'.
//
// Author : Hyowinner @ Sat Sep 19 21:42:53 2015
// Model version : 1.14
// Simulink Coder version : 8.7 (R2014b) 08-Sep-2014
//
//
// Target selection: arduino_ec.tlc
// Embedded hardware selection: Atmel->AVR
// Code generation objectives: Unspecified
// Validation result: Not run
//
#include "hyo_7sec_count_demo.h"
#include "Arduino.h"
// Overrun counter
static uint8_t uOverrunCounter;
uint8_t GetOverrunCounter(void)
{
return uOverrunCounter;
}
#define STEP_SIZE 1000000UL // Sample Time in microseconds
int main(void)
{
unsigned long oldTime;
unsigned long actualTime;
// Initialize Arduino
init();
Init_Hyo_Peri();
// Initialize model
hyo_7sec_count_demo_initialize();
oldTime = micros();
while (true) {
hyo_7sec_count_demo_step();
// Get model outputs here
actualTime = micros();
// Overrun check
if ((actualTime - oldTime) >= STEP_SIZE) {
// We missed our time slot for actual step, report it!
if (uOverrunCounter < 255U) {
uOverrunCounter++;
}
oldTime = actualTime; // Update time stamp of last step
continue; // We are late, continue with next step
}
// Waiting with pooling method
while ((actualTime - oldTime) < STEP_SIZE) {
actualTime = micros(); // Get actual time
}
oldTime = actualTime; // Update time stamp of last step
}
hyo_7sec_count_demo_terminate();
return 0;
}
//
// File trailer for generated code.
//
// [EOF]
//