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

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

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

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

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

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

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

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

  • Уменьшите использование ОЗУ/ПЗУ.

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

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

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

  • 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, относится как к симуляции, так и к генерации кода и описывается в разделе Задать перечисляемое значение по умолчанию. Другие методы относятся только к генерации кода. Чтобы настроить поведение перечисляемого типа, включите версию метода в methods(Static) раздел определения класса перечисления. Если вы не хотите настраивать тип, опускайте methods(Static) раздел. В таблице обобщены методы и данные, которые будут предоставлены для каждого из них.

Статический методЦельЗначение по умолчанию без реализации методаНастраиваемое значение возврата
getDefaultValueЗадает представителя перечисления по умолчанию для класса.Первый представитель, заданный в определении перечисленияВектор символов, содержащий имя представителя перечисления в классе (см. «Создание перечислений»).
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', 'int16', 'int32', 'uint8', или '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 блок. Собственный целый тип вашего оборудования является базовым целым типом для представителей перечисления.

  • A typedef оператор и ряд #define макросы. The 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 параметр блока отключен, эта функция не отображается в сгенерированном коде.

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

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

См. также

| |

Похожие темы