首页 > 其他分享 >MATLAB/Simulink中调用C语言实现的传递函数

MATLAB/Simulink中调用C语言实现的传递函数

时间:2023-11-17 17:25:36浏览次数:32  
标签:Simulink ufilter float lp1st C语言 filter MATLAB ma lp2nd

1. 引言

在变流器控制中,通常采用C语言实现传递函数,且通常写成独立的C文件,本文简要介绍如何在MATLAB/Simulink中调用这些C文件。

在本文中,采用C语言实现了一阶低通滤波器、二阶低通滤波器、滑动平均滤波器,具体代码见附录。同时需要安装C编译工具链,参考《Using GCC with MinGW》

2. 接口代码文件准备

为调用已写好的C文件,需要做一层额外的封装供Simulink的MATLAB Function调用。本文将这一接口文件命名作porting.hporting.c

2.1 porting.c文件

在该文件中,主要提供两类函数:仿真运行开始时的初始化(init)函数、离散周期中调用的回调(callback)函数。这两类函数都是基于已有的文件进行封装的,一个原则就是不要动已有的文件。

#include "ufilter.h"
#include "porting.h"

/**
 * @brief Handler for the 1st-order LPF
 */
static ufilter_lp1st_t lp1st;
/**
 * @brief Hanlder for the 2nd-order LPF
 */
static ufilter_lp2nd_t lp2nd;
/**
 * @brief Handler for the moving average
 */
static float ma_buffer[260];
static ufilter_ma_t ma;


float porting_ufilter_lp1st_init_lp1st(void)
{
    ufilter_lp1st_init(&lp1st, 314, 0.0001);
}

float porting_ufilter_lp1st_callback_lp1st(float _x)
{
    float y;
    y = ufilter_lp1st_callback(&lp1st, _x);
    return y;
}

float porting_ufilter_lp2nd_init_lp2nd(void)
{
    ufilter_lp2nd_init(&lp2nd, 314, 0.5, 0.0001);
}

float porting_ufilter_lp2nd_callback_lp2nd(float _x)
{
    float y;
    y = ufilter_lp2nd_callback(&lp2nd, _x);
    return y;
}

float porting_ufilter_ma_init_ma(void)
{
    ufilter_ma_init(&ma, 260, ma_buffer);
}

float porting_ufilter_ma_callback_ma(float _x)
{
    float y;
    y = ufilter_ma_callback(&ma, _x, 200);
    return y;
}

2.2 porting.h文件

该文件的主要作用时将已经封装函数声明,供外部调用。

float porting_ufilter_lp1st_init_lp1st(void);
float porting_ufilter_lp1st_callback_lp1st(float _x);

float porting_ufilter_lp2nd_init_lp2nd(void);
float porting_ufilter_lp2nd_callback_lp2nd(float _x);

float porting_ufilter_ma_init_ma(void);
float porting_ufilter_ma_callback_ma(float _x);

3. Simulink调用及配置方法

3.1 初始化函数的调用

在如下位置调用porting.c文件中重新封装的初始化函数。

image

3.2 回调函数的调用

在Simulink中添加MATLAB Function模块,在MATLAB Function中调用porting.c文件中重新封装的回调函数,例如:

function y = lp1st(u)

y = 0;
y = coder.ceval("porting_ufilter_lp1st_callback_lp1st", u);

end

并将MATLAB Function模块的Update method设置为DiscreteSample Time设置为C代码中回调函数在实际系统中的采样周期。(在Simulink中MODELING选项卡下选择Model Explorer可打开以下窗口)

image

3.3 Simulink仿真文件配置

主要需要进行3个内容的配置:Include directories (C文件所在路径)、Header file(以代码方式添加)、Source file(列出C文件)。

image

image

image

4. 仿真效果

仿真模型如下:

image

运行结果如下,仿真结果正确:

image

附录

A. ufilter.h文件

/**
 *******************************************************************************
 * @file    ufilter.h
 * @author  xixizhk
 *******************************************************************************
 * @version V20210109 \n
 * Initial version.
 *******************************************************************************
 */


/* Define to prevent recursive inclusion **************************************/
#ifndef _UFILTER_H
#define _UFILTER_H

#ifdef __cplusplus
extern "C" {
#endif

/**
 *******************************************************************************
 * @addtogroup Includes
 * @{
 */

#include "stdint.h"

/**
 * @}
 */

/**
 *******************************************************************************
 * @addtogroup Definitions
 * @{
 */

/** Definition of the handler for the 1st lowpass filter. */
typedef struct
{
    /* Coefficients for differential equation */
    float b_0;
    float a_1;
    /* Intermediate variables */
    float y_k_1;
} ufilter_lp1st_t;

/** Definition of the handler for the 2nd lowpass filter. */
typedef struct
{
    /* Coefficients for differential equation */
    float b_1;
    float a_1;
    float a_2;
    /* Intermediate variables */
    float x_k_1;
    float y_k_1;
    float y_k_2;
} ufilter_lp2nd_t;

/* Definitions of the handler for the moving average. */
typedef struct
{
    /* Pointer to integral buffer. */
    float *buffer;
    /* Length of int_buffer. */
    unsigned int N;
    /* Index for callback. */
    unsigned int index;
    /* Offset for integral. */
    float offset;
} ufilter_ma_t;

/**
 * @}
 */

/**
 *******************************************************************************
 * @addtogroup Types
 * @{
 */

/**
 * @}
 */

/**
 *******************************************************************************
 * @addtogroup Constants
 * @{
 */

/**
 * @}
 */

/**
 *******************************************************************************
 * @addtogroup Variables
 * @{
 */

/**
 * @}
 */

/**
 *******************************************************************************
 * @addtogroup Macros
 * @{
 */

/**
 * @}
 */

/**
 *******************************************************************************
 * @addtogroup Functions
 * @{
 */

/* For the 1st lowpass filter. */
void ufilter_lp1st_init
(
    ufilter_lp1st_t *_ufilter,
    float _omega_c,
    float _Ts
);
float ufilter_lp1st_callback
(
    ufilter_lp1st_t *_ufilter,
    float _input
);
void ufilter_lp1st_reset
(
    ufilter_lp1st_t *_ufilter
);

/* For the 2nd lowpass filter. */
void ufilter_lp2nd_init
(
    ufilter_lp2nd_t *_ufilter,
    float _omega_n,
    float _zeta,
    float _Ts
);
float ufilter_lp2nd_callback
(
    ufilter_lp2nd_t *_ufilter,
    float _input
);
void ufilter_lp2nd_reset
(
    ufilter_lp2nd_t *_ufilter
);

/* For the moving average. */
void ufilter_ma_init
(
    ufilter_ma_t *_ufilter,
    unsigned int _N,
    float *_buffer
);
float ufilter_ma_callback
(
    ufilter_ma_t *_ufilter,
    float _input,
    unsigned int _W
);
void ufilter_ma_reset
(
    ufilter_ma_t *_ufilter
);

/**
 * @}
 */


#ifdef __cplusplus
}
#endif


#endif /* _UFILTER_H */

/**************************** ALL RIGHTS RESERVED *****************************/

B. ufilter.c文件

/**
 *******************************************************************************
 * @file    ufilter.c
 * @author  xixizhk
 *******************************************************************************
 * @version V20210109 \n
 * Initial version.
 *******************************************************************************
 */


/**
 *******************************************************************************
 * @addtogroup Includes
 * @{
 */

#include "ufilter.h"
#include "math.h"

/**
 * @}
 */

/**
 *******************************************************************************
 * @addtogroup Definitions
 * @{
 */

/**
 * @}
 */

/**
 *******************************************************************************
 * @addtogroup Types
 * @{
 */

/**
 * @}
 */

/**
 *******************************************************************************
 * @addtogroup Constants
 * @{
 */

/**
 * @}
 */

/**
 *******************************************************************************
 * @addtogroup Variables
 * @{
 */

/**
 * @}
 */

/**
 *******************************************************************************
 * @addtogroup Macros
 * @{
 */

/**
 * @}
 */

/**
 *******************************************************************************
 * @addtogroup Functions
 * @{
 */

/**
 * @brief   Initialize the handler of the 1st lowpass filter.
 * @param   _ufilter [In]: Pointer to the handler of the filter.
 * @param   _omega_c [In]: Cut frequency of the filter.
 * @param   _Ts [In]: Sample time.
 * @retval  None.
 */
void ufilter_lp1st_init
(
    ufilter_lp1st_t *_ufilter,
    float _omega_c,
    float _Ts
)
{
    /* Coefficients calculation */
    _ufilter->b_0 = _omega_c * _Ts;
    /**
     * Origin expression:
     *  _ufilter->a_1 = -exp(-(_omega_c * _Ts)),
     * which results in steady-state error.
     */
    _ufilter->a_1 = -(1.0F - _omega_c * _Ts);
    /* Reset intermediate variables */
    ufilter_lp1st_reset(_ufilter);
}

/**
 * @brief   Callback function of the 1st lowpass filter.
 * @param   _ufilter [In]: Pointer to the handler of the filter.
 * @param   _input [In]: Input of the filter.
 * @retval  Output of the filter.
 */
float ufilter_lp1st_callback
(
    ufilter_lp1st_t *_ufilter,
    float _input
)
{
    float output;
    /* Calculate output */
    output = _ufilter->b_0 * _input - _ufilter->a_1 * _ufilter->y_k_1;
    /* Update intermediate variables */
    _ufilter->y_k_1 = output;
    /* Return output */
    return output;
}

/**
 * @brief   Reset the handler of the 1st lowpass filter.
 * @param   _ufilter [In]: Pointer to the handler of the filter.
 * @retval  None.
 */
void ufilter_lp1st_reset
(
    ufilter_lp1st_t *_ufilter
)
{
    _ufilter->y_k_1 = 0;
}

/**
 * @brief   Initialize the handler of the 2nd lowpass filter.
 * @param   _ufilter [In]: Pointer to the handler of the filter.
 * @param   _omega_n [In]: Resonant frequency of the filter.
 * @param   _zeta [In]: Coefficient of damping.
 * @param   _Ts [In]: Sample time.
 * @retval  None.
 */
void ufilter_lp2nd_init
(
    ufilter_lp2nd_t *_ufilter,
    float _omega_n,
    float _zeta,
    float _Ts
)
{
    /* Coefficients calculation */
    _ufilter->b_1 = _omega_n * _Ts / sqrt(1 - _zeta * _zeta)
            * exp(-_zeta * _omega_n * _Ts)
            * sin(_omega_n * _Ts * sqrt(1 - _zeta * _zeta));
    _ufilter->a_1 = -2 * exp(-_zeta * _omega_n * _Ts)
            * cos(_omega_n * _Ts * sqrt(1 - _zeta * _zeta));
    _ufilter->a_2 = exp(-2 * _zeta * _omega_n * _Ts);
    /* Reset intermediate variables */
    ufilter_lp2nd_reset(_ufilter);
}

/**
 * @brief   Callback function of the 2nd lowpass filter.
 * @param   _ufilter [In]: Pointer to the handler of the filter.
 * @param   _input [In]: Input of the filter.
 * @retval  Output of the filter.
 */
float ufilter_lp2nd_callback
(
    ufilter_lp2nd_t *_ufilter,
    float _input
)
{
    float output;
    /* Calculate output */
    output = _ufilter->b_1 * _ufilter->x_k_1 - _ufilter->a_1 * _ufilter->y_k_1
            - _ufilter->a_2 * _ufilter->y_k_2;
    /* Update intermediate variables */
    _ufilter->x_k_1 = _input;
    _ufilter->y_k_2 = _ufilter->y_k_1;
    _ufilter->y_k_1 = output;
    /* Return output */
    return output;
}

/**
 * @brief   Reset the handler of the 2nd lowpass filter.
 * @param   _ufilter [In]: Pointer to the handler of the filter.
 * @retval  None.
 */
void ufilter_lp2nd_reset
(
    ufilter_lp2nd_t *_ufilter
)
{
    _ufilter->x_k_1 = 0;
    _ufilter->y_k_1 = 0;
    _ufilter->y_k_2 = 0;
}

/**
 * @brief   Initialize handler of specified moving average handler.
 * @param   _ufilter [In]: Pointer to the handler of moving average.
 * @param   _N [In]: Length of integral buffer.
 * @param   _buffer [In]: Pointer to integral buffer.
 * @retval  None.
**/
void ufilter_ma_init
(
    ufilter_ma_t *_ufilter,
    unsigned int _N,
    float *_buffer
)
{
    unsigned int i;
    _ufilter->N = _N;
    _ufilter->buffer = _buffer;
    _ufilter->index = 0;
    _ufilter->offset = 0;
    for (i = 0; i < _N; i++)
    {
        *(_ufilter->buffer + i) = 0;
    }
}

/**
 * @brief   Callback function of specified moving average handler to
 *          calculate the output.
 * @param   _ufilter [In]: Pointer to the handler of moving average.
 * @param   _input [In]: Input of moving average.
 * @param   _W [In]: Length of window of moving average (1 <= W <= N).
 * @retval  Value of moving average.
**/
float ufilter_ma_callback
(
    ufilter_ma_t *_ufilter,
    float _input,
    unsigned int _W
)
{
    float tmp_float;

    /* moving average.*/
    float ave;
    /* Integral value at the end of the window and its index. */
    float int_W;
    unsigned int int_W_index;

    /* Limit the window. */
    if (_W > _ufilter->N)
    {
        _W = _ufilter->N;
    }
    if (_W == 0)
    {
        _W = 1;
    }

    /* Update callback index and calculate integral. */
    tmp_float = *(_ufilter->buffer + _ufilter->index);
    _ufilter->index = (_ufilter->index + 1U) % _ufilter->N;
    int_W_index = (_ufilter->index + _ufilter->N - _W) % _ufilter->N;
    int_W = *(_ufilter->buffer + int_W_index);
    *(_ufilter->buffer + _ufilter->index) = tmp_float + _input;

    /* Determine the offset and add to the buffer. */
    if ( _ufilter->index == 0U)
    {
        _ufilter->offset = *(_ufilter->buffer + _ufilter->index);
        *(_ufilter->buffer + _ufilter->index) = 0.0F;
    }

    /* Calculate moving average. */
    if (int_W_index >= _ufilter->index)
    {
        int_W -= _ufilter->offset;
    }
    ave = (*(_ufilter->buffer + _ufilter->index) - int_W) / ((float)_W);

    /* Return the average. */
    return ave;
}

/**
 * @brief   Reset the handler of the moving average filter.
 * @param   _ufilter [In]: Pointer to the handler of the filter.
 * @retval  None.
 */
void ufilter_ma_reset
(
    ufilter_ma_t *_ufilter
)
{
    unsigned int i;
    for (i = 0; i < _ufilter->N; i++)
    {
        *(_ufilter->buffer + i) = 0.0F;
    }
}

/**
 * @}
 */


/**************************** ALL RIGHTS RESERVED *****************************/

参考文献

[1] Rlover_star. Simulink调用外部C代码的几种方法. 2023.11.17. https://blog.csdn.net/Rlover_star/article/details/127882271

标签:Simulink,ufilter,float,lp1st,C语言,filter,MATLAB,ma,lp2nd
From: https://www.cnblogs.com/zysgy/p/17839223.html

相关文章

  • matlab plot 画图 刻度标签
    指定坐标轴范围您可以设置x轴、y轴和z坐标轴范围,以控制数据在坐标区上的显示位置。您也可以更改x轴线和y轴线的显示位置(仅适用于二维绘图),或反转值沿每条轴递增的方向。更改坐标轴范围创建一个线图。使用xlim和ylim函数指定坐标轴范围。对于三维绘图,请使用zlim函......
  • 基于物理层网络编码的相位同步算法matlab仿真
    1.算法运行效果图预览   2.算法运行软件版本matlab2022a 3.算法理论概述       基于物理层网络编码的相位同步算法是一种利用物理层网络编码技术来实现相位同步的算法。这种算法的原理是将两个或多个相位不同的信号进行叠加,产生一个叠加信号,然后通过分析叠加......
  • 使用C语言Beep()函数演奏歌曲
    曲子是大佬王宗贤的《孔雀之舞》,网上没有找到五线谱,只有简谱,而且曲子速度不明确。通过相关演奏音乐的可大体得知,因为连音较多,至10个小节处为24秒,所以每个小节是2.4秒,因为是2/4拍,每个小节是2拍,所以每半个拍子对应的时长是0.6秒,对应的是一个八分音符的音长,600毫秒在函数中用变量f控......
  • 入门c语言--3---关于qsort函数的一些理解
     qsort函数是c语言库函数的一种,作用是将所给的数组中的元素按要求进行排序。 qsort函数可以理解为冒泡函数的进阶,冒泡函数只能对一些如int,char等类型的数组进行排序,当遇到自主定义的struct类型的数组时便不能进行排序。此时便可以通过qsort函数进行排序。  在使用qsort函数......
  • matlab实现频谱感知-认知无线电
    1、前言\(\quad\)频谱感知的方法有很多,比如匹配滤波探测,能量检测,静态循环特征探测等方法,然后最近因为在用硬件做能量检测,所以本文主要是说了如何用matlab实现能量检测,它的大概流程就是:信号采样->模平方->累加->判决,其他的方法不再了解。2、一些前置知识:恒虚警率阈值......
  • 数据结构C语言之线性表
    发现更多计算机知识,欢迎访问Cr不是铬的个人网站1.1线性表的定义线性表是具有相同特性的数据元素的一个有限序列对应的逻辑结构图形:从线性表的定义中可以看出它的特性:(1)有穷性:一个线性表中的元素个数是有限的(2)一致性:一个线性表中所有元素的性质相同,即数据类型相同(3)序列性:各......
  • 实验4 C语言数组应用编程
    1实验任务1task1_1源代码1#include<stdio.h>2#defineN43voidtest1(){4inta[N]={1,9,8,4};5inti;6//输出数组a占用的内存字节数7printf("sizeof(a)=%d\n",sizeof(a));8//输出int类型数组a中每个元素的地址、值9for(i=0;i<N;......
  • c语言 函数参数个数影响
    参考:https://blog.csdn.net/Cheatscat/article/details/79306021https://blog.csdn.net/Dr_Haven/article/details/89383342一个函数的参数的数目过多(尤其是超过8个)显然是一种不可取的编程风格。参数的数目直接影响调用函数的速度,参数越多,调用函数越慢。参数的数目少,程序就显得......
  • c语言学习(文件)练习43
    需求:将10000以二进制的形式存入文件中#define_CRT_SECURE_NO_WARNINGS1#include<stdio.h>intmain(){ inta=10000; FILE*pf=fopen("D:\\桌面\\test.txt","wb"); fwrite(&a,1,1,pf); fclose(pf); pf=NULL; return0;} ......
  • Matlab
    a(2:end)取第二行到最后一行a(end)table_sample=sampleColor;table_scale=ScaleColor;subplot(1,2,1);sample_uv=table2array(table_sample);[sample_u,sample_v]=deal(sample_uv(:,1),sample_uv(:,2));plot(sample_u,sample_v);xlim([0,0.5]);ylim([0,0.5]);......