Это пример 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:
If this post helped you, please consider buying me a coffee or donating via PayPal to support research & publishing of new posts on TechOverflow