我是靠谱客的博主 靓丽眼神,最近开发中收集的这篇文章主要介绍[Simulink] 从Simulink S函数的使用Simulink S函数的使用Simulink C Mex S Functiondigital_in.c --> digital_in.mexw64编写digital_in.tlc建立S-function模块配置环境编译总结,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Simulink S函数的使用

这部分涉及到对Simulink建模的控制,从而生成我们可读、可进一步编写或修改的代码。因此,建模时需要遵循一定的建模规范,并进行对应的检查,例如:ISO26262、MAAB、MISRA C等检查,MAAB的建模规范中给出很多建模注意事项,为了满足代码的可读性,可以利用Simlink的mpt数据类型建立对应的数据字典。
这部分不是这个学习笔记的重点,这里先挖坑。

Simulink C Mex S Function

制作C MEX S函数,代码如下:

#define S_FUNCTION_NAME digital_in /* Defines and Includes */
#define S_FUNCTION_LEVEL 2
#include "simstruc.h"
enum{
Pin_idx = 0,
N_Para
};
#define Pin(S) mxGetScalar(ssGetSFcnParam(S,Pin_idx))
static void mdlInitializeSizes(SimStruct *S)
{
ssSetNumSFcnParams(S, N_Para);
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
return; /* Parameter mismatch reported by the Simulink engine*/
}
ssSetSFcnParamNotTunable(S,0);
if (!ssSetNumInputPorts(S, 1)) return;
ssSetInputPortWidth(S, 0, 1);
ssSetInputPortDirectFeedThrough(S, 0, 1);
if (!ssSetNumOutputPorts(S,0)) return; /*ssSetOutputPortWidth(S, 0, DYNAMICALLY_SIZED);*/
ssSetNumSampleTimes(S, 1);
/* Take care when specifying exception free code - see sfuntmpl.doc */
ssSetOptions(S, SS_OPTION_EXCEPTION_FREE_CODE);
}
static void mdlInitializeSampleTimes(SimStruct *S)
{
ssSetSampleTime(S, 0, INHERITED_SAMPLE_TIME);
ssSetOffsetTime(S, 0, 0.0);
}
static void mdlOutputs(SimStruct *S, int_T tid)
{
}
static void mdlTerminate(SimStruct *S){}
#define MDL_RTW
static void mdlRTW(SimStruct *S){
int8_T pin_number = Pin(S);
if(!ssWriteRTWParamSettings(S,N_Para,
SSWRITE_VALUE_DTYPE_NUM,"PIN", &pin_number, DTINFO(SS_INT8, COMPLEX_NO) ))
return;
}
#ifdef MATLAB_MEX_FILE /* Is this file being compiled as a MEX-file? */
#include "simulink.c" /* MEX-file interface mechanism */
#else
#include "cg_sfun.h" /* Code generation registration function */
#endif

上述代码中,两个地方注意一下:

enum{
Pin_idx = 0,
N_Para
};

其中,

  • enum枚举了两个变量Pin_idxN_Para,其中初始化Pin_idx = 0,则N_Para就初始化为1,恰好与变量个数相对应。
  • #define Pin(S) mxGetScalar(ssGetSFcnParam(S,Pin_idx))获取参数,获取到的是具体的值,这里需要将S-Function中的Parameters对应好。
  • ssWriteRTWParamSettings这个是要进行参数的传递,需要注意的是最终RTW认的是用户设定的参数名,而不是上图中的S-function parameters填写的参数,即:
if(!ssWriteRTWParamSettings(S,N_Para,
SSWRITE_VALUE_DTYPE_NUM,"PIN", &pin_number, DTINFO(SS_INT8, COMPLEX_NO) ))
return;

最终的tlc控制.c文件的时候,用的是"PIN"这个参数名,而不是Pin。

digital_in.c --> digital_in.mexw64

我使用的是windows 64位的电脑,所以生成的是digital_in.mexw64的文件,windows 32位则生成digital_in.mexw32的文件。

mex digital_in.c

编写digital_in.tlc

编写tlc文件要实现的目的是:

  • 在model.c文件的Includes部分加入#include "reg52.h",在model_step()函数中加入P%<Pin> = %<u>;
  • 为了说明如何生成用户自定义的文件,这里生成一个GPIOconfig.c文件,里面什么也没有。
%implements digital_in "C"
%%assign u = LibBlockInputSignal(0, "","",0)
%function BlockTypeSetup(block, system) void
%% 初始化程序写入到ert_main.c中?
%openfile tmpBuf
#include "reg52.h"
%closefile tmpBuf
%assign srcFile = LibGetModelDotCFile()
%warning srcFile
%<LibSetSourceFileSection(srcFile, "Includes", tmpBuf)>
%openfile tmpBuf
%closefile tmpBuf
%assign cFile = LibCreateSourceFile("Source","Custom","GPIOconfig")
%<LibSetSourceFileSection(srcFile, "Defines", tmpBuf)>
%endfunction
%function BlockInstanceSetup(block, system) void
%endfunction
%function Outputs(block, system) Output
%assign u = LibBlockInputSignal(0, "","",0)
%assign Pin = CAST("Number", SFcnParamSettings.PIN)
P%<Pin> = %<u>;
%endfunction

建立S-function模块

建立S-function模块,并Mask掉,参数如下:

配置环境

配置ert.tlc,设置为Fixed-step,进行自动代码生成,生成后的代码中标黄的地方为用户自定义的部分

编译

在编译之前,对ert_main.c进行修改:

  • 删除掉#include <stdio.h> /* This ert_main.c example uses printf/fflush */
  • int_T main(int_T argc, const char *argv[])修改为int_T main(void),同时删除(void)(argc); (void)(argv);
  • 删除下图中部分:
  • rt_OneStep()放到 while (rtmGetErrorStatus(LED_demo_M) == (NULL))
  • rt_OneStep()的/* Enable interrupts here */部分添加一个时钟中断

上面的修改其实可以看出,要做一个合适的底层驱动,其实最好是自定义main文件

这里给一个自己修改的ert_main.c

/*
* File: ert_main.c
*
* Code generated for Simulink model 'LED'.
*
* Model version
: 1.1
* Simulink Coder version
: 9.0 (R2018b) 24-May-2018
* C/C++ source code generated on : Fri Apr 12 10:31:58 2019
*
* Target selection: ert.tlc
* Embedded hardware selection: Intel->x86-64 (Windows64)
* Code generation objectives: Unspecified
* Validation result: Not run
*/
#include <stddef.h>
#include "LED.h"
/* Model's header file */
#include "rtwtypes.h"
/*#include "reg52.h"
/*#define led_blink P0
/*
* Associating rt_OneStep with a real-time clock or interrupt service routine
* is what makes the generated code "real-time".
The function rt_OneStep is
* always associated with the base rate of the model.
Subrates are managed
* by the base rate from inside the generated code.
Enabling/disabling
* interrupts and floating point context switches are target specific.
This
* example code indicates where these should take place relative to executing
* the generated code step function.
Overrun behavior should be tailored to
* your application needs.
This example simply sets an error status in the
* real-time model and returns from rt_OneStep.
*/
typedef unsigned int u16;
void delay(u16 i)
{
while(i--);
}
void rt_OneStep(void);
void rt_OneStep(void)
{
static boolean_T OverrunFlag = false;
/* Disable interrupts here */
/* Check for overrun */
if (OverrunFlag) {
rtmSetErrorStatus(LED_M, "Overrun");
return;
}
OverrunFlag = true;
/* Save FPU context here (if necessary) */
/* Re-enable timer or interrupt here */
/* Set model inputs here */
/* Step the model */
LED_step();
/* Get model outputs here */
/*led_blink = LED_Y.Out1;
/* Indicate task complete */
OverrunFlag = false;
/* Disable interrupts here */
/* Restore FPU context here (if necessary) */
/* Enable interrupts here */
delay(100000);
}
/*
* The example "main" function illustrates what is required by your
* application code to initialize, execute, and terminate the generated code.
* Attaching rt_OneStep to a real-time clock is target specific.
This example
* illustrates how you do this relative to initializing the model.
*/
int_T main(void)
{
/* Initialize model */
LED_initialize();
/* Attach rt_OneStep to a timer or interrupt service routine with
* period 1.0 seconds (the model's base sample time) here.
The
* call syntax for rt_OneStep is
*
rt_OneStep();
*/
while (rtmGetErrorStatus(LED_M) == (NULL)) {
/*
Perform other application tasks here */
rt_OneStep();
}
/* Disable rt_OneStep() here */
/* Terminate model */
LED_terminate();
return 0;
}
/*
* File trailer for generated code.
*
* [EOF]
*/

接下来就是可以keil进行编译,生成hex文件,并通过烧录软件烧写程序了,这部分就不说了。

总结

上面的过程,实际上是利用S函数和tlc来控制代码的过程,实际上S函数还可以实现C代码的嵌入需求,好像 C Caller这个模块也行。

最后

以上就是靓丽眼神为你收集整理的[Simulink] 从Simulink S函数的使用Simulink S函数的使用Simulink C Mex S Functiondigital_in.c --> digital_in.mexw64编写digital_in.tlc建立S-function模块配置环境编译总结的全部内容,希望文章能够帮你解决[Simulink] 从Simulink S函数的使用Simulink S函数的使用Simulink C Mex S Functiondigital_in.c --> digital_in.mexw64编写digital_in.tlc建立S-function模块配置环境编译总结所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(56)

评论列表共有 0 条评论

立即
投稿
返回
顶部