Когда вы итеративно разрабатываете модель, вы получаете выходной сигнал и утверждаете данные, которые генерирует образцовое выполнение. Вы также значения настройки параметров во время выполнения, чтобы наблюдать результаты относительно выходных параметров. Можно затем основывать проектные решения на анализе этих выходных параметров. Чтобы получить доступ к этому сигналу, состоянию и данным о параметре в среде быстрого прототипирования, можно сконфигурировать сгенерированный код, чтобы хранить данные в адресуемой памяти.
По умолчанию настройки оптимизации делают сгенерированный код более эффективным путем устранения ненужного устройства хранения данных сигнала и встраивания числовых значений параметров блоков. Чтобы сгенерировать код, который вместо этого выделяет адресуемую память для этих данных, можно отключить оптимизацию или задать настройки генерации кода для отдельных элементов данных.
Запустите скрипт, который готовит модель rtwdemo_basicsc
к этому примеру.
run(fullfile(matlabroot,'examples','simulinkcoder','main','prepare_rtwdemo_basicsc'));
Откройте модель в качестве примера, rtwdemo_basicsc
.
rtwdemo_basicsc
Модель загружает числовые переменные MATLAB в базовое рабочее пространство. Переменные рабочей области устанавливают некоторые параметры блоков в модели. Однако блок Gain в модели использует литеральное значение 2
.
В модели очистите образцовое Повторное использование памяти параметра конфигурации. Когда вы очищаете эту оптимизацию и другую оптимизацию ту, которая Устраняет лишние локальные переменные (сворачивание выражения), сгенерированный код выделяет память для сигнальных линий. Очистка Повторного использования памяти отключает большую часть другой оптимизации.
set_param('rtwdemo_basicsc','OptimizeBlockIOStorage','off')
Установите Параметры конфигурации оптимизации> Оптимизация> поведение параметра По умолчанию к Tunable
. Когда установлено в Tunable
, этот параметр конфигурации заставляет сгенерированный код выделять память для переменных рабочей области и параметров блоков.
set_param('rtwdemo_basicsc','DefaultParameterBehavior','Tunable')
Сгенерируйте код из модели.
rtwbuild('rtwdemo_basicsc')
### Starting build procedure for model: rtwdemo_basicsc ### Successful completion of build procedure for model: rtwdemo_basicsc
В отчете генерации кода просмотрите файл rtwdemo_basicsc.h
. Этот заголовочный файл задает тип структуры, который содержит данные сигнала. Структура содержит поля, что каждый представляет сигнальную линию в модели. Например, выходной сигнал блока Gain, именем которого является Gain
, появляется как поле Gain
.
file = fullfile('rtwdemo_basicsc_grt_rtw','rtwdemo_basicsc.h'); rtwdemodbtype(file,'/* Block signals (default storage) */',... 'B_rtwdemo_basicsc_T;',1,1)
/* Block signals (default storage) */ typedef struct { real32_T Table1; /* '<Root>/Table1' */ real32_T Gain; /* '<Root>/Gain' */ real32_T Delay; /* '<Root>/Delay' */ real32_T Table2; /* '<Root>/Table2' */ boolean_T RelOp1; /* '<Root>/RelOp1' */ boolean_T RelOp2; /* '<Root>/RelOp2' */ boolean_T LogOp; /* '<Root>/LogOp' */ } B_rtwdemo_basicsc_T;
Файл задает тип структуры, который содержит данные о параметрах блоков. Например, параметр Усиления блока Gain появляется как поле Gain_Gain
. Другие поля структуры представляют другие параметры блоков и переменные рабочей области из модели, включая начальные условия для сигналов и состояний.
rtwdemodbtype(file,'/* Parameters (default storage) */',... '/* Real-time Model Data Structure */',1,0)
/* Parameters (default storage) */ struct P_rtwdemo_basicsc_T_ { real_T K2; /* Variable: K2 * Referenced by: '<Root>/Stateflow Chart' */ real32_T LOWER; /* Variable: LOWER * Referenced by: '<Root>/Constant2' */ real32_T T1Break[11]; /* Variable: T1Break * Referenced by: '<Root>/Table1' */ real32_T T1Data[11]; /* Variable: T1Data * Referenced by: '<Root>/Table1' */ real32_T T2Break[3]; /* Variable: T2Break * Referenced by: '<Root>/Table2' */ real32_T T2Data[9]; /* Variable: T2Data * Referenced by: '<Root>/Table2' */ real32_T UPPER; /* Variable: UPPER * Referenced by: '<Root>/Constant1' */ real32_T Gain_Gain; /* Computed Parameter: Gain_Gain * Referenced by: '<Root>/Gain' */ real32_T Delay_InitialCondition; /* Computed Parameter: Delay_InitialCondition * Referenced by: '<Root>/Delay' */ uint32_T Table2_maxIndex[2]; /* Computed Parameter: Table2_maxIndex * Referenced by: '<Root>/Table2' */ boolean_T DataStoreMemory_InitialValue; /* Computed Parameter: DataStoreMemory_InitialValue * Referenced by: '<Root>/Data Store Memory' */ };
Просмотрите файл rtwdemo_basicsc_data.c
. Этот исходный файл выделяет глобальную память для структуры параметра и инициализирует значения полей на основе значений параметров в модели.
Просмотрите исходный файл rtwdemo_basicsc.c
. Код выделяет глобальную память для переменной структуры, которая содержит данные сигнала.
file = fullfile('rtwdemo_basicsc_grt_rtw','rtwdemo_basicsc.c'); rtwdemodbtype(file,'/* Block signals (default storage) */',... 'B_rtwdemo_basicsc_T rtwdemo_basicsc_B;',1,1)
/* Block signals (default storage) */ B_rtwdemo_basicsc_T rtwdemo_basicsc_B;
Алгоритм кода в функции модели step
вычисляет значения сигналов. Это затем присваивает эти значения полям структуры сигнала. Чтобы выполнить вычисления, алгоритм использует значения параметров от полей структуры параметра.
Когда это необходимо, чтобы выбрать оптимизацию генерации кода, такую как Повторное использование памяти, можно сохранить отдельные элементы данных от оптимизации. Сгенерированный код затем выделяет адресуемую память для элементов.
Выберите оптимизацию, которую вы ранее очистили.
set_param('rtwdemo_basicsc','OptimizeBlockIOStorage','on') set_param('rtwdemo_basicsc','LocalBlockOutputs','on') set_param('rtwdemo_basicsc','DefaultParameterBehavior','Inlined')
В модели выберите View> Model Data Editor.
В Model Data Editor осмотрите вкладку Signals.
Установите представление Change выпадающий список на Instrumentation
.
В модели выберите выходной сигнал блока Gain.
В Model Data Editor установите флажок в столбце Тестовой точки.
portHandle = get_param('rtwdemo_basicsc/Gain','PortHandles'); portHandle = portHandle.Outport; set_param(portHandle,'TestPoint','on')
Осмотрите вкладку Parameters.
В модели выберите блок Gain.
В Model Data Editor используйте Столбец значений, чтобы установить значение усиления к K1
.
Рядом с K1
кликните по кнопке действий (с тремя вертикальными точками) и выберите Create.
В диалоговом окне Create New Data, установленном Значении к Simulink.Parameter(2)
и нажимают Create. Объект Simulink.Parameter
под названием K1
, со значением 2
, появляется в базовом рабочем пространстве.
В диалоговом окне свойства для K1
примените класс памяти кроме Auto
при помощи Класса памяти. Например, используйте класс памяти Model default
, чтобы представлять объект параметра как поле глобальной структуры параметров.
set_param('rtwdemo_basicsc/Gain','Gain','K1'); K1 = Simulink.Parameter(2); K1.StorageClass = 'Model default';
Сгенерируйте код из модели.
rtwbuild('rtwdemo_basicsc')
### Starting build procedure for model: rtwdemo_basicsc ### Successful completion of build procedure for model: rtwdemo_basicsc
В отчете генерации кода просмотрите файл rtwdemo_basicsc.h
. Структура, которая содержит данные сигнала теперь, задает только одно поле, Gain
, который представляет вывод с концом теста блока Gain.
file = fullfile('rtwdemo_basicsc_grt_rtw','rtwdemo_basicsc.h'); rtwdemodbtype(file,'/* Block signals (default storage) */',... 'B_rtwdemo_basicsc_T;',1,1)
/* Block signals (default storage) */ typedef struct { real32_T Gain; /* '<Root>/Gain' */ } B_rtwdemo_basicsc_T;
Структура, которая содержит данные о параметрах блоков, задает одно поле, K1
, который представляет объект параметра K1
.
rtwdemodbtype(file,'/* Parameters (default storage) */',... '/* Real-time Model Data Structure */',1,0)
/* Parameters (default storage) */ struct P_rtwdemo_basicsc_T_ { real32_T K1; /* Variable: K1 * Referenced by: '<Root>/Gain' */ };
Можно сконфигурировать сгенерированный код, чтобы содержать дополнительный код и файлы так, чтобы можно было получить доступ к данным модели через стандартизированные интерфейсы. Например, используйте API C, чтобы регистрировать данные сигнала и настройки параметров во время выполнения.
Скопируйте этот пользовательский исходный код в файл с именем ex_myHandCode.c
в вашей текущей папке.
#include "ex_myHandHdr.h" #define paramIdx 0 /* Index of the target parameter, determined by inspecting the array of structures generated by the C API. */ #define sigIdx 0 /* Index of the target signal, determined by inspecting the array of structures generated by the C API. */ void tuneFcn(rtwCAPI_ModelMappingInfo *mmi, time_T *tPtr) { /* Take action with the parameter value only at the beginning of simulation and at the 5-second mark. */ if (*tPtr == 0 || *tPtr == 5) { /* Local variables to store information extracted from the model mapping information (mmi). */ void** dataAddrMap; const rtwCAPI_DataTypeMap *dataTypeMap; const rtwCAPI_ModelParameters *params; int_T addrIdx; uint16_T dTypeIdx; uint8_T slDataType; /* Use built-in C API macros to extract information. */ dataAddrMap = rtwCAPI_GetDataAddressMap(mmi); dataTypeMap = rtwCAPI_GetDataTypeMap(mmi); params = rtwCAPI_GetModelParameters(mmi); addrIdx = rtwCAPI_GetModelParameterAddrIdx(params,paramIdx); dTypeIdx = rtwCAPI_GetModelParameterDataTypeIdx(params,paramIdx); slDataType = rtwCAPI_GetDataTypeSLId(dataTypeMap, dTypeIdx); /* Handle data types 'double' and 'int8'. */ switch (slDataType) { case SS_DOUBLE: { real_T* dataAddress; dataAddress = dataAddrMap[addrIdx]; /* At the 5-second mark, increment the parameter value by 1. */ if (*tPtr == 5) { (*dataAddress)++; } printf("Parameter value is %f\n", *dataAddress); break; } case SS_INT8: { int8_T* dataAddress; dataAddress = dataAddrMap[addrIdx]; if (*tPtr == 5) { (*dataAddress)++; } printf("Parameter value is %i\n", *dataAddress); break; } } } } void logFcn(rtwCAPI_ModelMappingInfo *mmi, time_T *tPtr) { /* Take action with the signal value only when the simulation time is an integer value. */ if (*tPtr-(int_T)*tPtr == 0) { /* Local variables to store information extracted from the model mapping information (mmi). */ void** dataAddrMap; const rtwCAPI_DataTypeMap *dataTypeMap; const rtwCAPI_Signals *sigs; int_T addrIdx; uint16_T dTypeIdx; uint8_T slDataType; /* Use built-in C API macros to extract information. */ dataAddrMap = rtwCAPI_GetDataAddressMap(mmi); dataTypeMap = rtwCAPI_GetDataTypeMap(mmi); sigs = rtwCAPI_GetSignals(mmi); addrIdx = rtwCAPI_GetSignalAddrIdx(sigs,sigIdx); dTypeIdx = rtwCAPI_GetSignalDataTypeIdx(sigs,sigIdx); slDataType = rtwCAPI_GetDataTypeSLId(dataTypeMap, dTypeIdx); /* Handle data types 'double' and 'single'. */ switch (slDataType) { case SS_DOUBLE: { real_T* dataAddress; dataAddress = dataAddrMap[addrIdx]; printf("Signal value is %f\n", *dataAddress); break; } case SS_SINGLE: { real32_T* dataAddress; dataAddress = dataAddrMap[addrIdx]; printf("Signal value is %f\n", *dataAddress); break; } } } }
Скопируйте этот пользовательский код заголовка в файл с именем ex_myHandHdr.h
в вашей текущей папке.
#include <stdio.h> #include <string.h> #include <math.h> /* Include rtw_modelmap.h for definitions of C API macros. */ #include "rtw_modelmap.h" #include "builtin_typeid_types.h" #include "rtwtypes.h" void tuneFcn(rtwCAPI_ModelMappingInfo *mmi, time_T *tPtr); void logFcn(rtwCAPI_ModelMappingInfo *mmi, time_T *tPtr);
Эти файлы используют API C, чтобы получить доступ к сигналу и данным о параметре в коде, который вы генерируете из модели в качестве примера.
В модели, Параметры конфигурации набора> Генерация кода> Пользовательский код> Вставляют пользовательский код С в сгенерированный> Заголовочный файл к #include "ex_myHandHdr.h"
. В той же панели в диалоговом окне Configuration Parameters, набор Дополнительная информация о Сборке> Исходные файлы к ex_myHandCode.c
.
set_param('rtwdemo_basicsc','CustomHeaderCode','#include "ex_myHandHdr.h"') set_param('rtwdemo_basicsc','CustomSource','ex_myHandCode.c')
Выберите Configuration Parameters> MAT-file Logging. Сгенерированный исполняемый файл запускается только до времени остановки симуляции (который вы устанавливаете в образцовых параметрах конфигурации).
set_param('rtwdemo_basicsc','MatFileLogging','on')
Выберите опции под Параметрами конфигурации> Генерация кода>, Интерфейс> Генерирует API C для.
set_param('rtwdemo_basicsc','RTWCAPIParams','on') set_param('rtwdemo_basicsc','RTWCAPISignals','on') set_param('rtwdemo_basicsc','RTWCAPIStates','on') set_param('rtwdemo_basicsc','RTWCAPIRootIO','on')
Загрузите библиотеку блоков Пользовательского кода.
custcode
Добавьте блок System Outputs в модель.
add_block('custcode/System Outputs','rtwdemo_basicsc/System Outputs')
В диалоговом окне блока System Outputs, Система набора Выходной Код Выполнения Функции к этому коду:
{ rtwdemo_basicsc_U.input2++; rtwCAPI_ModelMappingInfo *MMI = &(rtmGetDataMapInfo(rtwdemo_basicsc_M).mmi); tuneFcn(MMI, rtmGetTPtr(rtwdemo_basicsc_M)); }
В диалоговом окне блока, Система набора Выходной Код выхода Функции к этому коду:
{ rtwCAPI_ModelMappingInfo *MMI = &(rtmGetDataMapInfo(rtwdemo_basicsc_M).mmi); logFcn(MMI, rtmGetTPtr(rtwdemo_basicsc_M)); }
Также, чтобы сконфигурировать блок System Outputs, в командной строке, используют эти команды:
temp.TLCFile = 'custcode'; temp.Location = 'System Outputs Function'; temp.Middle = sprintf(['{\nrtwdemo_basicsc_U.input2++;'... '\nrtwCAPI_ModelMappingInfo *MMI = '... '&(rtmGetDataMapInfo(rtwdemo_basicsc_M).mmi);'... '\ntuneFcn(MMI, rtmGetTPtr(rtwdemo_basicsc_M));\n}']); temp.Bottom = sprintf(['{\nrtwCAPI_ModelMappingInfo *MMI = '... '&(rtmGetDataMapInfo(rtwdemo_basicsc_M).mmi);'... '\nlogFcn(MMI, rtmGetTPtr(rtwdemo_basicsc_M));\n}']); set_param('rtwdemo_basicsc/System Outputs','RTWdata',temp)
Сгенерируйте код из модели.
rtwbuild('rtwdemo_basicsc')
### Starting build procedure for model: rtwdemo_basicsc ### Successful completion of build procedure for model: rtwdemo_basicsc
В отчете генерации кода просмотрите интерфейсный файл rtwdemo_basicsc_capi.c
. Этот файл инициализирует массивы структур, которые можно использовать, чтобы взаимодействовать с элементами данных через API C. Например, в массиве структур rtBlockSignals
, первая структура (индекс 0) описывает выходной сигнал с концом теста блока Gain в модели.
file = fullfile('rtwdemo_basicsc_grt_rtw','rtwdemo_basicsc_capi.c'); rtwdemodbtype(file,'/* Block output signal information */',... '/* Individual block tuning',1,0)
/* Block output signal information */ static const rtwCAPI_Signals rtBlockSignals[] = { /* addrMapIndex, sysNum, blockPath, * signalName, portNumber, dataTypeIndex, dimIndex, fxpIndex, sTimeIndex */ { 0, 0, TARGET_STRING("rtwdemo_basicsc/Gain"), TARGET_STRING(""), 0, 0, 0, 0, 0 }, { 0, 0, (NULL), (NULL), 0, 0, 0, 0, 0 } };
Поля структуры, такие как addrMapIndex
, указывают на индексы в другие массивы структур, такие как rtDataAddrMap
, которые описывают характеристики сигнала. Эти характеристики включают адрес данных сигнала (указатель на данные), тип числовых данных и размерности сигнала.
В файле rtwdemo_basicsc.c
просмотрите алгоритм кода в функции модели step
. Алгоритм сначала выполняет код, который вы задали в блоке System Outputs.
file = fullfile('rtwdemo_basicsc_grt_rtw','rtwdemo_basicsc.c'); rtwdemodbtype(file,'/* user code (Output function Body) */',... '/* Logic: ''<Root>/LogOp'' incorporates:',1,0)
/* user code (Output function Body) */ /* System '<Root>' */ { rtwdemo_basicsc_U.input2++; rtwCAPI_ModelMappingInfo *MMI = &(rtmGetDataMapInfo(rtwdemo_basicsc_M).mmi); tuneFcn(MMI, rtmGetTPtr(rtwdemo_basicsc_M)); } /* DataStoreWrite: '<Root>/DSWrite' incorporates: * Constant: '<Root>/Constant1' * Constant: '<Root>/Constant2' * Inport: '<Root>/In1' * Logic: '<Root>/LogOp' * RelationalOperator: '<Root>/RelOp1' * RelationalOperator: '<Root>/RelOp2' */ rtwdemo_basicsc_DW.mode = ((rtwdemo_basicsc_U.input1 > 10.0F) || (rtwdemo_basicsc_U.input1 < -10.0F)); /* Gain: '<Root>/Gain' incorporates: * Inport: '<Root>/In2' * Lookup_n-D: '<Root>/Table1' */ rtwdemo_basicsc_B.Gain = rtwdemo_basicsc_P.K1 * look1_iflf_binlx (rtwdemo_basicsc_U.input2, rtCP_Table1_bp01Data, rtCP_Table1_tableData, 10U); /* Chart: '<Root>/Stateflow Chart' */ /* Gateway: Stateflow Chart */ /* During: Stateflow Chart */ /* Entry Internal: Stateflow Chart */ /* Transition: '<S1>:5' */ if (rtwdemo_basicsc_DW.mode) { /* Transition: '<S1>:6' */ /* Transition: '<S1>:2' */ rtwdemo_basicsc_DW.X = rtwdemo_basicsc_B.Gain; } else { /* Transition: '<S1>:4' */ } /* Outport: '<Root>/Out1' incorporates: * Chart: '<Root>/Stateflow Chart' */ /* Transition: '<S1>:3' */ rtwdemo_basicsc_Y.Out1 = (real32_T)(rtwdemo_basicsc_DW.X * 3.0); /* Lookup_n-D: '<Root>/Table2' incorporates: * Inport: '<Root>/In3' * Inport: '<Root>/In4' */ rtwdemo_basicsc_DW.X = look2_iflf_binlx(rtwdemo_basicsc_U.input3, rtwdemo_basicsc_U.input4, rtCP_Table2_bp01Data, rtCP_Table2_bp02Data, rtCP_Table2_tableData, rtCP_Table2_maxIndex, 3U); /* user code (Output function Trailer) */ /* System '<Root>' */ { rtwCAPI_ModelMappingInfo *MMI = &(rtmGetDataMapInfo(rtwdemo_basicsc_M).mmi); logFcn(MMI, rtmGetTPtr(rtwdemo_basicsc_M)); } /* Matfile logging */ rt_UpdateTXYLogVars(rtwdemo_basicsc_M->rtwLogInfo, (&rtwdemo_basicsc_M->Timing.taskTime0)); /* signal main to stop simulation */ { /* Sample time: [1.0s, 0.0s] */ if ((rtmGetTFinal(rtwdemo_basicsc_M)!=-1) && !((rtmGetTFinal(rtwdemo_basicsc_M)-rtwdemo_basicsc_M->Timing.taskTime0) > rtwdemo_basicsc_M->Timing.taskTime0 * (DBL_EPSILON))) { rtmSetErrorStatus(rtwdemo_basicsc_M, "Simulation finished"); } } /* Update absolute time for base rate */ /* The "clockTick0" counts the number of times the code of this task has * been executed. The absolute time is the multiplication of "clockTick0" * and "Timing.stepSize0". Size of "clockTick0" ensures timer will not * overflow during the application lifespan selected. * Timer of this task consists of two 32 bit unsigned integers. * The two integers represent the low bits Timing.clockTick0 and the high bits * Timing.clockTickH0. When the low bit overflows to 0, the high bits increment. */ if (!(++rtwdemo_basicsc_M->Timing.clockTick0)) { ++rtwdemo_basicsc_M->Timing.clockTickH0; } rtwdemo_basicsc_M->Timing.taskTime0 = rtwdemo_basicsc_M->Timing.clockTick0 * rtwdemo_basicsc_M->Timing.stepSize0 + rtwdemo_basicsc_M->Timing.clockTickH0 * rtwdemo_basicsc_M->Timing.stepSize0 * 4294967296.0; } /* Model initialize function */ void rtwdemo_basicsc_initialize(void) { /* Registration code */ /* initialize non-finites */ rt_InitInfAndNaN(sizeof(real_T)); /* initialize real-time model */ (void) memset((void *)rtwdemo_basicsc_M, 0, sizeof(RT_MODEL_rtwdemo_basicsc_T)); rtmSetTFinal(rtwdemo_basicsc_M, 10.0); rtwdemo_basicsc_M->Timing.stepSize0 = 1.0; /* Setup for data logging */ { static RTWLogInfo rt_DataLoggingInfo; rt_DataLoggingInfo.loggingInterval = NULL; rtwdemo_basicsc_M->rtwLogInfo = &rt_DataLoggingInfo; } /* Setup for data logging */ { rtliSetLogXSignalInfo(rtwdemo_basicsc_M->rtwLogInfo, (NULL)); rtliSetLogXSignalPtrs(rtwdemo_basicsc_M->rtwLogInfo, (NULL)); rtliSetLogT(rtwdemo_basicsc_M->rtwLogInfo, "tout"); rtliSetLogX(rtwdemo_basicsc_M->rtwLogInfo, ""); rtliSetLogXFinal(rtwdemo_basicsc_M->rtwLogInfo, ""); rtliSetLogVarNameModifier(rtwdemo_basicsc_M->rtwLogInfo, "rt_"); rtliSetLogFormat(rtwdemo_basicsc_M->rtwLogInfo, 0); rtliSetLogMaxRows(rtwdemo_basicsc_M->rtwLogInfo, 1000); rtliSetLogDecimation(rtwdemo_basicsc_M->rtwLogInfo, 1); /* * Set pointers to the data and signal info for each output */ { static void * rt_LoggedOutputSignalPtrs[] = { &rtwdemo_basicsc_Y.Out1 }; rtliSetLogYSignalPtrs(rtwdemo_basicsc_M->rtwLogInfo, ((LogSignalPtrsType) rt_LoggedOutputSignalPtrs)); } { static int_T rt_LoggedOutputWidths[] = { 1 }; static int_T rt_LoggedOutputNumDimensions[] = { 1 }; static int_T rt_LoggedOutputDimensions[] = { 1 }; static boolean_T rt_LoggedOutputIsVarDims[] = { 0 }; static void* rt_LoggedCurrentSignalDimensions[] = { (NULL) }; static int_T rt_LoggedCurrentSignalDimensionsSize[] = { 4 }; static BuiltInDTypeId rt_LoggedOutputDataTypeIds[] = { SS_SINGLE }; static int_T rt_LoggedOutputComplexSignals[] = { 0 }; static RTWPreprocessingFcnPtr rt_LoggingPreprocessingFcnPtrs[] = { (NULL) }; static const char_T *rt_LoggedOutputLabels[] = { "output" }; static const char_T *rt_LoggedOutputBlockNames[] = { "rtwdemo_basicsc/Out1" }; static RTWLogDataTypeConvert rt_RTWLogDataTypeConvert[] = { { 0, SS_SINGLE, SS_SINGLE, 0, 0, 0, 1.0, 0, 0.0 } }; static RTWLogSignalInfo rt_LoggedOutputSignalInfo[] = { { 1, rt_LoggedOutputWidths, rt_LoggedOutputNumDimensions, rt_LoggedOutputDimensions, rt_LoggedOutputIsVarDims, rt_LoggedCurrentSignalDimensions, rt_LoggedCurrentSignalDimensionsSize, rt_LoggedOutputDataTypeIds, rt_LoggedOutputComplexSignals, (NULL), rt_LoggingPreprocessingFcnPtrs, { rt_LoggedOutputLabels }, (NULL), (NULL), (NULL), { rt_LoggedOutputBlockNames }, { (NULL) }, (NULL), rt_RTWLogDataTypeConvert } }; rtliSetLogYSignalInfo(rtwdemo_basicsc_M->rtwLogInfo, rt_LoggedOutputSignalInfo); /* set currSigDims field */ rt_LoggedCurrentSignalDimensions[0] = &rt_LoggedOutputWidths[0]; } rtliSetLogY(rtwdemo_basicsc_M->rtwLogInfo, "yout"); } /* block I/O */ (void) memset(((void *) &rtwdemo_basicsc_B), 0, sizeof(B_rtwdemo_basicsc_T)); /* states (dwork) */ (void) memset((void *)&rtwdemo_basicsc_DW, 0, sizeof(DW_rtwdemo_basicsc_T)); /* external inputs */ (void)memset(&rtwdemo_basicsc_U, 0, sizeof(ExtU_rtwdemo_basicsc_T)); /* external outputs */ rtwdemo_basicsc_Y.Out1 = 0.0F; /* Initialize DataMapInfo substructure containing ModelMap for C API */ rtwdemo_basicsc_InitializeDataMapInfo(); /* Matfile logging */ rt_StartDataLoggingWithStartTime(rtwdemo_basicsc_M->rtwLogInfo, 0.0, rtmGetTFinal(rtwdemo_basicsc_M), rtwdemo_basicsc_M->Timing.stepSize0, (&rtmGetErrorStatus(rtwdemo_basicsc_M))); /* Start for DataStoreMemory: '<Root>/Data Store Memory' */ rtwdemo_basicsc_DW.mode = false; /* InitializeConditions for UnitDelay: '<Root>/Delay' */ rtwdemo_basicsc_DW.X = 0.0F; } /* Model terminate function */ void rtwdemo_basicsc_terminate(void) { /* (no terminate code required) */ }
Этот код сначала тревожит входной сигнал input2
путем постепенного увеличения значения сигнала каждый раз, когда функция step
выполняется. Код затем использует встроенный макро-rtmGetDataMapInfo
, чтобы извлечь модель, сопоставляющую информацию от структуры данных модели rtwdemo_basicsc_M
. MMI
указателя указывает на извлеченную информацию об отображении, которая позволяет функциям tuneFcn
и logFcn
, чтобы получить доступ к информации, содержавшейся в массивах структур, которые задает файл API C rtwdemo_basicsc_capi.c
.
Просмотрите функциональный tuneFcn
в файле ex_myHandCode.c
. Эта функция использует API C (через модель, сопоставляющую информацию mmi
) и указатель на время симуляции, чтобы распечатать значение параметра K1
в конкретные моменты времени во время выполнения кода. Когда время симуляции достигает 5 секунд, функция изменяет значение параметров в памяти. При помощи блока switch case
функция может получить доступ к данным о параметре, является ли типом данных int8
или double
.
Просмотрите алгоритм кода в функции модели step
снова. Около конца функции алгоритм выполняет код, который вы задали в блоке System Outputs. Этот код вызывает функциональный logFcn
.
rtwdemodbtype(file,'/* user code (Output function Trailer) */',... '/* Matfile logging */',1,0)
/* user code (Output function Trailer) */ /* System '<Root>' */ { rtwCAPI_ModelMappingInfo *MMI = &(rtmGetDataMapInfo(rtwdemo_basicsc_M).mmi); logFcn(MMI, rtmGetTPtr(rtwdemo_basicsc_M)); }
Просмотрите функциональный logFcn
в файле ex_myHandCode.c
. Функция использует API C, чтобы распечатать значение сигнала с концом теста. Функция может получить доступ к данным сигнала, является ли типом данных single
или double
.
В командной строке запустите сгенерированный исполняемый rtwdemo_bascisc.exe
.
system('rtwdemo_basicsc')
Параметр и значения сигналов появляются в окне Command Window.
Для получения дополнительной информации об интерфейсах данных, включая API C, смотрите Интерфейсы Обмена данными (Simulink Coder).
Simulink.Parameter
| Simulink.Signal
| Simulink.Signal