В дополнение к векторам DWork, Simulink® программное обеспечение обеспечивает упрощенный набор рабочих векторов. В некоторых S-функциях эти элементарные векторы работы могут предоставить более простое решение, чем использование векторов DWork:
Векторы IWork хранят целочисленные данные.
Векторы Mode моделируют пересечения нуля или другие функции, которые требуют вектора в одной моде.
Векторы PWork хранят указатели на структуры данных, такие как те, которые соединяют S-функцию с унаследованным кодом, другим программным обеспечением или оборудованием приложением.
Векторы RWork хранят данные с плавающей точкой (real).
В следующей таблице сравнивается каждый тип рабочего вектора с вектором DWork.
Тип рабочего вектора | Сравнение с вектором DWork | Как создать эквивалентный вектор DWork |
---|---|---|
IWork | Векторы IWork не могут быть настроены в сгенерированном коде. Кроме того, вам разрешен только один вектор IWork. | ssSetNumDWork(S,1); ssSetDWorkDataType(S, 0, SS_INT8); |
Способ | Векторы Mode требуют большей памяти, чем векторы DWork, поскольку вектор mode всегда сохранен со integer тип данных. Кроме того, вам разрешен только один вектор Mode. | ssSetNumDWork(S,1); ssSetDWorkUsageType(S, 0, SS_DWORK_USED_AS_MODE); ssSetDWorkDataType(S, 0, SS_INT8); |
PWork | В отличие от векторов DWork, векторы PWork не могут быть названы в сгенерированном коде. Кроме того, вам разрешен только один вектор PWork. | ssSetNumDWork(S,1); ssSetDWorkDataType(S, 0, SS_POINTER); |
RWork | Векторы RWork не могут быть настроены в сгенерированном коде. Кроме того, вам разрешен только один вектор RWork. | ssSetNumDWork(S,1); ssSetDWorkDataType(S, 0, SS_DOUBLE); |
Процесс использования элементарных векторов работы аналогичен процессу для векторов DWork (см. Использование векторов DWork в C MEX S-Functions.) Элементарные векторы работы имеют меньше свойств, поэтому процесс инициализации проще. Однако, если вам нужно сгенерировать код для S-функции, S-функция становится более вовлеченной, чем при использовании векторов DWork.
Следующие шаги показывают, как настроить и использовать элементарные векторы работы. Список макросов Работ связанных с каждым шагом в следующем процессе см. в разделе Дополнительные векторные макросы.
В mdlInitializeSizes
, задайте размер рабочих векторов, используя ssSetNum
макрос, например:X
Работа
ssSetNumPWork(S, 2);
Этот макрос указывает, сколько элементов содержит рабочий вектор, однако механизм Simulink не выделяет память, в настоящее время.
S-функция может отложить определение длины рабочих векторов, пока вся информация о входах S-функции не будет доступна путем передачи значения DYNAMICALLY_SIZED
в
макрос. Если S-функция задерживает определение длины рабочих векторов в X
ssSetNumРабота
mdlInitializeSizes
, это должно обеспечить mdlSetWorkWidths
метод для настройки рабочих векторов.
Примечание
Если S-функция использует mdlSetWorkWidths
все рабочие векторы, используемые в S-функции, должны быть установлены в DYNAMICALLY_SIZED
в mdlInitializeSizes
, даже если точное значение известно ранее mdlInitializeSizes
вызывается. Размеры, используемые S-функцией, превышают указанные в mdlSetWorkWidths
.
Для получения примера см. sfun_dynsize.c
.
В mdlStart
, присвойте значения рабочим векторам, которые инициализируются только в начале симуляции. Используйте команду ssGet
макрос для извлечения указателя на каждый рабочий вектор и использования указателя для инициализации значений рабочих векторов. Также используйте команду X
РаботаssGet
для назначения значений конкретным элементам рабочего вектора.X
WorkValues
Механизм Simulink вызывает mdlStart
метод один раз в начале симуляции. Перед вызовом этого метода механизм выделяет память для рабочих векторов. Не используйте mdlStart
метод для данных, которые необходимо повторно инициализировать в ходе симуляции, например, данные, которые необходимо повторно инициализировать, когда включена включенная подсистема, содержащая S-функцию.
В mdlInitializeConditions
, инициализируйте значения любых рабочих векторов, которые могут потребоваться для повторной инициализации в определенных точках симуляции. Механизм выполняет mdlInitializeConditions
в начале симуляции и в любое время активируется включенная подсистема, содержащая S-функцию.
В mdlOutputs
, mdlUpdate
, и т.д., используйте
макрос для извлечения указателя на рабочий вектор и использования указателя для доступа или обновления значений рабочих векторов.X ssGet
Работа
Написание mdlRTW
метод, позволяющий Target Language Compiler (TLC) получить доступ к рабочему вектору. Этот шаг не является необходимым, если S-функция использует векторы DWork. Для получения информации о записи данных параметра в mdlRTW
метод, см. ssWriteRTWParamSettings
. Для получения дополнительной информации о генерации кода с помощью mdlRTW
метод, см. Запись полностью встроенных S-функций с стандартной программой mdlRTW (Simulink Coder).
Макрос | Описание |
---|---|
ssSetNumRWork | Задайте ширину действительного рабочего вектора. |
ssGetNumRWork | Запросите ширину действительного рабочего вектора. |
ssSetNumIWork | Задайте ширину целочисленного рабочего вектора. |
ssGetNumIWork | Запросите ширину целочисленного рабочего вектора. |
ssSetNumPWork | Задайте ширину рабочего вектора указателя. |
ssGetNumPWork | Запросите ширину рабочего вектора указателя. |
ssSetNumModes | Задайте ширину рабочего вектора режима. |
ssGetNumModes | Запросите ширину рабочего вектора режима. |
ssGetIWork | Получите указатель на целочисленный рабочий вектор. |
ssGetIWorkValue | Получите элемент целочисленного рабочего вектора. |
ssGetModeVector | Получите указатель на рабочий вектор режима. |
ssGetModeVectorValue | Получите элемент рабочего вектора режима. |
ssGetPWork | Получите указатель на рабочий вектор указателя. |
ssGetPworkValue | Получите один элемент из рабочего вектора указателя. |
ssGetRWork | Получите указатель на рабочий вектор с плавающей точкой. |
ssGetRWorkValue | Получите элемент рабочего вектора с плавающей точкой. |
ssSetIWorkValue | Установите значение одного элемента целочисленного рабочего вектора. |
ssSetModeVectorValue | Установите значение одного элемента рабочего вектора режима. |
ssSetPWorkValue | Установите значение одного элемента рабочего вектора указателя. |
ssSetRWorkValue | Установите значение одного элемента рабочего вектора с плавающей точкой. |
В следующих разделах приведены примеры четырех типов элементарных векторов работы.
Этот пример открывает файл и хранит FILE
указатель в рабочем векторе указателя.
Следующий оператор, включенный в mdlInitializeSizes
function, указывает, что рабочий вектор указателя должен содержать один элемент.
ssSetNumPWork(S, 1) /* pointer-work vector */
Следующий код использует рабочий вектор указателя для хранения FILE
указатель, возвращенный от стандартной функции ввода-вывода fopen
.
#define MDL_START /* Change to #undef to remove function. */ #if defined(MDL_START) static void mdlStart(real_T *x0, SimStruct *S) { FILE *fPtr; void **PWork = ssGetPWork(S); fPtr = fopen("file.data", "r"); PWork[0] = fPtr; } #endif /* MDL_START */
Следующий код извлекает FILE
указатель на рабочий вектор указателя и передает его в fclose
в порядок для закрытия файла.
static void mdlTerminate(SimStruct *S) { if (ssGetPWork(S) != NULL) { FILE *fPtr; fPtr = (FILE *) ssGetPWorkValue(S,0); if (fPtr != NULL) { fclose(fPtr); } ssSetPWorkValue(S,0,NULL); } }
Примечание
Несмотря на то, что механизм Simulink обрабатывает отключение вектора PWork, mdlTerminate
метод всегда должен освобождать память, сохраненную в векторе PWork.
S-функция stvctf.c
использует векторы RWork и IWork, чтобы смоделировать изменяющуюся во времени непрерывную передаточную функцию. Описание этой S-функции см. в примере Прерывания в Непрерывных состояниях.
В следующем примере реализуется блок switch с использованием рабочего вектора mode. The mdlInitializeSizes
метод конфигурирует два входных порта с прямым сквозным соединением и один выходной порт. Элемент вектора режима указывает, передается ли сигнал от первого или второго входного порта на выход. S-функция использует один параметр S-функции и соответствующий параметр времени выполнения, чтобы сохранить значение режима и позволить переключению коммутатора во время симуляции.
static void mdlInitializeSizes(SimStruct *S) { /* Initialize one S-function parameter to toggle the mode value */ ssSetNumSFcnParams(S, 1); if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) { /* Return if number of expected != number of actual parameters */ return; } { int iParam = 0; int nParam = ssGetNumSFcnParams(S); for ( iParam = 0; iParam < nParam; iParam++ ) { ssSetSFcnParamTunable( S, iParam, SS_PRM_TUNABLE ); } } /* Initialize two input ports with direct feedthrough */ if (!ssSetNumInputPorts(S, 2)) return; ssSetInputPortWidth(S, 0, 1); ssSetInputPortWidth(S, 1, 1); ssSetInputPortDataType( S, 0, SS_DOUBLE); ssSetInputPortDataType( S, 1, SS_DOUBLE); ssSetInputPortDirectFeedThrough( S, 0, 1); ssSetInputPortDirectFeedThrough( S, 1, 1); /* Initialize one output port */ if (!ssSetNumOutputPorts(S, 1)) return; ssSetOutputPortWidth(S, 0, 1); ssSetOutputPortDataType( S, 0, SS_DOUBLE); /* Initialize one element in the mode vector */ ssSetNumSampleTimes(S, 1); ssSetNumModes(S,1); ssSetOptions(S, SS_OPTION_WORKS_WITH_CODE_REUSE | SS_OPTION_USE_TLC_WITH_ACCELERATOR | SS_OPTION_DISALLOW_CONSTANT_SAMPLE_TIME | SS_OPTION_NONVOLATILE); }
The mdlInitializeConditions
метод инициализирует значение вектора mode с помощью текущего значения параметра диалога S-функции.
#define MDL_INITIALIZE_CONDITIONS /* Function: mdlInitializeConditions ============================= * Abstract: * Initialize the mode vector value. */ static void mdlInitializeConditions(SimStruct *S) { int_T *mv = ssGetModeVector(S); real_T param = mxGetScalar(ssGetSFcnParam(S,0)); mv[0] = (int_T)param; }
The mdlProcessParameters
и mdlSetWorkWidths
методы инициализируют и обновляют параметр времени выполнения. Когда симуляция запускается, изменения в параметре диалога S-функции сопоставляются с параметром времени выполнения.
/* Function: mdlSetWorkWidths ============================================= * Abstract: * Sets the number of runtime parameters. */ #define MDL_SET_WORK_WIDTHS static void mdlSetWorkWidths(SimStruct *S) { ssSetNumRunTimeParams(S,1); ssRegDlgParamAsRunTimeParam(S,0,0,"P1",SS_INT16); } /* Function: mdlProcessParameters =========================================== * Abstract: * Update run-time parameters. */ #define MDL_PROCESS_PARAMETERS static void mdlProcessParameters(SimStruct *S) { ssUpdateDlgParamAsRunTimeParam(S,0); }
The mdlOutputs
метод обновляет значение вектора режима новым значением параметров во время выполнения на каждом главном временном шаге. Затем он использует значение вектора режима, чтобы определить, какой входной сигнал должен пройти к выходу.
static void mdlOutputs(SimStruct *S, int_T tid) { InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S,0); InputRealPtrsType u2Ptrs = ssGetInputPortRealSignalPtrs(S,1); real_T *y = ssGetOutputPortSignal(S,0); int_T *mode = ssGetModeVector(S); real_T param = mxGetScalar(ssGetSFcnParam(S,0)); if (ssIsMajorTimeStep(S)) { mode[0] = (int_T)param; } if (!mode[0]) { /* first input */ y[0] = (*uPtrs[0]); } if (mode[0]) { /* second input */ y[0] = (*u2Ptrs[0]); } }