为平均值滤波器生成代码
此示例说明使用 codegen
命令从 MATLAB® 函数生成 C 代码的建议工作流。步骤如下:
1.向 MATLAB 函数添加 %#codegen
指令,以指示它用于代码生成。此指令还使 MATLAB 代码分析器能够识别特定于 MATLAB 的代码生成警告和错误。
2.生成 MEX 函数以检查 MATLAB 代码是否适用于代码生成。如果发生错误,您应在生成 C 代码之前将其修复。
3.在 MATLAB 中测试 MEX 函数,以确保它在功能上等同于原始 MATLAB 代码,并且不会出现任何运行时错误。
4.生成 C 代码。
5.检查 C 代码。
前提条件
此示例没有任何前提条件。
关于 averaging_filter
函数
averaging_filter.m
函数充当输入信号上的平均值滤波器;它采用值的输入向量并计算向量中每个值的平均值。输出向量的大小和形状与输入向量相同。
type averaging_filter
% y = averaging_filter(x) % Take an input vector signal 'x' and produce an output vector signal 'y' with % same type and shape as 'x' but filtered. function y = averaging_filter(x) %#codegen % Use a persistent variable 'buffer' that represents a sliding window of % 16 samples at a time. persistent buffer; if isempty(buffer) buffer = zeros(16,1); end y = zeros(size(x), class(x)); for i = 1:numel(x) % Scroll the buffer buffer(2:end) = buffer(1:end-1); % Add a new sample value to the buffer buffer(1) = x(i); % Compute the current average value of the window and % write result y(i) = sum(buffer)/numel(buffer); end
%#codegen
编译指令指示 MATLAB 代码用于代码生成。
创建一些样本数据
生成噪声正弦波并绘制结果。
v = 0:0.00614:2*pi;
x = sin(v) + 0.3*rand(1,numel(v));
plot(x, 'red');
生成 MEX 函数用于测试
使用 codegen
命令生成 MEX 函数。codegen
命令会检查 MATLAB 函数是否适用于代码生成,并生成 MEX 函数,您可以在生成 C 代码之前在 MATLAB 中测试该函数。
codegen averaging_filter -args {x}
Code generation successful.
由于 C 使用静态类型,codegen
必须在编译时确定 MATLAB 文件中所有变量的属性。在这里,-args
命令行选项会提供一个示例输入,以便 codegen
基于输入类型推断新类型。使用上述步骤中创建的样本信号作为示例输入可确保 MEX 函数使用相同的输入。
默认情况下,codegen
在当前文件夹中生成名为 averaging_filter_mex
的 MEX 函数。这允许您测试 MATLAB 代码和 MEX 函数,并将结果进行比较。
在 MATLAB 中测试 MEX 函数
在 MATLAB 中运行 MEX 函数
y = averaging_filter_mex(x); % Plot the result when the MEX function is applied to the noisy sine wave. % The 'hold on' command ensures that the plot uses the same figure window as % the previous plot command. hold on; plot(y, 'blue');
生成 C 代码
codegen -config coder.config('lib') averaging_filter -args {x}
Code generation successful.
检查生成的代码
带 -config coder.config('lib')
选项的 codegen
命令可生成打包为独立 C 库的 C 代码。生成的 C 代码位于 codegen/lib/averaging_filter/
文件夹中。这些文件是:
dir codegen/lib/averaging_filter/
. .. _clang-format averaging_filter.a averaging_filter.c averaging_filter.h averaging_filter.o averaging_filter_data.c averaging_filter_data.h averaging_filter_data.o averaging_filter_initialize.c averaging_filter_initialize.h averaging_filter_initialize.o averaging_filter_rtw.mk averaging_filter_terminate.c averaging_filter_terminate.h averaging_filter_terminate.o averaging_filter_types.h buildInfo.mat codeInfo.mat codedescriptor.dmr compileInfo.mat examples interface rtw_proj.tmw rtwtypes.h
检查 averaging_filter.c
函数的 C 代码
type codegen/lib/averaging_filter/averaging_filter.c
/* * Prerelease License - for engineering feedback and testing purposes * only. Not for sale. * File: averaging_filter.c * * MATLAB Coder version : 5.6 * C/C++ source code generated on : 30-Jan-2023 12:48:14 */ /* Include Files */ #include "averaging_filter.h" #include "averaging_filter_data.h" #include "averaging_filter_initialize.h" #include <string.h> /* Variable Definitions */ static double buffer[16]; /* Function Definitions */ /* * Use a persistent variable 'buffer' that represents a sliding window of * 16 samples at a time. * * Arguments : const double x[1024] * double y[1024] * Return Type : void */ void averaging_filter(const double x[1024], double y[1024]) { double dv[15]; int i; int k; if (!isInitialized_averaging_filter) { averaging_filter_initialize(); } /* y = averaging_filter(x) */ /* Take an input vector signal 'x' and produce an output vector signal 'y' * with */ /* same type and shape as 'x' but filtered. */ for (i = 0; i < 1024; i++) { double b_y; /* Scroll the buffer */ memcpy(&dv[0], &buffer[0], 15U * sizeof(double)); /* Add a new sample value to the buffer */ b_y = x[i]; buffer[0] = b_y; /* Compute the current average value of the window and */ /* write result */ for (k = 0; k < 15; k++) { double d; d = dv[k]; buffer[k + 1] = d; b_y += d; } y[i] = b_y / 16.0; } } /* * Use a persistent variable 'buffer' that represents a sliding window of * 16 samples at a time. * * Arguments : void * Return Type : void */ void averaging_filter_init(void) { memset(&buffer[0], 0, 16U * sizeof(double)); } /* * File trailer for averaging_filter.c * * [EOF] */