概述
引言
最近有接触到用C语言编写S函数,因此对这方面做了一些尝试,直接上代码。两个.c代码实现同样的功能。一个是C语言版,一个是Matlab版本。代码在我的机器上能够调试使用。如果有其他的问题,欢迎在评论区留言。
VScode能够运行的C程序:
#include<stdio.h>
#include<string.h>
typedef struct{
char Status[100];
float Value[2]; //value为结构体包含两个值。
} DS_65;
typedef struct{
float EU_at_100;
float EU_at_0;
char Units_index[20];
short int Decimal_Point;
} DS_68;
typedef struct{
char Target[20];
char Actual[20];
char Permitted[20];
char Normal[20];
} DS_69;
typedef struct{
unsigned short int Simulate_Status;
float Simulate_Value;
unsigned short int Transducer_Status;
float Transducer_Value;
unsigned short int Simulate_EnorDisable;
} DS_82;
typedef struct{
short int Propagate_Fault_Forward;
float Uncertain_if_Limited;
float BAD_if_Limited;
short int Uncertain_if_Man_mode;
} STATUS_OPTS;
typedef struct{
short int Increase_to_Close;
int Fault_State_to_value;
} IO_OPTS;
DS_65 fun(DS_65 SP,IO_OPTS IO_OPT,DS_69 MODE_BLK,float FSTATE_VAL[],
STATUS_OPTS STATUS_OPT,float INPUTVALUE[],float SP_HI_LIM,float SP_LO_LIM,
float SP_RATE_UP,float SP_RATE_DN,DS_68 PV_SCALE,DS_68 XD_SCALE,DS_65 SP_INPUT)
{
DS_65 OUT;
float SP_rate_auto;
float SP_rate_cas;
int target_mode;
int i;
target_mode = (strcmp(MODE_BLK.Target,"O/S")==0)*1+(strcmp(MODE_BLK.Target,"IMAN")==0)*2
+(strcmp(MODE_BLK.Target,"LO")==0)*3+(strcmp(MODE_BLK.Target,"MAN")==0)*4+
(strcmp(MODE_BLK.Target,"CAS")==0)*5+(strcmp(MODE_BLK.Target,"RCAS")==0)*6;
// printf("%dn",target_mode);
switch (target_mode){
case 1:
strcpy(OUT.Status,"Bad");
for(i=0;i<2;i++){
OUT.Value[i] = SP.Value[i];
}
break;
case 2:
strcpy(OUT.Status,"GoodNC");
for(i=0;i<2;i++){
OUT.Value[i] = SP.Value[i];
}
break;
case 3:
if(IO_OPT.Fault_State_to_value == 1){
strcpy(OUT.Status,"Fault State to value");
OUT.Value[0] = FSTATE_VAL[0];
OUT.Value[1] = FSTATE_VAL[1];
}
// IO_OPTS 的另外一个值:"Target to Man if Fault State activated"
else{
strcpy(OUT.Status,"Target to Man if Fault State activated");
for(i=0;i<2;i++){
OUT.Value[i] = SP.Value[i];
}}
break;
case 4:
if(STATUS_OPT.Uncertain_if_Man_mode == 1){
strcpy(OUT.Status,"Uncertain if Man mode");
for(i=0;i<2;i++){
OUT.Value[i] = INPUTVALUE[i];
}}
else {
strcpy(OUT.Status,"GoodNC");
for(i=0;i<2;i++){
OUT.Value[i] = INPUTVALUE[i];
}}
break;
case 5:
if(SP.Value[0] > SP_RATE_UP){
SP.Value[0] = SP_RATE_UP;
}
else if(SP.Value[0] < SP_RATE_DN){
SP.Value[0] = SP_RATE_DN;
}
else if(SP.Value[1] > SP_HI_LIM){
SP.Value[1] = SP_HI_LIM;
}
else if(SP.Value[1] < SP_LO_LIM){
SP.Value[1] = SP_LO_LIM;
}
else{
SP_rate_cas = (SP.Value[1] - PV_SCALE.EU_at_0)*100/(PV_SCALE.EU_at_100 -
PV_SCALE.EU_at_0); //PV_SCALE
OUT.Value[1] = SP_rate_cas*(XD_SCALE.EU_at_100-XD_SCALE.EU_at_0) +
XD_SCALE.EU_at_0; //XD_SCALE
OUT.Value[0] = SP.Value[0];
strcpy(OUT.Status, SP.Status);
}
break;
case 6:
if(SP.Value[0] > SP_RATE_UP){
SP.Value[0] = SP_RATE_UP;
}
else if(SP.Value[0] < SP_RATE_DN){
SP.Value[0] = SP_RATE_DN;
}
else if(SP.Value[1] > SP_HI_LIM){
SP.Value[1] = SP_HI_LIM;
}
else if(SP.Value[1] < SP_LO_LIM){
SP.Value[1] = SP_LO_LIM;
}
else{
SP_rate_cas = (SP.Value[1] - PV_SCALE.EU_at_0)*100/(PV_SCALE.EU_at_100 -
PV_SCALE.EU_at_0); //PV_SCALE
OUT.Value[1] = SP_rate_cas*(XD_SCALE.EU_at_100-XD_SCALE.EU_at_0) +
XD_SCALE.EU_at_0; //XD_SCALE
OUT.Value[0] = SP.Value[0];
strcpy(OUT.Status, SP.Status);
}
break;
default: // 如果MODE_BLK.Actual不设定值或者设定的值不等于上面的几种情况,则运行该块代码。为“AUTO”模式。
if(SP_INPUT.Value[0] > SP_RATE_UP){
SP_INPUT.Value[0] = SP_RATE_UP;
}
else if(SP_INPUT.Value[0] < SP_RATE_DN){
SP_INPUT.Value[0] = SP_RATE_DN;
}
else if(SP_INPUT.Value[1] > SP_HI_LIM){
SP_INPUT.Value[1] = SP_HI_LIM;
}
else if(SP_INPUT.Value[1] < SP_LO_LIM){
SP_INPUT.Value[1] = SP_LO_LIM;
}
else{
SP_rate_auto = (SP_INPUT.Value[1] - PV_SCALE.EU_at_0)*100/(PV_SCALE.EU_at_100 -
PV_SCALE.EU_at_0); //PV_SCALE
OUT.Value[1] = SP_rate_auto*(XD_SCALE.EU_at_100-XD_SCALE.EU_at_0) +
XD_SCALE.EU_at_0; //XD_SCALE
OUT.Value[0] = SP_INPUT.Value[0];
strcpy(OUT.Status, SP_INPUT.Status);
}}
return OUT;
}
void main()
{
DS_65 sp = {"test_the_fun.",{0.2, 15}};
IO_OPTS io_opt = {1, 1};
DS_69 mode_blk = {"CAS","AUTO",'p','n'};
float fstate_val[] = {0.1,5.0};
STATUS_OPTS status_opts = {0, 0.4, 0.5, 1};
float input_value[] = {0.3, 30.0};
float sp_hi_lim = 100; // 默认值为100%。
float sp_lo_lim = 0; // 默认值为0。
float sp_rate_up = 2; // 默认值为-inf。
float sp_rate_dn = 0; // 默认值为+inf。
DS_68 pv_scale = {20, 4, "mA", 2};
DS_68 xd_scale = {100, 20, "kPa", 2};
DS_65 sp_input = {"man input.",{0.3,30}}; //操作员输入的SP。
DS_65 out;
out = fun(sp,io_opt,mode_blk,fstate_val,status_opts,input_value,sp_hi_lim,
sp_lo_lim,sp_rate_up,sp_rate_dn,pv_scale,xd_scale,sp_input);
printf("%s %.2f %.2f", out.Status, out.Value[0], out.Value[1]);
}
Matlab能够运行的C程序:
在matlab中编译使用如下命令:
mex -g AO_MATLAB.c %AO_MATLAB.c为c代码文件名。
#define S_FUNCTION_NAME AO_MATLAB//这里把文件名sfuntmpl_basic修改为test
#define S_FUNCTION_LEVEL 2
#include<stdio.h>
#include<string.h>
#include<simstruc.h>
//程序里面要用到的头文件在这里引用,如“math.h”等。
static void mdlInitializeSizes(SimStruct *S)
{
//这个函数用来设置输入、输出和参数的。
ssSetNumSFcnParams(S, 33); /*设置参数个数,这里为3 */
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
return;
}
ssSetNumContStates(S, 0);//设置连续状态的个数,缺省为0;
ssSetNumDiscStates(S, 0);//设置离散状态的个数,缺省为0;
if (!ssSetNumInputPorts(S, 3)) return;//设置输入变量的个数,这里为1
ssSetInputPortWidth(S, 0, 1); //设置输入变量0的维数为1
ssSetInputPortWidth(S, 1, 1); //设置输入变量0的维数为1
ssSetInputPortWidth(S, 2, 1); //设置输入变量0的维数为1
ssSetInputPortRequiredContiguous(S, 0, true); //设置input0的访问方式,true就是临近访问,这样指针的增量后就可以直接访问下个input端口了。
ssSetInputPortDirectFeedThrough(S, 0, 1);// 设置输入端口的信号是否mdlOutputs函数中使用,这儿设置为true。
if (!ssSetNumOutputPorts(S, 3)) return;//设置输出变量的个数
ssSetOutputPortWidth(S, 0, 1);//设置输出变量0的维数为1维
ssSetOutputPortWidth(S, 1, 1);//设置输出变量1的维数为1维
ssSetOutputPortWidth(S, 2, 1);//设置输出变量2的维数为1维
ssSetNumSampleTimes(S, 1); //设置采样时间,此处为1s。
ssSetNumRWork(S, 0);//不管
ssSetNumIWork(S, 0);
ssSetNumPWork(S, 0);
ssSetNumModes(S, 0);
ssSetNumNonsampledZCs(S, 0);
ssSetOptions(S, 0);
//下面可以写全局变量的初始化程序
}
static void mdlInitializeSampleTimes(SimStruct *S)//暂时不管
{
ssSetSampleTime(S, 0, CONTINUOUS_SAMPLE_TIME);
ssSetOffsetTime(S, 0, 0.0);
}
#define MDL_INITIALIZE_CONDITIONS /* Change to #undef to remove function */
#if defined(MDL_INITIALIZE_CONDITIONS)
static void mdlInitializeConditions(SimStruct *S)//暂时不管
{
}
#endif /* MDL_INITIALIZE_CONDITIONS */
#define MDL_START /* Change to #undef to remove function */
#if defined(MDL_START)
static void mdlStart(SimStruct *S)//暂时不管
{
}
#endif /* MDL_START */
static void mdlOutputs(SimStruct *S, int_T tid)//这里填入相关的运算、算法等
{
int i;
real_T *IO_OPT_Fault_State_to_value = mxGetPr(ssGetSFcnParam(S,0)); //1
real_T *CONSTANT_0 = mxGetPr(ssGetSFcnParam(S,1)); //1
real_T *FSTATE_VAL_rate = mxGetPr(ssGetSFcnParam(S,2)); //0.1
real_T *STATUS_OPT_Uncertain_if_Man_mode = mxGetPr(ssGetSFcnParam(S,3)); //1
real_T *INPUTVALUE_rate = mxGetPr(ssGetSFcnParam(S,4)); // 定的是0.3,可改
real_T *SP_HI_LIM = mxGetPr(ssGetSFcnParam(S,5)); //100
real_T *SP_LO_LIM = mxGetPr(ssGetSFcnParam(S,6)); //0
real_T *SP_RATE_DN = mxGetPr(ssGetSFcnParam(S,7)); //0
real_T *SP_RATE_UP = mxGetPr(ssGetSFcnParam(S,8)); //2
real_T *PV_SCALE_EU_at_100 = mxGetPr(ssGetSFcnParam(S,9)); //20
real_T *PV_SCALE_EU_at_0 = mxGetPr(ssGetSFcnParam(S,10)); //4
real_T *XD_SCALE_EU_at_100 = mxGetPr(ssGetSFcnParam(S,11));//100
real_T *XD_SCALE_EU_at_0 = mxGetPr(ssGetSFcnParam(S,12)); //20
real_T *SP_INPUT_Value_rate = mxGetPr(ssGetSFcnParam(S,13)); //0.3
real_T *MODECONSTANT_0 = mxGetPr(ssGetSFcnParam(S,14)); //"O/S"
real_T *RESULTCONSTANT_0 = mxGetPr(ssGetSFcnParam(S,15)); //"Bad"
real_T *MODE_BLK_Target = mxGetPr(ssGetSFcnParam(S,16)); //"CAS"
real_T *SP_INPUT_Status = mxGetPr(ssGetSFcnParam(S,17)); //"man input."
real_T *SP_INPUT_Value_hl = mxGetPr(ssGetSFcnParam(S,18)); //30
real_T *CONSTANT_3 = mxGetPr(ssGetSFcnParam(S,19)); //设定为100.
real_T *RESULTCONSTANT_1 = mxGetPr(ssGetSFcnParam(S,20)); //"GoodNC"
real_T *RESULTCONSTANT_2 = mxGetPr(ssGetSFcnParam(S,21)); //"Fault State to value"
real_T *RESULTCONSTANT_3 = mxGetPr(ssGetSFcnParam(S,22)); //"Target to Man if Fault State activated"
real_T *RESULTCONSTANT_4 = mxGetPr(ssGetSFcnParam(S,23)); //"Uncertain if Man mode"
real_T *RESULTCONSTANT_5 = mxGetPr(ssGetSFcnParam(S,24)); //"GoodNC"
real_T *INPUTVALUE_hl = mxGetPr(ssGetSFcnParam(S,25)); //30.0
real_T *CONSTANT_1 = mxGetPr(ssGetSFcnParam(S,26)); //1
real_T *FSTATE_VAL_hl = mxGetPr(ssGetSFcnParam(S,27)); //5.0
real_T *MODECONSTANT_1 = mxGetPr(ssGetSFcnParam(S,28)); //"IMAN"
real_T *MODECONSTANT_2 = mxGetPr(ssGetSFcnParam(S,29)); //"LO"
real_T *MODECONSTANT_3 = mxGetPr(ssGetSFcnParam(S,30)); //"MAN"
real_T *MODECONSTANT_4 = mxGetPr(ssGetSFcnParam(S,31)); //"CAS"
real_T *MODECONSTANT_5 = mxGetPr(ssGetSFcnParam(S,32)); //"RCAS"
real_T *SP_Value_rate = (real_T*) ssGetInputPortSignal(S,0);
real_T *SP_Value_hl = (real_T*) ssGetInputPortSignal(S,1);
real_T *SP_Status = (real_T*) ssGetInputPortSignal(S,2);
real_T *OUT_Value_rate = ssGetOutputPortSignal(S,0);
real_T *OUT_Value_hl = ssGetOutputPortSignal(S,1);
real_T *OUT_Status = ssGetOutputPortSignal(S,2);
switch ((MODE_BLK_Target[0]==MODECONSTANT_0[0])*1+(MODE_BLK_Target[0]==MODECONSTANT_1[0])*2
+(MODE_BLK_Target[0]==MODECONSTANT_2[0])*3+(MODE_BLK_Target[0]==MODECONSTANT_3[0])*4+
(MODE_BLK_Target[0]==MODECONSTANT_4[0])*5+(MODE_BLK_Target[0]==MODECONSTANT_5[0])*6){
case 1:
OUT_Status[0]=RESULTCONSTANT_0[0];
OUT_Value_rate[0] = SP_Value_rate[0];
OUT_Value_hl[0] = SP_Value_hl[0];
break;
case 2:
OUT_Status[0]=RESULTCONSTANT_1[0];
OUT_Value_rate[0] = SP_Value_rate[0];
OUT_Value_hl[0] = SP_Value_hl[0];
break;
case 3:
if(IO_OPT_Fault_State_to_value[0] == CONSTANT_1[0]){
OUT_Status[0]=RESULTCONSTANT_2[0];
OUT_Value_rate[0] = FSTATE_VAL_rate[0];
OUT_Value_hl[0] = FSTATE_VAL_hl[0];
}
// IO_OPTS 的另外一个值:"Target to Man if Fault State activated"
else{
OUT_Status[0]=RESULTCONSTANT_3[0];
OUT_Value_rate[0] = SP_Value_rate[0];
OUT_Value_hl[0] = SP_Value_hl[0];
}
break;
case 4:
if(STATUS_OPT_Uncertain_if_Man_mode[0] == CONSTANT_0[0]){
OUT_Status[0] = RESULTCONSTANT_4[0];
OUT_Value_rate[0] = INPUTVALUE_rate[0];
OUT_Value_hl[0] = INPUTVALUE_hl[0];
}
else {
OUT_Status[0]=RESULTCONSTANT_5[0];
OUT_Value_rate[0] = INPUTVALUE_rate[0];
OUT_Value_hl[0] = INPUTVALUE_hl[0];
}
break;
case 5:
if(SP_Value_rate[0] > SP_RATE_DN[0]){
SP_Value_rate[0] = SP_RATE_DN[0];
}
else if(SP_Value_rate[0] < SP_RATE_DN[0]){
SP_Value_rate[0] = SP_RATE_DN[0];
}
else if(SP_Value_hl[0] > SP_HI_LIM[0]){
SP_Value_hl[0] = SP_HI_LIM[0];
}
else if(SP_Value_hl[0] < SP_LO_LIM[0]){
SP_Value_hl[0] = SP_LO_LIM[0];
}
else{
OUT_Value_hl[0] = (SP_Value_hl[0]- PV_SCALE_EU_at_0[0])*CONSTANT_3[0]/(PV_SCALE_EU_at_100[0] - PV_SCALE_EU_at_0[0])
*((XD_SCALE_EU_at_100[0]-XD_SCALE_EU_at_0[0]) + XD_SCALE_EU_at_0[0]);
OUT_Value_rate[0] = SP_Value_rate[0];
OUT_Status[0] = SP_Status[0];
}
break;
case 6:
if(SP_Value_rate[0] > SP_RATE_DN[0]){
SP_Value_rate[0] = SP_RATE_DN[0];
}
else if(SP_Value_rate[0] < SP_RATE_DN[0]){
SP_Value_rate[0] = SP_RATE_DN[0];
}
else if(SP_Value_hl[0] > SP_HI_LIM[0]){
SP_Value_hl[0] = SP_HI_LIM[0];
}
else if(SP_Value_hl[0] < SP_LO_LIM[0]){
SP_Value_hl[0] = SP_LO_LIM[0];
}
else{
OUT_Value_hl[0] = (SP_Value_hl[0]- PV_SCALE_EU_at_0[0])*CONSTANT_3[0]/(PV_SCALE_EU_at_100[0] - PV_SCALE_EU_at_0[0])
*((XD_SCALE_EU_at_100[0]-XD_SCALE_EU_at_0[0]) + XD_SCALE_EU_at_0[0]);
OUT_Value_rate[0] = SP_Value_rate[0];
OUT_Status[0] = SP_Status[0];
}
break;
default: // 如果MODE_BLK.Actual不设定值或者设定的值不等于上面的几种情况,则运行该块代码。为“AUTO”模式。
if(SP_INPUT_Value_rate[0] > SP_RATE_DN[0]){
SP_INPUT_Value_rate[0] = SP_RATE_DN[0];
}
else if(SP_INPUT_Value_rate[0] < SP_RATE_DN[0]){
SP_INPUT_Value_rate[0] = SP_RATE_DN[0];
}
else if(SP_INPUT_Value_rate[0] > SP_HI_LIM[0]){
SP_INPUT_Value_rate[0] = SP_HI_LIM[0];
}
else if(SP_INPUT_Value_rate[0] < SP_LO_LIM[0]){
SP_INPUT_Value_rate[0] = SP_LO_LIM[0];
}
else{
OUT_Value_hl[0] = (SP_INPUT_Value_hl[0]- PV_SCALE_EU_at_0[0])*CONSTANT_3[0]/(PV_SCALE_EU_at_100[0] - PV_SCALE_EU_at_0[0])
*((XD_SCALE_EU_at_100[0]-XD_SCALE_EU_at_0[0]) + XD_SCALE_EU_at_0[0]);
OUT_Value_rate[0] = SP_INPUT_Value_rate[0];
OUT_Status[0] = SP_INPUT_Status[0];
}}
}
#define MDL_UPDATE /* Change to #undef to remove function */
#if defined(MDL_UPDATE)
static void mdlUpdate(SimStruct *S, int_T tid)
{
}
#endif /* MDL_UPDATE */
#define MDL_DERIVATIVES /* Change to #undef to remove function */
#if defined(MDL_DERIVATIVES)
static void mdlDerivatives(SimStruct *S)
{
}
#endif /* MDL_DERIVATIVES */
static void mdlTerminate(SimStruct *S)//这里需要把global变量全部初始化,否则下次运行程序时,全局变量还是之前的值。
{
}
#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
调试过程中有用的链接:
- MATLAB中调用MEX文件相关的介绍;
- MATLAB中的S-Function的用法(C语言)
- mex -setup 未找到支持的编译器或 SDK。您可以安装免费提供的 MinGW-w64 C/C++ 编译器;请参阅安装 MinGW-w64 编译器。有关更多选项,请访问
后记:
C语言指针和数组在使用时很繁琐,以上代码在调试的过程中出现的问题,也主要是指针和数组的问题。欢迎在评论区留言交流。
最后
以上就是安静天空为你收集整理的使用C语言编写S函数实例的全部内容,希望文章能够帮你解决使用C语言编写S函数实例所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复