Пример Matlab S-функции: чтение double-входа и запись в файл

Это пример Matlab Level-2 S-функции, которая считывает один непрерывный вход типа double и записывает его в файл out.txt в формате CSV time,value. Файл открывается в функции mdlStart и закрывается в функции mdlTerminate. Входное значение считывается в функции mdlUpdate.

Также см. Пример Matlab Level 2 S-Function: Синусоида (непрерывный вывод).

single_input_write_to_file.cpp
#define S_FUNCTION_NAME  single_input_write_to_file
#define S_FUNCTION_LEVEL 2

#include "simstruc.h"
#include <cstdio>  // Для работы с файлами

// Определить константы
#define SAMPLING_RATE 1000 // 1kHz

static void mdlInitializeSizes(SimStruct *S)
{
    ssSetNumSFcnParams(S, 0);  // Нет параметров
    ssSetNumContStates(S, 0);  // Нет непрерывных состояний
    ssSetNumDiscStates(S, 0);  // Нет дискретных состояний
    // 1 входной порт с 1 элементом
    if (!ssSetNumInputPorts(S, 1)) return;
    ssSetInputPortWidth(S, 0, 1);  // Ширина входного порта = 1
    ssSetInputPortDataType(S, 0, SS_DOUBLE);
    ssSetInputPortComplexSignal(S, 0, COMPLEX_NO);

    ssSetInputPortRequiredContiguous(S, 0, 1);  // Требовать непрерывную память входного порта
    // ssSetInputPortDirectFeedThrough(S, 0, 1);  // Прямой проход

    // Нет выходных портов
    if (!ssSetNumOutputPorts(S, 0)) return;
    // Времена выборки
    ssSetNumSampleTimes(S, 1);  // Одно время выборки

    // Рабочие векторы
    ssSetNumRWork(S, 0);  // Вектор вещественной работы
    ssSetNumIWork(S, 0);  // Вектор целочисленной работы
    ssSetNumPWork(S, 1);  // Вектор работы с указателем для указателя на файл
    ssSetNumModes(S, 0);  // Вектор режимов
    ssSetNumNonsampledZCs(S, 0);  // Нулевые переходы

    // Сделать блок S-function пригодным для использования в модели, сгенерированной Real-Time Workshop
    ssSetOptions(S, 0);
}

#define MDL_START
static void mdlStart(SimStruct *S) {
    // Открыть файл "out.txt" для записи
    FILE *file = fopen("out.txt", "w");
    if (file == NULL) {
        ssSetErrorStatus(S, "Failed to open file 'out.txt'");
        return;
    }

    const real_T *u = (const real_T*) ssGetInputPortSignal(S, 0);  // Указатель на вход
    real_T input_value = u == nullptr ? -1 : u[0];  // Считать входное значение

    ssSetPWorkValue(S, 0, file);
}

// Function: mdlInitializeSampleTimes =========================================
// Abstract:
//    Инициализировать времена выборки на 1мс (1кГц)
static void mdlInitializeSampleTimes(SimStruct *S)
{
    ssSetSampleTime(S, 0, 1.0 / SAMPLING_RATE);  // Частота выборки 1кГц
    ssSetOffsetTime(S, 0, 0.0);
}

// Не требуется для этого примера
static void mdlOutputs(SimStruct *S, int_T tid) {
    // Ничего не делать
}

#define MDL_UPDATE
static void mdlUpdate(SimStruct *S, int_T tid)
{
    real_T time = ssGetT(S);  // Получить текущее время симуляции

    // Получить входное значение
    const real_T *u = (const real_T*) ssGetInputPortRealSignal(S, 0);  // Указатель на вход
    real_T input_value = u == nullptr ? -1 : u[0];  // Считать входное значение

    // Получить указатель на файл из рабочего вектора
    FILE *file = (FILE*) ssGetPWorkValue(S, 0);
    if (file != NULL) {
        fprintf(file, "%f,%f\n", time, input_value);  // Записать входное значение в файл
    }
}

static void mdlTerminate(SimStruct *S)
{
    // Закрыть файл
    FILE *file = (FILE*) ssGetPWorkValue(S, 0);
    if (file != NULL) {
        fclose(file);
    }
}

// Требуемый трейлер S-function
#ifdef MATLAB_MEX_FILE
#include "simulink.c"   // Механизм интерфейса MEX-file
#else
#include "cg_sfun.h"    // Интерфейс генерации кода
#endif

Check out similar posts by category: