Следующие шаги показывают, как инициализировать и использовать векторы DWork в S-функции MEX C. Для полного списка макросов SimStruct, имеющих отношение к векторам DWork, см. Вектор DWork C Макросы MEX.
В mdlInitializeSizes задайте количество векторов DWork с помощью макроса ssSetNumDWork. Например, чтобы указать, что S-функция содержит два вектора DWork, используйте команду
ssSetNumDWork(S, 2);
Несмотря на то, что метод mdlInitializeSizes говорит механизм Simulink®, сколько векторов DWork S-функция будет использовать, механизм не выделяет память для векторов DWork в это время.
S-функция может задержать определение количества векторов DWork, пока вся информация о S-входных-параметрах-функции не доступна путем передачи значения DYNAMICALLY_SIZED макросу ssSetNumDWork. Если S-функция задерживает определение количества векторов DWork в mdlInitializeSizes, это должно предоставить метод mdlSetWorkWidths, чтобы настроить векторы DWork.
Если S-функция не предоставляет метод mdlSetWorkWidths, метод mdlInitializeSizes устанавливает любые применимые атрибуты для каждого вектора DWork. Например, следующие строки инициализируют ширины и типы данных векторов DWork, инициализированных на предыдущем шаге.
ssSetDWorkWidth(S, 0, 2); ssSetDWorkWidth(S, 1, 1); ssSetDWorkDataType(S, 0, SS_DOUBLE); ssSetDWorkDataType(S, 1, SS_BOOLEAN);
В следующей таблице перечислены атрибуты, которые вы можете установить для вектора DWork и показываете пример макроса, который устанавливает ее. Смотрите ssSetDWorkRTWStorageClass для списка поддерживаемых классов памяти.
| Атрибут | Макрос |
|---|---|
| Тип данных | |
| Размер | |
| Имя | |
| Тип использования | |
| Числовой тип, или действительный или комплексный | |
| Идентификатор Simulink Coder™ | |
| Класс памяти Simulink Coder | |
| Simulink Coder C вводит спецификатор | |
В mdlStart инициализируйте значения любых векторов DWork, которые должны быть установлены только в начале симуляции. Используйте макрос ssGetDWork, чтобы получить указатель на каждый вектор DWork и инициализировать значения. Например, следующий метод mdlStart инициализирует первый вектор DWork.
static void mdlStart(SimStruct *S)
{
real_T *x = (real_T*) ssGetDWork(S,0);
/* Initialize the first DWork vector */
x[0] = 0;
x[1] = 2;
}
Механизм Simulink выделяет память для вектора DWork прежде, чем вызвать метод mdlStart. Поскольку метод mdlStart называется только однажды в начале симуляции, не используйте его для данных или состояний, которые должны быть повторно инициализированы, например, при перевключении отключенной подсистемы, содержащей S-функцию.
В mdlInitializeConditions инициализируйте значения любых векторов DWork, которые должны быть повторно инициализированы в определенные моменты в симуляции. Механизм выполняет mdlInitializeConditions в начале симуляции и любое время, которое повторно включена активированная подсистема, содержащая S-функцию. Смотрите, что пример mdlStart на предыдущем шаге для команд раньше инициализировал векторные значения DWork.
В mdlOutputs mdlUpdate, и т.д., использует макрос ssGetDWork, чтобы получить указатель на вектор DWork и использовать или обновить векторные значения DWork. Например, для вектора DWork, хранящего два дискретных состояния, следующий mdlOutputs и методы mdlUpdate вычисляют вывод и обновляют значения дискретного состояния.
S-функция ранее задала U(element) как (*uPtrs[element]), A, B, C и D как матрицы пространства состояний для дискретной системы пространства состояний.
/* Function: mdlOutputs ==============================================
* Abstract:
* y = Cx + Du
*/
static void mdlOutputs(SimStruct *S, int_T tid)
{
if( ssGetDWorkUsageType(S, 0) == SS_DWORK_USED_AS_DSTATE) {
real_T *y = ssGetOutputPortRealSignal(S,0);
real_T *x = (real_T*) ssGetDWork(S, 0);
InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S,0);
UNUSED_ARG(tid); /* not used in single tasking mode */
/* y=Cx+Du */
y[0]=C[0][0]*x[0]+C[0][1]*x[1]+D[0][0]*U(0)+D[0][1]*U(1);
y[1]=C[1][0]*x[0]+C[1][1]*x[1]+D[1][0]*U(0)+D[1][1]*U(1);
}
}
#define MDL_UPDATE
/* Function: mdlUpdate ===============================================
* Abstract:
* xdot = Ax + Bu
*/
static void mdlUpdate(SimStruct *S, int_T tid)
{
real_T tempX[2] = {0.0, 0.0};
real_T *x = (real_T*) ssGetDWork(S, 0);
InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S,0);
UNUSED_ARG(tid); /* not used in single tasking mode */
/* xdot=Ax+Bu */
tempX[0]=A[0][0]*x[0]+A[0][1]*x[1]+B[0][0]*U(0)+B[0][1]*U(1);
tempX[1]=A[1][0]*x[0]+A[1][1]*x[1]+B[1][0]*U(0)+B[1][1]*U(1);
x[0]=tempX[0];
x[1]=tempX[1];
}
Вы не должны включать код в метод mdlTerminate, чтобы освободить память, используемую, чтобы сохранить вектор DWork. Точно так же, если вы генерируете встроенный код для S-функции, вы не должны писать метод mdlRTW, чтобы получить доступ к вектору DWork в файле TLC. Программное обеспечение Simulink обрабатывает эти аспекты вектора DWork для вас.
В следующей таблице перечислены макросы MEX C, имеющие отношение к векторам DWork.
| Макрос | Описание |
|---|---|
ssSetNumDWork | Задайте количество векторов DWork. |
ssGetNumDWork | Запросите количество векторов DWork. |
ssGetDWork | Получите указатель на определенный вектор DWork. |
ssGetDWorkComplexSignal | Определите, является ли определенный вектор DWork действительным или комплексным. |
ssGetDWorkDataType | Получите тип данных вектора DWork. |
ssGetDWorkName | Получите имя вектора DWork. |
ssGetDWorkRTWIdentifier | Используйте идентификатор, чтобы объявить вектор DWork в сгенерированном коде. |
ssGetDWorkRTWIdentifierMustResolveToSignalObject | Укажите, должен ли вектор DWork решить к объекту Simulink.Signal в рабочей области MATLAB®. |
ssGetDWorkRTWStorageClass | Получите класс памяти вектора DWork. |
ssGetDWorkRTWTypeQualifier | Доберитесь спецификатор типа C раньше объявлял вектор DWork в сгенерированном коде. |
ssGetDWorkUsageType | Определите, как вектор DWork используется в S-функции. |
ssGetDWorkUsedAsDState | Определите, хранит ли вектор DWork дискретные состояния. |
ssGetDWorkWidth | Получите размер вектора DWork. |
ssSetDWorkComplexSignal | Задайте, являются ли элементы вектора DWork действительными или комплексными. |
ssSetDWorkDataType | Задайте тип данных вектора DWork. |
ssSetDWorkName | Задайте имя вектора DWork. |
ssSetDWorkRTWIdentifier | Укажите, что идентификатор раньше объявлял вектор DWork в сгенерированном коде. |
ssSetDWorkRTWIdentifierMustResolveToSignalObject | Задайте, должен ли вектор DWork решить к объекту Simulink.Signal. |
ssSetDWorkRTWStorageClass | Задайте класс памяти для вектора DWork. |
ssSetDWorkRTWTypeQualifier | Укажите, что спецификатор типа C раньше объявлял вектор DWork в сгенерированном коде. |
ssSetDWorkUsageType | Задайте, как вектор DWork используется в S-функции. |
ssSetDWorkUsedAsDState | Укажите, что вектор DWork хранит значения дискретного состояния. |
ssSetDWorkWidth | Задайте ширину вектора DWork. |
Можно использовать векторы DWork, чтобы связаться с унаследованным кодом. Если у вас есть существующий код, который выделяет структуры данных в памяти, сохраните указатель на те структуры данных в векторе DWork. Ваша S-функция может затем связаться с унаследованным кодом через указатель. Также для простоты в подготовке вашей S-функции, можно использовать указатель, работают вектор, чтобы сохранить указатель. Смотрите, что Элементарные Векторы работы для описания указателя работают векторы.
Можно также использовать векторы DWork, чтобы сохранить состояние унаследованного кода. sfuntmpl_gate_fortran.c файла шаблона показывает, как использовать векторы DWork, чтобы взаимодействовать с устаревшим кодом Фортран. Legacy Code Tool использует векторы DWork, чтобы поддержать состояния наследия C или Кода С++, включенного через инструмент. Смотрите Интегрируют Функции C Используя Legacy Code Tool для получения дополнительной информации о Legacy Code Tool.