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

Перечислимые типы данных

Перечислимые данные являются данными, которые ограничиваются конечным множеством значений. Перечислимый тип данных является классом MATLAB®, который задает набор перечисляемых значений. Каждое перечисляемое значение состоит из перечислимого имени и базового целого числа, которое программное обеспечение использует внутренне и в сгенерированном коде. Следующее является определением класса MATLAB для перечислимого типа данных под названием BasicColors, который используется в примерах в этом разделе.

classdef BasicColors < Simulink.IntEnumType
  enumeration
    Red(0)
    Yellow(1)
    Blue(2)
  end
end

Для основной информации о перечислимых типах данных и их использовании в моделях Simulink®, смотрите Использование Перечислимые Данные в Моделях Simulink (Simulink). Для получения информации о перечислимых типах данных в графиках Stateflow® смотрите, Задают Перечислимые Типы данных (Stateflow).

Задайте целочисленный тип данных для перечисления

Когда вы задаете тип данных для своего перечисления, вы можете:

  • Управляйте размером перечислимых типов данных в сгенерированном коде путем определения суперкласса.

  • Уменьшайте использование RAM/ROM.

  • Улучшите переносимость кода.

  • Улучшите интеграцию с унаследованным кодом.

Можно задать эти целочисленные типы данных:

  • int8

  • uint8

  • int16

  • uint16

  • int32

  • Simulink.IntEnumType. Задайте значения в области значений целого числа со знаком для вашей аппаратной платформы.

Используйте определение класса в файле MATLAB

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

classdef Colors < int8
   enumeration
     Red(0)
     Green(1)
     Blue(2)
   end
end

Генератор кода генерирует этот код:

typedef int8_T Colors;

#define Red      ((Colors)0)
#define Green ((Colors)1)
#define Blue     ((Colors)2)

Используйте функцию Simulink.defineIntEnumType

Чтобы задать размер целочисленного типа данных, задайте пару "имя-значение" StorageType как целочисленный тип данных.

Simulink.defineIntEnumType('Colors',{'Red','Green','Blue'},...
[0;1;2],'StorageType','int8')

Генератор кода генерирует этот код:

typedef int8_T Colors;

#define Red      ((Colors)0)
#define Green ((Colors)1)
#define Blue     ((Colors)2)

Настройте перечислимый тип данных

Когда вы генерируете код из модели, которая использует перечислимые данные, можно реализовать эти статические методы настроить поведение типа в процессе моделирования и в сгенерированном коде:

  • getDefaultValue — Задает значение по умолчанию перечислимого типа данных.

  • getDescription — Задает описание перечислимого типа данных.

  • getHeaderFile — Задает заголовочный файл, где тип задан для сгенерированного кода.

  • getDataScope — Задает, экспортирует ли сгенерированный код или импортирует перечислимое определение типов к или от отдельного заголовочного файла.

  • addClassNameToEnumNames — Задает, становится ли имя класса префиксом в сгенерированном коде.

Первый из этих методов, getDefaultValue, относится к симуляции и для генерации кода, и описан в, Задают Перечисляемое значение По умолчанию (Simulink). Другие методы относятся только к генерации кода. Чтобы настроить поведение перечислимого типа, включайте версию метода в methods(Static) раздел определения класса перечисления. Если вы не хотите настраивать тип, не используйте methods(Static) раздел. Таблица суммирует методы и данные, чтобы предоставить для каждого.

Статический методЦельЗначение по умолчанию, не реализовывая методПользовательское возвращаемое значение
getDefaultValueЗадает член перечисления по умолчанию для класса.Первый член задан в определении перечисленияВектор символов, содержащий имя члена перечисления в классе (см., Инстанцирует Перечислений (Simulink)).
getDescriptionЗадает описание класса перечисления.''Вектор символов, содержащий описание типа.
getHeaderFileЗадает имя заголовочного файла. Метод getDataScope определяет значение файла.''

Вектор символов, содержащий имя заголовочного файла, который задает перечислимый тип.

По умолчанию, сгенерированный #include директива использует разделитель препроцессора " вместо < и >. Сгенерировать направляющий #include <myTypes.h>, задайте пользовательское возвращаемое значение как '<myTypes.h>'.

getDataScopeЗадает, экспортирует ли сгенерированный код или импортирует определение перечислимого типа данных. Используйте метод getHeaderFile задавать сгенерированный или включенный заголовочный файл, который задает тип.'Auto'Один из: 'Auto', 'Exported', или 'Imported'.
addClassNameToEnumNamesЗадает, снабдить ли префиксом имя класса в сгенерированном коде.falsetrue или false.

Задайте описание

Чтобы задать описание для перечислимого типа данных, включайте этот метод в methods(Static) раздел класса перечисления:

function retVal = getDescription() 
% GETDESCRIPTION  Optional description of the data type.
  retVal = 'description';
end

Замените вектором символов MATLAB description. Сгенерированный код, который задает перечислимый тип, включает заданное описание.

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

Чтобы препятствовать тому, чтобы сгенерированный код задал перечислимый тип данных, который позволяет вам предоставлять определение во внешнем файле, включают эти методы в methods(Static) раздел класса перечисления:

    function retVal = getHeaderFile()
      % GETHEADERFILE Specifies the file that defines this type in generated code.
      % The method getDataScope determines the significance of the specified file.
      retVal = 'imported_enum_type.h';
    end

    function retVal = getDataScope()
      % GETDATASCOPE Specifies whether generated code imports or exports this type.
      % Return one of:
      % 'Auto':     define type in model_types.h, or import if header file specified
      % 'Exported': define type in a generated header file
      % 'Imported': import type definition from specified header file
      % If you do not define this method, DataScope is 'Auto' by default.
      retVal = 'Imported';
    end

Вместо того, чтобы задать тип в model_types.h, который является поведением по умолчанию, сгенерированный код импортирует определение из заданного заголовочного файла с помощью #include оператор как:

#include "imported_enum_type.h"

Генерация кода не создает импортированный заголовочный файл. Необходимо обеспечить заголовочный файл, с помощью имени файла, заданного методом getHeaderFile, это задает перечислимый тип данных.

Чтобы создать перечисление Simulink, которое соответствует вашему существующему перечислению кода С, используйте Simulink.importExternalCTypes функция.

Экспортируйте определение типа в сгенерированном коде

Чтобы сгенерировать отдельный заголовочный файл, который задает перечислимый тип данных, включайте эти методы в methods(Static) раздел класса перечисления:

    function retVal = getDataScope()
      % GETDATASCOPE Specifies whether generated code imports or exports this type.
      % Return one of:
      % 'Auto':     define type in model_types.h, or import if header file specified
      % 'Exported': define type in a generated header file
      % 'Imported': import type definition from specified header file
      % If you do not define this method, DataScope is 'Auto' by default.
      retVal = 'Exported';
    end

    function retVal = getHeaderFile()
      % GETHEADERFILE Specifies the file that defines this type in generated code.
      % The method getDataScope determines the significance of the specified file.
      retVal = 'exported_enum_type.h';
    end

Сгенерированный код экспортирует определение перечислимого типа сгенерированному заголовочному файлу exported_enum_type.h.

Добавьте префиксы в имена классов

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

    function retVal = addClassNameToEnumNames()
      % ADDCLASSNAMETOENUMNAMES Specifies whether to add the class name
      % as a prefix to enumeration member names in generated code.
      % Return true or false.
      % If you do not define this method, no prefix is added.
      retVal = true;
    end

Задайте возвращаемое значение как true включить добавление префикса имени класса или как false подавить добавление префикса. Если вы задаете true, каждое перечисляемое значение в классе появляется в сгенерированном коде как EnumTypeName_EnumName. Для класса перечисления в качестве примера BasicColors в Перечислимых Типах данных может выглядеть так определение типов в сгенерированном коде:

#ifndef _DEFINED_TYPEDEF_FOR_BasicColors_
#define _DEFINED_TYPEDEF_FOR_BasicColors_

typedef enum {
  BasicColors_Red = 0,            /* Default value */
  BasicColors_Yellow = 1,
  BasicColors_Blue = 2,
} BasicColors;

#endif

Имя класса перечисления BasicColors появляется как префикс для каждого из перечислимых имен.

Управляйте использованием дублирующихся имен элемента перечисления

Когда вы импортируете данные о перечислении от заголовочного файла, можно управлять использованием дублирующихся имен элемента перечисления во время генерации кода. Дублирующиеся имена элемента перечисления улучшают удобочитаемость кода. Используйте параметр конфигурации модели Duplicate enumeration member names, чтобы позволить дублирующиеся имена элемента перечисления в различных перечисляемых типах во время генерации кода или сгенерировать ошибку или предупреждающее сообщение. Можно использовать дублирующиеся имена элемента перечисления, только если два перечисления имеют тот же StorageType и имейте эти технические требования:

  • DataScope установите на 'Imported'

  • StorageType установите на 'int8'int16int32uint8, или 'uint16'

  • Value то же самое

Например:

typedef int32_T enum {
  Red = 0,
  Yellow = 1,
  Blue = 2,
}A;

typedef int32_T enum {
  Black = 0,
  Yellow = 1,
  White = 2,
}B;
У вас может быть Yellow член перечисления в перечислении A и B не снабжая префиксом имя элемента имя класса, чтобы улучшить удобочитаемость вашего кода.

Управляйте реализацией перечислимого типа в сгенерированном коде

Предположим, что вы задаете перечислимый тип BasicColors. Можно указать, что сгенерированный код реализует определение типа при помощи:

  • enum блок. Нативный целочисленный тип вашего оборудования является базовым целочисленным типом для членов перечисления.

  • typedef оператор и серия #define макросы. typedef оператор основывает имя перечислимого типа на определенном целочисленном типе данных, таком как int8. Партнер макросов члены перечисления с базовыми целочисленными значениями.

Реализуйте перечислимый тип при помощи enum Блок

Реализовывать определение типа при помощи enum блок:

  • В Simulink задайте перечислимый тип при помощи classdef блокируйтесь в файле скрипта. Выведите перечисление из типа Simulink.IntEnumType.

  • В качестве альтернативы используйте функциональный Simulink.defineIntEnumType. Не задавайте свойство StorageType.

Когда вы генерируете код, определение типа появляется в enum блок.

#ifndef _DEFINED_TYPEDEF_FOR_BasicColors_
#define _DEFINED_TYPEDEF_FOR_BasicColors_

typedef enum {
  Red = 0,            /* Default value */
  Yellow,
  Blue,
} BasicColors;

#endif

Реализуйте перечислимый тип Используя определенный целочисленный тип

Реализовывать определение типа с помощью typedef оператор и #define макросы:

  • В Simulink задайте перечислимый тип с помощью classdef блокируйтесь в файле скрипта. Выведите перечисление из определенного целочисленного типа, такого как int8.

  • В качестве альтернативы используйте функциональный Simulink.defineIntEnumType. Задайте свойство StorageType использование определенного целочисленного типа, такого как int8.

Когда вы генерируете код, определение типа появляется как typedef оператор и серия #define макросы.

#ifndef _DEFINED_TYPEDEF_FOR_BasicColors_
#define _DEFINED_TYPEDEF_FOR_BasicColors_

typedef int8_T BasicColors;

#define Red ((BasicColors)0)            /* Default value */
#define Yellow ((BasicColors)1)
#define Blue ((BasicColors)2)

#endif

По умолчанию, сгенерированный файл model_types.h содержит определения перечислимого типа.

Преобразование типа для перечислений

Безопасный кастинг

Блок Simulink Data Type Conversion принимает сигнал целочисленного типа. Блок преобразует вход в одно из базовых значений перечислимого типа.

Если входное значение не совпадает с базовым значением значения перечислимого типа, Simulink вводит безопасный бросок, чтобы заменить входное значение на значение по умолчанию перечислимого типа.

Включите и отключите безопасный кастинг

Можно включить или отключить безопасный кастинг для перечислений во время генерации кода для блока Simulink Data Type Conversion или блока Stateflow.

Чтобы управлять безопасным кастингом, включите или отключите параметры блоков Saturate on integer overflow. Параметр работает можно следующим образом:

  • Enabled: Simulink заменяет не соответствующее входное значение на значение по умолчанию перечисляемых значений в процессе моделирования. Программное обеспечение генерирует безопасную функцию броска во время генерации кода.

  • Disabled: Для не соответствующего входного значения, Simulink генерирует ошибку в процессе моделирования. Программное обеспечение не использует безопасную функцию броска во время генерации кода. В этом случае код более эффективен. Однако код может быть более уязвим для ошибок времени выполнения.

Безопасная функция броска в сгенерированном коде

В этом примере показано, как безопасный бросок функционирует int32_T ET08_safe_cast_to_BasicColors для перечисления BasicColors появляется в сгенерированном коде, когда сгенерировано для 32-битного оборудования.

static int32_T ET08_safe_cast_to_BasicColors(int32_T input)
{
	int32_T output;
	/* Initialize output value to default value for BasicColors (Red) */
	output = 0;
	if ((input >= 0) && (input <= 2)) {
	/* Set output value to input value if it is a member of BasicColors */
		output = input;
	}
	return output;
}
Через эту функцию используется значение по умолчанию перечислимого типа, если входное значение не совпадает с одним из базовых значений значений перечислимого типа.

Если параметр Saturate on integer overflow блока отключен, эта функция не появляется в сгенерированном коде.

Ограничения перечислимого типа

  • Сгенерированный код не поддерживает перечисленные данные регистрации.

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

| |

Похожие темы