В этом примере показано, как создать код, использующий глобальные данные, определенные некоторым рукописным кодом. В рукописном коде переменная указателя указывает на одну из трех структурных переменных, содержащих данные параметров. Рукописная функция переключает указатель между структурами. Сгенерированный код получает доступ к данным параметра путем отмены ссылки на переменную указателя.
Открыть исходный файл примера 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.

Модель создает переменные и объекты в базовом рабочем пространстве. Блок константы и блок усиления используют ECoderDemos.Parameter объекты GAIN и OFFSET для установки параметров «Постоянное значение» и «Блок усиления». ECoderDemos является примером пользовательского пакета, который определяет два класса, Parameter и Signalи некоторые пользовательские классы хранения.
На вкладке Моделирование (Modeling) щелкните Редактор данных модели (Model Data Editor).
В Редакторе данных модели (Model Data Editor) проверьте вкладку Параметры (Parameters).
Установите в раскрывающемся списке Изменить представление значение Code.
Нажмите кнопку Показать/обновить дополнительную информацию.
Редактор данных модели показывает строки, которые соответствуют параметрам «Постоянное значение» и «Коэффициент усиления» блоков и строк, которые соответствуют OFFSET и GAIN, которые устанавливают значения параметров. В столбце «Класс хранилища» OFFSET и GAIN использовать пользовательский класс хранения StructPointer, который ECoderDemos пакет определяет.
Откройте конструктор классов пользовательских хранилищ и проверьте классы пользовательских хранилищ в ECoderDemos пакет. В командной строке используйте следующую команду:
cscdesigner('ECoderDemos')
В этом примере пакет определяет несколько пользовательских классов хранения, включая StructPointer. Нельзя редактировать определения. Однако позже можно создать собственные пакеты и пользовательские классы хранения. Пример создания пакета и пользовательского класса хранения см. в разделе Создание и применение класса хранения.
В разделе Настраиваемые определения классов хранения щелкните StructPointer. Параметры этого пользовательского класса хранения позволяют сгенерированному коду взаимодействовать с переменной указателя, StructPointer, из внешнего кода. Например, в пользовательском классе хранения используются следующие параметры:
Для области данных установлено значение Imported потому что пример внешнего кода определяет (выделяет память для) StructPointer. С помощью этой настройки генератор кода избегает создания ненужных, повторяющихся определений для элементов данных, таких как ECoderDemos.Parameter объекты, использующие пользовательский класс хранения.
Для доступа к данным установлено значение Pointer потому что в примере внешний код, StructPointer является указателем.
Для раздела памяти установлено значение ConstVolatile потому что пример внешнего кода определяет StructPointer в виде постоянных, изменчивых данных (const volatile).
Тип имеет значение FlatStructure потому что в примере внешний код, StructPointer указывает на структуру. С помощью этой настройки сгенерированный код обрабатывает каждый элемент данных (ECoderDemos.Parameter объект) как поле плоской структуры, имя переменной и имя типа которого можно указать.
На вкладке Атрибуты структуры (Structure Attributes) для параметра Наименование структуры (Struct name) установлено значение StructPointer. Для FlatStructure custom storage class, Struct name указывает имя структурной переменной в созданном коде. В этом примере: StructPointer - имя переменной, определяемое внешним кодом.
Для имени типа установлено значение DataStruct_type, которое является именем типа структуры, определяемого внешним кодом примера.
В модели в диалоговом окне Параметры конфигурации (Configuration Parameters) проверьте панель Создание кода (Code Generation) > Пользовательский код (Custom Code).
В разделе Вставить пользовательский код C в сгенерированном выберите Инициализировать функцию. Это значение параметра определяет код для включения в создаваемую функцию инициализации модели. В этой модели параметр конфигурации устанавливается таким образом, что сгенерированный код вызывает 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);
}