基于simulink的s-function的PWM生成
simulink真是無所不能,不僅可以仿真電路,生成代碼,還可以將自己的代碼放在仿真里運(yùn)行,這里基于sfun寫一個(gè)PWM生成器,便于sfun的學(xué)習(xí)
模型
設(shè)置sfun的函數(shù)名和參數(shù),其中有兩個(gè)參數(shù)和兩個(gè)輸入信號,兩個(gè)參數(shù)分別是輸出波形的幅值和模型運(yùn)行的分辨率,這里設(shè)置幅值為5,分辨率為10k兩個(gè)輸入信號分別是占空比和周期值,這里設(shè)置占空比為50%,周期為40ms(25hz)注:分辨率要大于PWM的周期值
仿真結(jié)果如下:
代碼
/*
* File : sfun_pwm.c
* Abstract:
*
* This file represents an S-function example which demonstrates the S-function macros for using a
* controllable sample time. This S-function generates PWM (Pulse-width modulation) signals based
* on the input period and duty cycle signals.
*
* This S-function registers a controllable sample time with which the S-function can schedule the
* next hit when changing the output value. The S-function has two input ports and one output
* port. The first input port is the duty cycle signal and the second is the period signal. The
* S-function has two block parameters: the amplitude of the generated PWM signal and the
* resolution of the controllable sample time.
*
* This S-function illustrates the use of the S-function macro:
*
* ssSetControllableSampleTime(S, 0, resolution)
*
* to register a controllable sample time in mdlInitializeSampleTimes(). The resolution must be a
* positive finite number that defines the fundamental step size that the S-function can schedule
* the next hit for this sample time.
*
* This S-function illustrates the use of the S-function macro:
*
* ssSetNumTicksToNextHitForControllableSampleTime(S, 0, numTick)
*
* to schedule the next hit of the controllable sample time. The next hit happens after t =
* t_current + numTick * resolution. numTick must be a positive integer. The S-function must use
* this macro to schedule the execution of the controllable sample time in
* mdlInitializeConditions() and mdlOutputs().
*
* Copyright 2017 The MathWorks, Inc.
*/
#define S_FUNCTION_NAME mysfun_generate //函數(shù)名
#define S_FUNCTION_LEVEL 2 //sfun的深度
#include "simstruc.h"
#include "assert.h"
/* Function: mdlInitializeSizes ================================================
* Abstract:
*
* Register an S-function with two input ports, one output port, and three DWorks. Specify the
* number of sample times to 1.
*
*/
static void mdlInitializeSizes(SimStruct* S)
{
//這個(gè)函數(shù)用來初始化的,主要是設(shè)置輸入、輸出和參數(shù)的。
if (!ssSetNumInputPorts(S, 2)) return;//設(shè)置輸入信號2個(gè)
ssSetInputPortWidth(S, 0, 1);//設(shè)置輸入變量0的維數(shù)為1
ssSetInputPortDirectFeedThrough(S, 0, 1);// 設(shè)置輸入端口的信號是否mdlOutputs函數(shù)中使用,這兒設(shè)置為true
ssSetInputPortWidth(S, 1, 1);//設(shè)置輸入變量1的維數(shù)為1
ssSetInputPortDirectFeedThrough(S, 1, 1);// 設(shè)置輸入端口的信號是否mdlOutputs函數(shù)中使用,這兒設(shè)置為true
if (!ssSetNumOutputPorts(S, 1)) return;//設(shè)置輸出變量的個(gè)數(shù)
ssSetOutputPortWidth(S, 0, 1);//設(shè)置輸出變量0的維數(shù)為1維
ssSetNumSFcnParams(S, 2);//設(shè)置參數(shù)2個(gè)
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
return;
}
ssSetNumContStates(S, 0);//設(shè)置連續(xù)狀態(tài)變量的
ssSetNumDiscStates(S, 0);
ssSetNumDWork(S, 3);
ssSetDWorkWidth(S, 0, 1);//設(shè)置離散狀態(tài)變量的
ssSetDWorkDataType(S, 0, SS_BOOLEAN);
ssSetDWorkWidth(S, 1, 1);
ssSetDWorkDataType(S, 1, SS_DOUBLE);
ssSetDWorkWidth(S, 2, 1);
ssSetDWorkDataType(S, 2, SS_UINT32);
ssSetNumSampleTimes(S, 1);//設(shè)置采樣時(shí)間,此處為1s,后面有修改
ssSetOperatingPointCompliance(S, USE_DEFAULT_OPERATING_POINT);
ssSetOptions(S, SS_OPTION_EXCEPTION_FREE_CODE |
SS_OPTION_USE_TLC_WITH_ACCELERATOR);//默認(rèn)
}
/* Function: mdlInitializeSampleTimes ==========================================
* Abstract:
* Register a controllable sample time with the specified resolution.
*/
static void mdlInitializeSampleTimes(SimStruct* S)
{
real_T resolution = (real_T) *mxGetPr(ssGetSFcnParam(S,1));//設(shè)置采樣時(shí)間
ssSetControllableSampleTime(S, 0, resolution);//將參數(shù)分辨率設(shè)置成采樣時(shí)間
}
/* Function: mdlInitializeConditions============================================
* Abstract:
* Initialize the DWorks related to the generation of the PWM signals. Force a hit for the
* controllable sample time.
*/
#define MDL_INITIALIZE_CONDITIONS
static void mdlInitializeConditions(SimStruct *S)
{
//初始化離散狀態(tài)變量的值
/*
* Force a sample hit whenever the system is initialized.
*/
ssSetNumTicksToNextHitForControllableSampleTime(S, 0, 1);
boolean_T * x1 = (boolean_T*)ssGetDWork(S,0);
real_T *x2 = (real_T*)ssGetDWork(S,1);
uint32_T *x3 = (uint32_T*)ssGetDWork(S,2);
*x1 = true;
*x2 = 0.0;
*x3 = 0;
}
/* Function: mdlOutputs ========================================================
* Abstract:
* Generate the PWM signals based on the input duty cycle and period signals.
*/
static void mdlOutputs(SimStruct* S, int_T tid)
{
//這個(gè)函數(shù)就是輸出的函數(shù),所有的代碼動作在這里執(zhí)行
real_T* y = ssGetOutputPortRealSignal(S, 0);//獲取輸出端口
boolean_T* x1 = (boolean_T*)ssGetDWork(S,0);//獲取離散變量端口
real_T *x2 = (real_T*)ssGetDWork(S,1);//獲取離散變量端口
uint32_T *x3 = (uint32_T*)ssGetDWork(S,2); //獲取離散變量端口
size_t numTicksToNextHit = 0;//設(shè)置值
real_T yout_value = 0.0;
if (*x1) {
real_T amplitude_prm = (real_T) *mxGetPr(ssGetSFcnParam(S,0));
real_T period_prm = (real_T) *mxGetPr(ssGetSFcnParam(S,1));
InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S,0);
real_T duty = *uPtrs[0];
real_T p = *uPtrs[1];
size_t numSamples = (size_t) (p/period_prm);
numTicksToNextHit = (size_t) (duty*numSamples);
if (numTicksToNextHit == 0) {
numTicksToNextHit = numSamples;
yout_value = 0;
} else if (numTicksToNextHit == numSamples) {
numTicksToNextHit = numSamples;
yout_value = amplitude_prm;
} else {
*x1 = false;
*x2 = duty;
*x3 = (uint32_T)(numSamples - numTicksToNextHit);
yout_value = amplitude_prm;
}
} else {
*x1 = true;
numTicksToNextHit = (size_t) *x3;
yout_value = 0;
}
*y = yout_value;//輸出
ssSetNumTicksToNextHitForControllableSampleTime(S, 0, numTicksToNextHit); //更新下一次的采樣時(shí)間
} /* mdlOutputs */
static void mdlTerminate(SimStruct *S)
{
}
/* Required S-Function trailer */
#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