Помимо векторов DWork, программное обеспечение Simulink ® предоставляет упрощенный набор векторов работы. В некоторых S-функциях эти элементарные рабочие векторы могут обеспечить более простое решение, чем использование векторов DWork:
Векторы IWork хранят целочисленные данные.
Векторы режимов моделируют пересечения нулей или другие элементы, для которых требуется одномодовый вектор.
Векторы PWork хранят указатели на структуры данных, такие как те, которые связывают S-функцию с унаследованным кодом, другим программным приложением или аппаратным приложением.
Векторы RWork хранят данные с плавающей запятой (вещественные).
В следующей таблице сравнивается каждый тип рабочего вектора с вектором DWork.
| Тип рабочего вектора | Сравнение с вектором DWork | Создание эквивалентного вектора DWork |
|---|---|---|
| IWork | Векторы IWork не могут быть настроены в сгенерированном коде. Кроме того, разрешен только один вектор IWork. | ssSetNumDWork(S,1); ssSetDWorkDataType(S, 0, SS_INT8); |
| Способ | Векторы режима требуют больше памяти, чем векторы DWork, поскольку вектор режима всегда сохраняется с помощью 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 макро, например:XWork
ssSetNumPWork(S, 2);
Этот макрос указывает, сколько элементов содержит рабочий вектор, однако в данный момент модуль Simulink не выделяет память.
S-функция может отложить определение длины рабочих векторов до тех пор, пока не будет доступна вся информация о входах S-функции путем передачи значения. DYNAMICALLY_SIZED в ssSetNum макро. Если S-функция откладывает задание длины рабочих векторов в XWorkmdlInitializeSizes, он должен обеспечить mdlSetWorkWidths способ настройки рабочих векторов.
Примечание
Если S-функция использует mdlSetWorkWidths, все рабочие векторы, используемые в S-функции, должны быть установлены в DYNAMICALLY_SIZED в mdlInitializeSizes, даже если точное значение известно до mdlInitializeSizes вызывается. Размеры, используемые S-функцией, превышают указанные в mdlSetWorkWidths.
Пример см. в разделе sfun_dynsize.c.
В mdlStartприсвойте значения рабочим векторам, которые инициализируются только в начале моделирования. Используйте ssGet для извлечения указателя на каждый рабочий вектор и использования указателя для инициализации значений рабочего вектора. В качестве альтернативы используйте XWorkssGet для назначения значений определенным элементам рабочего вектора.XWorkValues
Движок Simulink вызывает mdlStart один раз в начале моделирования. Перед вызовом этого метода подсистема выделяет память для рабочих векторов. Не используйте mdlStart метод для данных, которые должны быть повторно инициализированы в ходе моделирования, например, данные, которые должны быть повторно инициализированы, когда активирована подсистема, содержащая S-функцию.
В mdlInitializeConditionsинициализируйте значения всех рабочих векторов, которые могут потребоваться для повторной инициализации в определенных точках моделирования. Модуль выполняет mdlInitializeConditions в начале моделирования и в любое время снова включается включенная подсистема, содержащая S-функцию.
В mdlOutputs, mdlUpdateи т.д., используйте ssGet для извлечения указателя на рабочий вектор и использования указателя для доступа или обновления значений рабочего вектора.XWork
Написать mdlRTW метод, позволяющий компилятору целевого языка (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 функция указывает, что рабочий вектор указателя должен содержать один элемент.
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-функции см. в примере Прерываний в непрерывных состояниях.
В следующем примере блок переключения реализуется с использованием рабочего вектора режима. 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);
} mdlInitializeConditions метод инициализирует значение вектора режима, используя текущее значение параметра диалогового окна 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;
}
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);
}
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]);
}
}