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

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

В дополнение к векторам 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. Кроме того, вам разрешают только один вектор Режима.
ssSetNumDWork(S,1);
ssSetDWorkUsageType(S, 0, 
   sSS_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 в S-функциях MEX C.) Элементарные векторы работы имеют меньше свойств, таким образом, процесс инициализации более прост. Однако, если необходимо сгенерировать код для 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-функции смотрите Разрывы в качестве примера в Непрерывных состояниях.

Вектор режима

Следующие реализации в качестве примера блок switch с помощью режима работают вектор. Метод 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]);
    }
}