exponenta event banner

Элементарные рабочие векторы

Описание элементарного вектора работы

Помимо векторов DWork, программное обеспечение Simulink ® предоставляет упрощенный набор векторов работы. В некоторых S-функциях эти элементарные рабочие векторы могут обеспечить более простое решение, чем использование векторов DWork:

  • Векторы IWork хранят целочисленные данные.

  • Векторы режимов моделируют пересечения нулей или другие элементы, для которых требуется одномодовый вектор.

  • Векторы PWork хранят указатели на структуры данных, такие как те, которые связывают S-функцию с унаследованным кодом, другим программным приложением или аппаратным приложением.

  • Векторы RWork хранят данные с плавающей запятой (вещественные).

Связь с векторами DWork

В следующей таблице сравнивается каждый тип рабочего вектора с вектором 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);
Затем вектор DWork сохраняет указатель.
RWorkВекторы RWork не могут быть настроены в сгенерированном коде. Кроме того, разрешен только один вектор RWork.
ssSetNumDWork(S,1);
ssSetDWorkDataType(S, 0, SS_DOUBLE);

Использование элементарных рабочих векторов

Процесс использования элементарных рабочих векторов аналогичен процессу использования векторов DWork (см. Использование векторов DWork в C MEX S-Functions). Элементарные рабочие векторы имеют меньше свойств, поэтому процесс инициализации проще. Однако при необходимости генерации кода для S-функции S-функция становится более задействованной, чем при использовании векторов DWork.

Следующие шаги показывают, как настроить и использовать элементарные рабочие векторы. Список макросов, связанных с каждым шагом в следующем процессе, см. в разделе Дополнительные макросы рабочего вектора.

  1. В mdlInitializeSizes, укажите размер рабочих векторов с помощью ssSetNumXWork макро, например:

    ssSetNumPWork(S, 2);

    Этот макрос указывает, сколько элементов содержит рабочий вектор, однако в данный момент модуль Simulink не выделяет память.

    S-функция может отложить определение длины рабочих векторов до тех пор, пока не будет доступна вся информация о входах S-функции путем передачи значения. DYNAMICALLY_SIZED в ssSetNumXWork макро. Если S-функция откладывает задание длины рабочих векторов в mdlInitializeSizes, он должен обеспечить mdlSetWorkWidths способ настройки рабочих векторов.

    Примечание

    Если S-функция использует mdlSetWorkWidths, все рабочие векторы, используемые в S-функции, должны быть установлены в DYNAMICALLY_SIZED в mdlInitializeSizes, даже если точное значение известно до mdlInitializeSizes вызывается. Размеры, используемые S-функцией, превышают указанные в mdlSetWorkWidths.

    Пример см. в разделе sfun_dynsize.c.

  2. В mdlStartприсвойте значения рабочим векторам, которые инициализируются только в начале моделирования. Используйте ssGetXWork для извлечения указателя на каждый рабочий вектор и использования указателя для инициализации значений рабочего вектора. В качестве альтернативы используйте ssGetXWorkValues для назначения значений определенным элементам рабочего вектора.

    Движок Simulink вызывает mdlStart один раз в начале моделирования. Перед вызовом этого метода подсистема выделяет память для рабочих векторов. Не используйте mdlStart метод для данных, которые должны быть повторно инициализированы в ходе моделирования, например, данные, которые должны быть повторно инициализированы, когда активирована подсистема, содержащая S-функцию.

  3. В mdlInitializeConditionsинициализируйте значения всех рабочих векторов, которые могут потребоваться для повторной инициализации в определенных точках моделирования. Модуль выполняет mdlInitializeConditions в начале моделирования и в любое время снова включается включенная подсистема, содержащая S-функцию.

  4. В mdlOutputs, mdlUpdateи т.д., используйте ssGetXWork для извлечения указателя на рабочий вектор и использования указателя для доступа или обновления значений рабочего вектора.

  5. Написать 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]);
    }
}