Этот пример показывает, как сгенерировать код, который использует глобальные данные, которые задает некоторый рукописный код. В рукописном коде переменная указателя указывает на одну из трех переменных структуры, которые содержат данные о параметре. Рукописные функциональные переключатели указатель между структурами. Сгенерированный код получает доступ к данным о параметре путем разыменования переменной указателя.
Откройте исходный файл в качестве примера rtwdemo_importstruct_user.c
. Код задает переменную ReferenceStruct
структуры данных по умолчанию как постоянную (const
) данные и статически инициализирует каждое поле. Эта структура представляет набор справочных данных.
/* Constant default data structure (reference data set) */ const DataStruct_type ReferenceStruct = { 11, /* OFFSET */ 2 /* GAIN */ };
Код задает две других переменные структуры, WorkingStruct1
и WorkingStruct2
, как энергозависимые (volatile
) данные.
/* Volatile data structures (working data sets) */ volatile DataStruct_type WorkingStruct1; volatile DataStruct_type WorkingStruct2;
Код задает функцию, которая может инициализировать:
Неактивная рабочая структура от активной рабочей структуры.
Обе рабочих структуры от ссылочной структуры.
/* Function to initialize inactive working structures from active structure */ void InitInactiveWorkingStructs(void) { if (StructPointer == &WorkingStruct1) { /* Copy values from WorkingStruct1 to WorkingStruct2 */ memcpy((void*)&WorkingStruct2, (void*)&WorkingStruct1, sizeof(ReferenceStruct)); } else if (StructPointer == &WorkingStruct2) { /* Copy values from WorkingStruct2 to WorkingStruct1 */ memcpy((void*)&WorkingStruct1, (void*)&WorkingStruct2, sizeof(ReferenceStruct)); } else { /* Initialize both working structures from ReferenceStruct */ memcpy((void*)&WorkingStruct1, &ReferenceStruct, sizeof(ReferenceStruct)); memcpy((void*)&WorkingStruct2, &ReferenceStruct, sizeof(ReferenceStruct)); } }
Код задает StructPointer
, который является указателем const volatile
на структуру. Код инициализирует указатель на адрес ReferenceStruct
.
/* Define structure pointer. Point to reference structure by default */ const volatile DataStruct_type *StructPointer = &ReferenceStruct;
Наконец, код задает функцию, которая может динамически установить StructPointer
указывать или на ReferenceStruct
, WorkingStruct1
или на WorkingStruct2
.
/* Function to switch between structures */ void SwitchStructPointer(Dataset_T Dataset) { switch (Dataset) { case Working1: StructPointer = &WorkingStruct1; break; case Working2: StructPointer = &WorkingStruct2; break; default: StructPointer = &ReferenceStruct; } }
Заголовочный файл в качестве примера rtwdemo_importstruct_user.h
задает перечисление Dataset_T
и структура, вводит Datastruct_type
. Файл включает (#include
) встроенный заголовочный файл Simulink® Coder™ rtwtypes.h
, который задает (typedef
) типы данных Simulink Coder, такие как int16_T
.
#include "rtwtypes.h" typedef enum { Reference = 0, Working1, Working2 } Dataset_T; typedef struct DataStruct_tag { int16_T OFFSET; /* OFFSET */ int16_T GAIN; /* GAIN */ } DataStruct_type;
Файл также объявляет глобальные переменные и функции.
Код разработан так, чтобы исходный код алгоритма управления (или сгенерировал или рукописный) мог считать данные из ReferenceStruct
, WorkingStruct1
или WorkingStruct2
путем разыменования (->
) StructPointer
. Две рабочих структуры (WorkingStruct1
и WorkingStruct2
) расположены в энергозависимой памяти и предназначаются, чтобы быть измененными во время времени выполнения внешним калибровочным инструментом. Калибровочный инженер не изменяет активную рабочую структуру. Вместо этого инженер изменяет значения параметров в неактивной рабочей структуре и затем активирует ее путем переключения рабочих структур.
При необходимости для безопасности или при подготовке к закрытию приложения, калибровочный инструмент может указать StructPointer
на ReferenceStruct
вместо этого. ReferenceStruct
хранит значения параметров по умолчанию, которые не изменяются во время выполнения.
Откройте модель в качестве примера, rtwdemo_importstruct
.
Модель создает переменные и объекты в базовом рабочем пространстве. Блок Constant и блок Gain используют объекты ECoderDemos.Parameter
GAIN
и OFFSET
, чтобы установить параметры блоков Постоянного значения и Усиления. ECoderDemos
является примером пользовательский пакет, который задает два класса, Parameter
и Signal
и некоторые пользовательские классы памяти.
В модели выберите View> Model Data Editor.
В Model Data Editor осмотрите вкладку Parameters.
Установите представление Change выпадающий список на Code
.
Нажмите кнопку дополнительной информации Show/refresh.
Model Data Editor показывает строки, которые соответствуют параметрам Постоянного значения и Усиления блоков и строк, который соответствует OFFSET
и GAIN
, которые устанавливают значения параметров. В столбце Класса памяти OFFSET
и GAIN
используют пользовательский класс памяти StructPointer
, который задает пакет ECoderDemos
.
Откройте Custom Storage Class Designer и осмотрите пользовательские классы памяти в пакете ECoderDemos
. В командной строке используйте эту команду:
cscdesigner('ECoderDemos')
Этот пакет в качестве примера задает несколько пользовательских классов памяти, включая StructPointer
. Вы не можете отредактировать определения. Однако можно создать собственные пакеты и пользовательские классы памяти позже. Для примера, который показывает, как создать пакет и пользовательский класс памяти, смотрите, Создают и Применяют Пользовательский Класс памяти.
В соответствии с Пользовательскими определениями класса памяти, нажмите StructPointer
. Настройки для этого пользовательского класса памяти позволяют сгенерированному коду взаимодействовать с переменной указателя, StructPointer
, из внешнего кода. Например, пользовательский класс памяти использует эти настройки:
Осциллограф данных установлен в Imported
, потому что пример, который задает внешний код (выделяет память для), StructPointer
. С этой установкой генератор кода старается не генерировать ненужные, дублирующиеся определения для элементов данных, таких как ECoderDemos.Parameter
возражает, то использование пользовательский класс памяти.
Доступ к данным установлен в Pointer
, потому что в примере внешний код, StructPointer
является указателем.
Раздел Memory установлен в ConstVolatile
, потому что пример внешний код задает StructPointer
как постоянные, энергозависимые данные (const volatile
).
Тип установлен в FlatStructure
, потому что в примере внешний код, StructPointer
указывает на структуру. С этой установкой сгенерированный код обрабатывает каждый элемент данных (объект ECoderDemos.Parameter
) как поле плоской структуры, имя переменной которой и имя типа можно задать.
На вкладке Structure Attributes имя Struct определяется к StructPointer
. Для FlatStructure
пользовательский класс памяти имя Struct задает имя переменной структуры в сгенерированном коде. В этом примере StructPointer
является именем переменной, которую задает внешний код.
Имя типа установлено в DataStruct_type
, который является именем типа структуры, который задает пример внешний код.
В модели, в диалоговом окне Configuration Parameters, осматривают Генерацию кода> панель Пользовательского кода.
Под Вставкой пользовательский код С в сгенерированном выберите функцию Initialize. Это значение параметров указывает, что код, чтобы включать в сгенерированную модель инициализирует функцию. В этой модели установлен параметр конфигурации так, чтобы сгенерированный код вызвал функцию InitInactiveWorkingStructs
. InitInactiveWorkingStructs
инициализирует рабочие структуры со значениями от ReferenceStruct
. Код инициализации затем устанавливает указатель на первую рабочую структуру.
Под Дополнительной информацией о сборке выберите Исходные файлы. Этот параметр конфигурации идентифицирует пример внешний файл кода rtwdemo_importstruct_user.c
для включения в процесс сборки после генерации кода.
Сгенерируйте код из модели.
В сгенерированном файле rtwdemo_importstruct.c
, образцовые вызовы функции инициализации InitInactiveWorkingStructs
.
/* Model initialize function */ void rtwdemo_importstruct_initialize(void) { /* user code (Initialize function Body) */ /* Initialize the working structures to reference values */ InitInactiveWorkingStructs(); /* Switch to first working structure */ SwitchStructPointer(Working1); } /*
Алгоритм в образцовом выполнении (step
) функция разыменовывает переменную указателя StructPointer
.
/* Model step function */ void rtwdemo_importstruct_step(void) { /* Outport: '<Root>/Out' incorporates: * Constant: '<Root>/Offset' * Gain: '<Root>/Gain' * Inport: '<Root>/In' * Sum: '<Root>/Sum' */ Sensor_Out = (int16_T)((int16_T)(Sensor_In - StructPointer->OFFSET) * StructPointer->GAIN); }