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

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

Перечислимые данные являются данными, которые ограничиваются конечным множеством значений. Перечислимый тип данных является классом 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 появляется как префикс для каждого из перечислимых имен.

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

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

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

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

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

| |

Похожие темы