Базовые векторы работы

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

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

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

  • Векторы Mode моделируют пересечения нуля или другие функции, которые требуют вектора в одной моде.

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

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

Отношение к векторам DWork

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

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

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

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

  1. В mdlInitializeSizes, задайте размер рабочих векторов, используя ssSetNum XРабота макрос, например:

    ssSetNumPWork(S, 2);

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

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

    Примечание

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

    Для получения примера см. sfun_dynsize.c.

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

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

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

  4. В mdlOutputs, mdlUpdate, и т.д., используйте X ssGetРабота макрос для извлечения указателя на рабочий вектор и использования указателя для доступа или обновления значений рабочих векторов.

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