Функциональные блоки Simulink обеспечивают механизм генерации кода C or C++ для компонентов моделирования, которые представляют общие ресурсы. Вы определяете логику как ресурс в блоке Simulink Function, который отделяет интерфейс функции (имя и аргументы) от реализации логики. Функциональные вызывающие абоненты (блоки Function Caller, блоки MATLAB Function и Stateflow® графики) может затем повторно использовать логику функции на разных уровнях иерархии модели.
Функциональные блоки Simulink обеспечивают альтернативу переиспользуемым подсистемам. Для примера фактора использования блока Simulink Function вместо блока подсистемы состоит в том, что блок Simulink Function разделяет состояния между вызывающими функциями. Генератор кода производит одну функцию. Если блок Simulink Function содержит блоки, которые имеют состояния, такие как задержка или память, состояния, постоянные между вызывающими функциями. Порядок вызовов функций является важным фактором.
Переиспользуемые функции, которые генерирует генератор кода из подсистем, не разделяют состояния. Генератор кода производит одну функцию для нескольких образцов подсистемы как оптимизацию. Если эта подсистема содержит блоки, которые имеют состояния, генератор кода производит одну функцию, но передает другую переменную состояния каждому образцу. Состояния образцов не разделяются.
Другие способы использования функциональных блоков Simulink и вызывающих абонентов:
Вложение вызовов в функцию.
Вызов функции, определенной в одном компоненте моделирования, из другого компонента моделирования.
Генерация функций, которые являются глобально доступными или ограниченными по объему.
Создание кода для клиентского и серверного приложения.
Выберите, как реализовать Simulink® функции и вызывающие абоненты на основе ваших требований к генерации кода. Факторы включают в себя:
Как вы представляете функцию и функции вызывающих абонентов в модели
Область видимости функции
Экспортировать ли функцию из модели (требует Embedded Coder®)
Индивидуальные настройки интерфейса кода функции (требует Embedded Coder)
Требования к генерации кода
Ограничения генерации кода
Эта таблица показывает Код С для функции, которая умножает вход значение на два, и блока Simulink Function, который может представлять эту функцию в модели Simulink.
Определение функции | Элемент моделирования |
---|---|
#include "timestwo_sf.h" #include "ex_slfunc_comp_sf.h" #include "ex_slfunc_comp_sf_private.h" void timestwo_sf(real_T rtu_x, real_T *rty_y) { *rty_y = 2.0 * rtu_x; } |
Функциональный блок Simulink |
Вызывающий абонент функции Simulink вызывает функцию, заданную блоком Simulink Function. Из любого места в иерархии модели или графика можно вызвать функцию, заданную блоком Simulink Function, используя один из следующих элементов моделирования:
Вызов функции | Элемент моделирования |
---|---|
void ex_slfunc_comp_sf_step(void) { real_T rtb_FunctionCaller1; timestwo_sf(ex_slfunc_comp_sf_U.In1, &rtb_FunctionCaller1); ex_slfunc_comp_sf_Y.Out1 = rtb_FunctionCaller1; . . . |
Блок вызывающего абонента функции |
void ex_slfunc_comp_gf_step(void) { real_T rtb_y1_l; timestwo_gf(ex_slfunc_comp_gf_U.In4, &rtb_y1_l); ex_slfunc_comp_gf_Y.Out4 = rtb_y1_l; . . . |
Переход на диаграмму Stateflow |
void ex_slfunc_comp_mf_step(void) { real_T rtb_y; timestwo_mf(ex_slfunc_comp_mf_U.In3, &rtb_y); ex_slfunc_comp_mf_Y.Out3 = rtb_y; . . . |
Блок MATLAB function |
Для получения дополнительной информации о вариантах моделирования смотрите Обзор функций Simulink.
Функция, которую вы задаете с блоком Simulink Function, может быть глобальной или масштабированной.
Global --- Генератор кода помещает код для глобальной функции в исходные и заголовочные файлы, которые отделены от файлов кода модели (для примера,
и function
.c
) . Отдельные файлы делают код функции доступным для совместного использования между вызывающими абонентами функции. function
.h
Scoped --- Генератор кода помещает код для функции scoped в файлы кода модели (
и model
.c
). Чтобы вызвать функцию scoped в контексте модели, вызывающий функцию должен быть на том же уровне, что и функция в иерархии модели, или на одном или нескольких уровнях ниже.model
.h
Чтобы создать библиотеку функций, которые доступны из любого места сгенерированного кода модели, настройте каждую функцию как масштабированный блок Simulink Function. Поместите каждую ограниченную функцию в виртуальную подсистему на корневом уровне модели.
Для получения дополнительной информации см., и Обзор масштабированных и глобальных функциональных блоков Simulink.
Несмотря на то, что вы можете использовать блоки Simulink Function в одном проекте верхней модели, код функции более многоразовый, когда вы генерируете его как автономные, атомарные компоненты. Вы делаете это, проектируя функции в контексте моделей экспорта функций.
Для получения дополнительной информации смотрите Сгенерировать исходный код компонента для экспорта во внешнюю основу кода (Embedded Coder) и Обзор моделей экспорта функций.
С помощью Embedded Coder упростите интегрирование сгенерированного кода с внешним кодом, настроив сгенерированные интерфейсы кода функции для блоков Simulink Function и Function Caller. Можно настроить интерфейсы функций для:
Глобальные функциональные блоки Simulink
Масштабные функциональные блоки Simulink, которые находятся на корневом уровне модели
Для получения дополнительной информации смотрите Configure Entry-Point Function Interfaces for Simulink Function and Function Caller Blocks (Embedded Coder).
Если вы используете блок Simulink Function в модели на основе скорости и не вызываете эту функцию, генератор кода рассматривает блок Simulink Function как константу и не производит код функции. Для примера это может произойти во время разработки модели, когда вы готовы задать функцию, но не готовы идентифицировать вызывающего абонента.
Чтобы идентифицировать такие блоки в модели на основе скорости, отобразите шаг расчета цвета во время симуляции. По умолчанию блоки Constant появляются пурпурно. Поскольку генератор кода рассматривает незакрытые Simulink Function блокирует константы во время симуляции, они кажутся пурпурными.
В рамках иерархии модели имена функции являются уникальными. Если генератор кода находит несколько функций с таким же именем, это вызывает ошибку. Измените имя одной из функций и удалите slprj
папка.
Подпись (для примера, аргументы и типы данных аргументов) для вызывающих абонентов функций и функций должна совпадать.
Если генератор кода сначала находит функцию, и сигнатура вызывающего абонента функции не совпадает, генератор кода выдает ошибку. Измените сигнатуру вызывающего абонента функции так, чтобы она совпадала с сигнатурой блока Simulink Function или удалите slprj
папка.
Если генератор кода сначала находит вызывающего функцию абонента, и сигнатура функции не совпадает, генератор кода выдает предупреждающее сообщение. Измените сигнатуру вызывающего абонента функции или функции так, чтобы сигнатуры совпадали.
В определении блока Simulink Function не задайте входные и выходные сигналы для блоков Argument Inport и Argument Outport с классом памяти.
Не указывайте блоки Inport аргумента и Outport аргумента в качестве тестовых точек.
Если вы задаете тип данных входов и выходных сигналов для блоков Аргумента Inport и Аргумент Outport как Simulink.IntEnumType
, Simulink.AliasType
, или Simulink.Bus
, установите DataScope
свойство к Imported
или Exported
.
Интерфейс функции и вызывающие абоненты функции должны соответствовать типу данных, сложности, размерности и количеству аргументов.
Чтобы сгенерировать код из модели, которая включает ограниченные функции Simulink, модель должна быть моделью экспорта функций. Генератор кода не поддерживает основанные на скорости модели, которые включают ограниченные функции Simulink.
Можно использовать блок Simulink Function, чтобы задать область видимости функции в модели-ссылке. Однако вы не можете сгенерировать код для модели экспорта функций, которая использует блок Function Caller в атомарной подсистеме, чтобы вызвать эту функцию.
Можно вызвать функцию C++, которую генератор кода производит из блока Simulink Function с кодом, сгенерированным из диаграммы Stateflow. Из-за текущих ограничений возможностей для сгенерированных функций C++, вы должны вызвать эти функции с кодом, сгенерированным из блока Function Caller.
Функции Simulink и вызывающие абоненты не выполняют MaxStackSize
параметр.
Генерация кода для интерфейса класса C++ поддерживает только ограниченные области функций Simulink.
В этом примере показано, как использовать блоки Simulink Function и Function Caller для генерации кода переиспользуемой функции. Генератор кода производит глобальную функцию, которая соответствует требованиям кода, так что существующий внешний код может вызвать функцию и локальную функцию. Генератор кода также производит вызовы глобальных и локальных функций. Вызов глобальной функции показывает, что глобальная функция используется повторно (совместно используется).
Требования к коду для глобальной функции:
Имена функции начинаются с префикса func_
.
Имена входных аргументов имеют вид x
, где n
n
является уникальным целым значением.
Имена выходных аргументов имеют вид y
, где n
n
является уникальным целым значением.
Входные и выходные аргументы являются целыми числами (int
) и передаются по ссылке. Размер собственного целого числа целевого компьютера составляет 32 бита.
Вы создаете функцию, которая вызывает сгенерированный код переиспользуемой функции. Затем вы создаете и конфигурируете модель, соответствующую требованиям кода.
Некоторые функции, используемые в этом примере, такие как псевдонимизация и замена типов данных, требуют программного обеспечения Embedded Coder.
В корневой папке генерации кода создайте файлы call_times2.h
и call_times2.c
. Если вы предпочитаете, можно скопировать файлы из matlabroot\help\toolbox\ecoder\examples
.
call_times2.h
typedef int my_int;
call_times2.c
#include "call_times2.h" void call_times2(void) { int times2result; func_times2(x1, &y1); printf('Times 2 Value:', y1); }
Этот код С вызывает переиспользуемую функцию func_times2
. Функция умножает целочисленное входное значение x1
на 2 и возвращает результат следующим y1
.
Откройте пример модели ex_slfunc_comp
, который доступен в папке matlabroot\help\toolbox\ecoder\examples
. Модель включает две функции Simulink, смоделированные как блоки Simulink Function, func_times2
и func_times3
и вызов каждой функции. Как указано в модели, видимость блока Simulink Function для func_times2
установлено в global
. Эта настройка видимости делает код функции доступным для другого кода, включая внешний код, который вы хотите интегрировать с сгенерированным кодом. Видимость для func_times3
установлено в scoped
.
Если вы конфигурируете модель с системным целевым файлом GRT или с системным целевым файлом ERT, File packaging format установлено на Modular
генератор кода производит код функции для модели.
Для получения дополнительной информации смотрите Сгенерировать код для функции Simulink и вызывающего абонента функции.
Пример принимает, что сгенерированный код запускается на целевом компьютере с собственным целым числом 32 бита. Внешний код представляет целые числа с типом данных my_int
, который является псевдонимом int
. Сконфигурируйте генератор кода, чтобы использовать my_int
вместо типа данных, используемого генератором кода по умолчанию, который является int32_T
.
Создайте объект Simulink .AliasType, чтобы представлять пользовательский тип данных my_int
.
my_int = Simulink.AliasType my_int = AliasType with properties: Description: '' DataScope: 'Auto' HeaderFile: '' BaseType: 'double'
Установите свойства типа псевдонима. Введите описание, установите возможности равной Imported
, укажите заголовочный файл, который включает определение типа и связать тип псевдонима с базовым типом Simulink int32
.
my_int.Description='Custom 32-bit int representation'; my_int.DataScope='Imported'; my_int.HeaderFile='call_times2.h'; my_int.BaseType='int32'; my_int AliasType with properties: Description: 'Custom 32-bit int representation' DataScope: 'Imported' HeaderFile: 'call_times2.h' BaseType: 'int32'
Сконфигурируйте генератор кода, чтобы заменить образцы типа int32_T
с my_int
. В диалоговом окне Параметров конфигурации откройте панель Code Generation Data Type Replacement .
Выберите Replace data type names in the generated code.
В таблице Data type names введите my_int
для имени замены для int32
.
Чтобы внешний код вызывал глобальную функцию, сконфигурируйте соответствующий блок Simulink Function с глобальной видимостью и интерфейсом, который соответствует ожидаемому внешними вызывающими абонентами.
Откройте блок, который представляет times2
функция.
Сконфигурируйте имя функции и видимость путем установки Trigger Port параметров блоков. Например, требования к коду определяют, что имя функции начинается с префикса func_
.
Установите Function name равными func_times2
.
Установите Function visibility значение global
.
Сконфигурируйте входной параметр функции и выходные аргументы путем установки параметров Argument Inport и Argument Outport параметров блоков. Например, требования к коду определяют, что имена аргумента имеют форму x
и n
y
. Требования также определяют, что аргументы должны быть типами n
my_int
.
На вкладке Main установите Argument name равным x1
(вход) и y1
(выход).
На вкладке Signal Attributes установите Data type равным int32
. С указанной ранее заменой типа данных int32
появляется в сгенерированном коде следующим myint
.
Сконфигурируйте интерфейс блочного кода Simulink Function. На верхнем уровне модели щелкните правой кнопкой мыши блок, представляющий глобальную функцию func_times2
. В контекстном меню выберите C/C++ Code Configure C/C++ Function Interface.
Установите C/C++ function name значение func_times2
.
Установите C/C++ return argument значение void
.
Установите C/C++ Identifier Name для аргумента x1
на x1
.
Установите C/C++ Identifier Name для аргумента y1
на y1
.
Если в диалоговом окне перечислен выходной аргумент y1
перед входным параметром x1
, переупорядочить аргументы путем перетаскивания строки для x1
над строкой для y1
.
Сконфигурируйте блок Simulink Function, который представляет локальную функцию с ограниченной видимостью. Исходя из требований к коду, вы, возможно, также должны будете сконфигурировать имя функции, имена и типы входных и выходных аргументов, а также функциональный интерфейс.
Откройте блок, который представляет times3
функция.
Сконфигурируйте имя функции и видимость путем установки Trigger Port параметров блоков. Например, требования к коду определяют, что имя функции начинается с префикса func_
.
Установите Function name равными func_times3
.
Установите Function visibility значение scoped
.
Сконфигурируйте входной параметр функции и выходные аргументы путем установки параметров Argument Inport и Argument Outport параметров блоков. Например, требования к коду определяют, что имена аргумента имеют форму x
и n
y
. Требования также определяют, что аргументы должны быть типами n
my_int
.
На вкладке Main установите Argument name равным x1
(вход) и y1
(выход).
На вкладке Signal Attributes установите Data type равным int32
. С указанной ранее заменой типа данных int32
появляется в сгенерированном коде следующим my_int
.
Сконфигурируйте интерфейс блочного кода Simulink Function. На верхнем уровне модели щелкните правой кнопкой мыши по функции scoped func_times3
. В меню выберите C/C++ Code Configure C/C++ Function Interface. В этом случае генератор кода управляет именованием функции и аргументов. Имя функции объединяет имя корневой модели и имя функции, которое вы задаете для порта триггера блока Simulink Function. В этом примере имя являетсяex_slfunc_comp_func_times3
.
Можно задать C/C++ return argument имя аргумента, заданное для блока Argument Outport или void
. В данном примере установите для него значение void
.
Для аргументов генератор кода готовится rtu_
(вход) или rty_
(выход) в имя аргумента, заданное для блока Argument Inport.
Если в диалоговом окне перечислен выходной аргумент y1
перед входным параметром x1
, переупорядочить аргументы путем перетаскивания строки для x1
над строкой для y1
.
Для каждого вызывающего абонента функции сконфигурируйте параметры блоков Function Caller:
Установите Function prototype значение y1 = func_times2(x1)
.
Установите Input argument specifications значение int32(1)
.
Установите Output argument specifications значение int32(1)
.
Сгенерируйте код для модели.
Глобальный код функции
Исходный код для глобальной, переиспользуемой функции func_times2
находится в папке сборки в файле подсистемы, func_times2.c
.
#include "func_times2.h" /* Include model header file for global data */ #include "ex_slfunc_comp.h" #include "ex_slfunc_comp_private.h" void func_times2(my_int x1, my_int *y1) { *y1 = x1 << 1; }
Код локальной функции
Генератор кода помещает определение для локальной (scoped) функции func_times3
в папке сборки файлов в ex_slfunc_comp.c
файлов.
void ex_slfunc_comp_func_times3(my_int rtu_x1, my_int *rty_y1) { *rty_y1 = 3 * rtu_x1; }
Вызовы сгенерированных функций
Функция выполнения модели (шаг) в файле модели ex_slfunc_comp.c
, вызывает две функции Simulink: глобальную функцию func_times2
и локальная функция ex_slfunc_comp_func_times3
. Имя ex_slfunc_comp_func_times3
отражает возможности локальной функции путем объединения имени модели и имени функции.
void ex_slfunc_comp_step(void) { my_int rtb_FunctionCaller2; func_times2(ex_slfunc_comp_U.In1, &rtb_FunctionCaller2); ex_slfunc_comp_Y.Out1 = rtb_FunctionCaller2; ex_slfunc_comp_func_times3(ex_slfunc_comp_U.In2, &rtb_FunctionCaller2); ex_slfunc_comp_Y.Out2 = rtb_functionCaller2; . . .
Объявление точки входа для локальной функции
Файл заголовка модели ex_slfunc_comp.h
включает в себя extern
объявление для ex_slfunc_comp_func_times3 функции
. Этот оператор объявляет точку входа функции.
extern void ex_slfunc_comp_func_times3(my_int rtu_x1, my_int *rty_y1);
Включите операторы для глобальной функции
Файл заголовка модели ex_slfunc_comp.h
списки включают операторы для глобальной функцииfunc_times2
.
#include "func_times2_private.h" #include "func_times2.h"
Локальные макросы и данные для глобальной функции
Файл заголовка подсистемы func_times2_private.h
задает макросы и включает заголовочные файлы, которые объявляют данные и функции для глобальной функции, func_times2
.
#ifndef RTW_HEADER_func_times2_private_h_ #define RTW_HEADER_func_times2_private_h_ #ifndef ex_slfunc_comp_COMMON_INCLUDES_ #define ex_slfunc_comp_COMMON_INCLUDES_ #include "rtwtypes.h" #endif #endif
Объявление точки входа для глобальной функции
Общий заголовочный файл func_times2.h
, в общей папке утилит slprj/
, списки общих типов включают для stf
/ _sharedutilsrtwtypes.h
. Файл также включает extern
объявление для глобальной функции, func_times2
. Этот оператор объявляет точку входа функции.
#ifndef RTW_HEADER_func_times2_ #define RTW_HEADER_func_times2_ #include "rtwtypes.h" extern void func_times2(my_int rtu_x1, my_int *rty_y1); #endif
В этом примере показано, как сгенерировать код С для блоков Simulink Function и Function Caller, и отображается соответствующий сгенерированный код.
Откройте пример модели rtwdemo_export_functions
. Модель использует программное обеспечение Stateflow, но в этом примере рассматривается только код, сгенерированный из ссылочных моделей.
Чтобы просмотреть содержимое подсистемы, дважды кликните мышью rtwdemo_functions
. Блок Simulink Function является f3
подсистема, определяемая как y = f3(u)
.
Сгенерируйте код.
Генератор кода создает rtwdemo_functions.c
. Этот файл содержит определение функции и код инициализации функции.
Код инициализации для функции f3
:
void f3_Init(void) { rtDWork.Delay_DSTATE = 1; }
Код для функции f3
:
void f3(real_T rtu_u, real_T *rty_y) { rtY.TicToc10 = rtDWork.Delay_DSTATE; rtDWork.Delay_DSTATE = (int8_T)(int32_T)-(int32_T)rtY.TicToc10; adder_h(rtB.Subtract, rtU.U2, rtu_u, rtB.FunctionCaller); *rty_y = rtB.FunctionCaller; } void adder_h(real_T rtu_u1, real_T rtu_u2, real_T rtu_u3, real_T *rty_y) { *rty_y = (rtu_u1 + rtu_u2) + rtu_u3; }
Общий заголовочный файл f3.h
содержит объявление точки входа для функции f3
.
#include "rtwtypes.h" extern void f3(real_T rtu_u, real_T *rty_y);
В rtwdemo_export_functions
модель, дважды кликните rtwdemo_caller
для просмотра содержимого подсистемы вызывающего абонента.
Сгенерируйте код.
Генератор кода создает файлы rtwdemo_caller.h
и rtwdemo_caller.c
в папке rtwdemo_caller_ert_rtw
.
rtwdemo_caller.h
включает общий заголовочный файл, f3.h
, который содержит объявление точки входа функции.
rtwdemo_caller.c
вызывает функцию f3
.
void rtwdemo_caller_t_10tic(const real_T *rtu_u, real_T *rty_y) { f3(*rtu_u, rty_y); }