exponenta event banner

Создание кода для фильтра усреднения

В этом примере показан рекомендуемый рабочий процесс для генерации кода C из функции MATLAB ® с помощью codegen команда. Ниже перечислены шаги:

1. Добавить %#codegen директиву функции MATLAB, указывающую, что она предназначена для генерации кода. Эта директива также позволяет анализатору кода MATLAB определять предупреждения и ошибки, характерные для MATLAB, для генерации кода.

2. Создайте функцию MEX для проверки пригодности кода MATLAB для создания кода. При возникновении ошибок необходимо исправить их перед созданием кода C.

3. Проверьте функцию MEX в MATLAB, чтобы убедиться, что она функционально эквивалентна исходному коду 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');

Figure contains an axes. The axes contains an object of type line.

Создание функции MEX для тестирования

Создайте функцию MEX с помощью codegen команда. codegen команда проверяет, подходит ли функция MATLAB для генерации кода, и генерирует функцию MEX, которую можно протестировать в MATLAB перед генерацией кода C.

codegen averaging_filter -args {x}
Code generation successful.

Поскольку C использует статическую типизацию, codegen должен определять свойства всех переменных в файлах MATLAB во время компиляции. Здесь, -args параметр командной строки предоставляет пример ввода, так что codegen может выводить новые типы на основе входных типов. Использование образца сигнала, созданного выше, в качестве примера ввода гарантирует, что функция MEX может использовать тот же вход.

По умолчанию codegen генерирует функцию MEX с именем averaging_filter_mex в текущей папке. Это позволяет протестировать код MATLAB и функцию MEX и сравнить результаты.

Тестирование функции MEX в MATLAB

Выполнение функции MEX в MATLAB

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');

Figure contains an axes. The axes contains 2 objects of type line.

Создать код C

codegen -config coder.config('lib') averaging_filter -args {x}
Code generation successful.

Проверка созданного кода

codegen с помощью команды -config coder.config('lib') создает код C, упакованный как автономная библиотека C. Сгенерированный код C находится в codegen/lib/averaging_filter/ папка. Файлы:

dir codegen/lib/averaging_filter/
.                              averaging_filter_terminate.c   
..                             averaging_filter_terminate.h   
.gitignore                     averaging_filter_terminate.o   
_clang-format                  averaging_filter_types.h       
averaging_filter.a             buildInfo.mat                  
averaging_filter.c             codeInfo.mat                   
averaging_filter.h             codedescriptor.dmr             
averaging_filter.o             compileInfo.mat                
averaging_filter_data.c        defines.txt                    
averaging_filter_data.h        examples                       
averaging_filter_data.o        interface                      
averaging_filter_initialize.c  rtw_proj.tmw                   
averaging_filter_initialize.h  rtwtypes.h                     
averaging_filter_initialize.o  
averaging_filter_rtw.mk        

Проверьте код C для averaging_filter.c Функция

type codegen/lib/averaging_filter/averaging_filter.c
/*
 * File: averaging_filter.c
 *
 * MATLAB Coder version            : 5.2
 * C/C++ source code generated on  : 21-Apr-2021 01:20:09
 */

/* 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];
  double b_y;
  double d;
  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++) {
    /*  Scroll the buffer */
    memcpy(&dv[0], &buffer[0], 15U * sizeof(double));
    /*  Add a new sample value to the buffer */
    buffer[0] = x[i];
    /*  Compute the current average value of the window and */
    /*  write result */
    b_y = buffer[0];
    for (k = 0; k < 15; k++) {
      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]
 */