Доступ к сигналу, состоянию и данным о параметре во время выполнения

Когда вы итеративно разрабатываете модель, вы получаете выходной сигнал и утверждаете данные, которые генерирует выполнение модели. Вы также значения настройки параметров во время выполнения, чтобы наблюдать результаты относительно выходных параметров. Можно затем основывать проектные решения на анализе этих выходных параметров. Чтобы получить доступ к этому сигналу, состоянию и данным о параметре в среде быстрого прототипирования, можно сконфигурировать сгенерированный код, чтобы хранить данные в адресуемой памяти.

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

Исследуйте модель в качестве примера

Запустите скрипт, который готовит модель rtwdemo_basicsc для этого примера.

run(fullfile(matlabroot,'examples','simulinkcoder','main','prepare_rtwdemo_basicsc'));

Эти данные сконфигурированы для генерации кода:

  • Параметры UPPERниже, LIMIT, K1, и K2 (Stateflow), T1Break, T1Data, T2Break, T2 Data

  • Сигналы Input1, Input2, Input3, Input4, и output

  • Состояния X (задержка) и mode (запись памяти хранилища данных и Stateflow)

Откройте модель в качестве примера, rtwdemo_basicsc.

rtwdemo_basicsc

Модель загружает числовые переменные MATLAB в базовое рабочее пространство. Переменные рабочей области устанавливают некоторые параметры блоков в модели. Однако блок Gain в модели использует литеральное значение 2.

Отключите оптимизацию

1. В модели очистите Повторное использование памяти параметра конфигурации модели. Когда вы очищаете эту оптимизацию и другую оптимизацию ту, которая Устраняет лишние локальные переменные (сворачивание выражения), сгенерированный код выделяет память для сигнальных линий. Очистка Повторного использования памяти отключает большую часть другой оптимизации.

set_param('rtwdemo_basicsc','OptimizeBlockIOStorage','off')

2. Установите поведение параметра Значения по умолчанию параметра конфигурации модели на Tunable. Когда установлено в Tunable, этот параметр конфигурации заставляет сгенерированный код выделять память для переменных рабочей области и параметров блоков.

set_param('rtwdemo_basicsc','DefaultParameterBehavior','Tunable')

3. Сгенерируйте код.

rtwbuild('rtwdemo_basicsc')
### Starting build procedure for: rtwdemo_basicsc
### Successful completion of build procedure for: rtwdemo_basicsc

4. В отчете генерации кода просмотрите файл 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'
                              */
};

5. Просмотрите файл rtwdemo_basicsc_data.c. Этот исходный файл выделяет глобальную память для структуры параметра и инициализирует значения полей на основе значений параметров в модели.

6. Просмотрите исходный файл 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')

1. На вкладке Modeling нажмите Model Data Editor.

2. В Model Data Editor смотрите вкладку Signals.

3. Установите представление Change выпадающий список на Instrumentation.

4. В модели выберите выходной сигнал блока Gain.

5. В Model Data Editor установите флажок в столбце Тестовой точки.

portHandle = get_param('rtwdemo_basicsc/Gain','PortHandles');
portHandle = portHandle.Outport;
set_param(portHandle,'TestPoint','on')

6. Смотрите вкладку Parameters.

7. В модели выберите блок Gain.

8. В Model Data Editor используйте Столбец значений, чтобы установить значение усиления к K1.

10. Рядом с K1, кликните по кнопке действий (с тремя вертикальными точками) и выберите Create.

11. В диалоговом окне Create New Data, установленном Значении к Simulink.Parameter(2) и нажмите Create. Simulink.Parameter возразите названному K1, со значением 2, появляется в базовом рабочем пространстве.

12. В диалоговом окне свойства для K1, примените класс памяти кроме Auto при помощи Класса памяти. Например, используйте класс памяти Model default представлять объект параметра как поле глобальной структуры параметров.

set_param('rtwdemo_basicsc/Gain','Gain','K1');
K1 = Simulink.Parameter(2);
K1.StorageClass = 'Model default';

13. Сгенерируйте код.

rtwbuild('rtwdemo_basicsc')
### Starting build procedure for: rtwdemo_basicsc
### Successful completion of build procedure for: rtwdemo_basicsc

14. В отчете генерации кода просмотрите файл 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;
            }
        }
    }
}

2. Скопируйте этот пользовательский код заголовка в файл с именем 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, чтобы получить доступ к сигналу и данным о параметре в коде, который вы генерируете из модели в качестве примера.

3. Установите Заголовочный файл параметров конфигурации модели и Исходные файлы к #include "ex_myHandHdr.h" и ex_myHandCode.c, соответственно.

set_param('rtwdemo_basicsc','CustomHeaderCode','#include "ex_myHandHdr.h"')
set_param('rtwdemo_basicsc','CustomSource','ex_myHandCode.c')

4. Выберите Логгирование MAT-файла параметра конфигурации модели. Сгенерированный исполняемый файл запускается только до времени остановки симуляции (который вы устанавливаете в параметрах конфигурации модели).

set_param('rtwdemo_basicsc','MatFileLogging','on')

5 параметров параметров конфигурации модели Select C API, сигналы, состояния и ввод-вывод корневого уровня.

set_param('rtwdemo_basicsc','RTWCAPIParams','on')
set_param('rtwdemo_basicsc','RTWCAPISignals','on')
set_param('rtwdemo_basicsc','RTWCAPIStates','on')
set_param('rtwdemo_basicsc','RTWCAPIRootIO','on')

5. Загрузите библиотеку блоков Пользовательского кода.

custcode

6. Добавьте блок System Outputs в модель.

add_block('custcode/System Outputs','rtwdemo_basicsc/System Outputs')

7. В Системе Выходное диалоговое окно блока, Система набора Выходной Код Выполнения Функции к этому коду:

{
rtwdemo_basicsc_U.input2++;
rtwCAPI_ModelMappingInfo *MMI = &(rtmGetDataMapInfo(rtwdemo_basicsc_M).mmi);
tuneFcn(MMI, rtmGetTPtr(rtwdemo_basicsc_M));
}

8. В диалоговом окне блока, Система набора Выходной Код выхода Функции к этому коду:

{
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)

9. Сгенерируйте код.

rtwbuild('rtwdemo_basicsc')
### Starting build procedure for: rtwdemo_basicsc
### Successful completion of build procedure for: rtwdemo_basicsc

10. В отчете генерации кода просмотрите интерфейсный файл 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, это описывает характеристики сигнала. Эти характеристики включают адрес данных сигнала (указатель на данные), тип числовых данных и размерности сигнала.

11. В файле 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 задает.

12. Просмотрите функциональный tuneFcn в файле ex_myHandCode.c. Эта функция использует API C (через модель, сопоставляющую информацию mmi) и указатель на время симуляции, чтобы распечатать значение параметра K1 в конкретные моменты времени во время выполнения кода. Когда время симуляции достигает 5 секунд, функция изменяет значение параметров в памяти. При помощи switch case блокируйтесь, функция может получить доступ к данным о параметре, является ли типом данных int8 или double.

13. Просмотрите алгоритм кода в модели 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));
  }

14. Просмотрите функциональный logFcn в файле ex_myHandCode.c. Функция использует API C, чтобы распечатать значение сигнала с концом теста. Функция может получить доступ к данным сигнала, является ли типом данных single или double.

15. В командной строке запустите сгенерированный исполняемый rtwdemo_bascisc.exe.

system('rtwdemo_basicsc')

Параметр и значения сигналов появляются в окне Command Window.

Для получения дополнительной информации об интерфейсах данных, включая API C, смотрите Интерфейсы Обмена данными (Simulink Coder).

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

| |

Похожие темы

Для просмотра документации необходимо авторизоваться на сайте