Можно вызвать и интегрировать внешний код С в Simulink® моделирует, используя блоки C Function. C Function блоки позволяют вам вызвать внешний код C и настроить интегрирование кода с помощью панелей Output Code, Start Code и Terminate Code в диалоговом окне параметров блоков. Используйте C Function блок для:
Вызовите функции из внешнего кода С и настройте код для ваших моделей Simulink.
Предварительная обработка данных для вызова функции C и постпроцессная обработка данных после вызова функции.
Задайте другой код для симуляции и генерации кода.
Вызовите несколько функций.
Инициализируйте и работайте с постоянными данными, кэшированными в блоке.
Выделите и отключите память.
Используйте блок C Function, чтобы вызвать внешние алгоритмы C в Simulink, который вы хотите изменить. Чтобы вызвать одну функцию C из модели Simulink, используйте блок C Caller. Чтобы интегрировать динамические системы, которые имеют непрерывные состояния или изменения состояния, используйте блок S-Function.
Следующие примеры используют C Function блоки, чтобы вычислить сумму и среднее значение входов.
Начните с создания внешних исходных файлов.
Создайте заголовочный файл с именем data_array.h
.
/* Define a struct called DataArray */ typedef struct DataArray_tag { /* Define a pointer called pData */ double* pData; /* Define the variable length */ int length; } DataArray; /* Function declaration */ double data_sum(DataArray data);
В той же папке создайте новый файл, data_array.c
. В этом файле запишите функцию C, которая вычисляет сумму входа чисел.
#include "data_array.h" /* Define a function that takes in a struct */ double data_sum(DataArray data) { /* Define 2 local variables to use in the function */ double sum = 0.0; int i; /* Calculate the sum of values */ for (i = 0; i < data.length; i++) { sum = sum + data.pData[i]; } /* Return the result to the block */ return sum; }
Создайте новую, пустую модель и добавьте блок C Function. Блок C Function находится в User-Defined Functions библиотеке браузера библиотек.
Дважды кликните C Function блок, чтобы открыть диалоговое окно блока. Щелкните, чтобы открыть диалоговое окно Configuration Parameters. На панели Simulation Target определите файл заголовка в разделе Insert custom C code in generated: > Header file.
Определите исходный файл по пути Additional build information > Source files.
Примечание
Чтобы использовать блок C Function в подсистеме For Each или с непрерывным шагом расчета, или чтобы оптимизировать использование блока в выполнении условной входной ветви, все пользовательские функции кода, вызываемые блоком, должны быть детерминированными, то есть всегда производящими одни и те же выходы для тех же входов. Определите, какие пользовательские функции кода являются детерминированными с помощью параметров Deterministic functions и Specify by function на панели Simulation target. Если блок ссылается на любые пользовательские глобальные переменные кода, то Deterministic functions должны установить на All
для порядка блока в подсистеме For Each, в выполнении условной входной ветви или с непрерывным шагом расчета.
Для примера, показывающего блок C Function в Подсистеме For Each, смотрите Использование блока C Function В Каждой Подсистеме.
Щелкните OK, чтобы закрыть параметры конфигурации.
На панели Output Code диалогового окна параметров блоков C Function запишите код, который блок выполняет во время симуляции. В этом примере внешняя функция C вычисляет сумму. На панели Output Code напишите код, который вызывает data_array.c
функция для вычисления суммы, затем вычисляет среднее значение.
/* declare the struct dataArr */ DataArray dataArr; /* store the length and data coming in from the input port */ dataArr.pData = &data; dataArr.length = length; /* call the function from the external code to calculate sum */ sum = data_sum(dataArr); /* calculate the mean */ mean = sum / length;
Можно задать код, который запускается в начале симуляции и в конце симуляции в Start Code и Terminate Code панелях.
Используйте таблицу Symbols, чтобы определить символы, используемые во внешнем коде С Добавить или удалить символ можно с помощью кнопок Add и Delete. Задайте все символы, используемые в Output Code, Start Code и Terminate Code панелях, чтобы убедиться, что порты отображаются правильно.
В таблице Symbols задайте следующее.
Name - имя символа в исходном коде.
Scope - Возможности символов и порядок их появления. Вы можете изменить возможности символа в любое время.
Input
- Входной символ в блок C Function.
Output
- Выход символа в блок C Function.
InputOutput
- Задайте символ как вход и выход в блок C Function.
Используйте InputOutput
Возможности для отображения входа, проходящей мимо указателя мыши в вашем Коде С. Порты, созданные с использованием InputOutput
возможности видимости имеют то же имя для входных и выходных портов. InputOutput
возможности позволяет повторно использовать буфер для входных и выходных портов. Буфер повторного использования может оптимизировать использование памяти и улучшить симуляцию кода и эффективность генерации кода, в зависимости от размера сигнала и размещения блока. Ограничения включают:
InputOutput
символ не может использоваться в Start
и Terminate
код.
InputOutput
порт не поддерживает void*
тип данных.
InputOutput
порт не поддерживает size()
выражения.
Persistent
- Определите символ как постоянные данные.
Вы можете задать пустой указатель с помощью Persistent
возможности в блоке C Function. Пустой указатель - это указатель, который может хранить данные любого типа, которые вы создали или выделили.
Constant
- Определите символ как константу, используя размер значения или числовые выражения.
Parameter
- Задайте символ как параметр. Имя параметра определяется Label символа.
Label - Метка символа. Для символов с заданной возможностями Input
или Output
эта метка отображается как имя порта на блоке. Для символов с заданной возможностями Parameter
, эта метка является меткой, которая появляется в маске параметров блоков. Вы не можете задать метку для Persistent
символы. Если возможности Constant
, метка является постоянным выражением.
Type - Тип данных символа. Выберите тип данных из выпадающего списка или укажите пользовательский тип данных.
Как использовать пользовательский тип, такой как Simulink.Bus
, Simulink Enum или Simulink.AliasType
который не имеет определения внешнего заголовка, сопоставленного с блоком C Function, правильно установите тип в таблице Symbol.
Size - Размер данных о символе. Блок C Function поддерживает только скаляры, и поддерживаются векторы. Матрицы и массивы с более высоким измерением не поддерживаются. Для определения размера выхода можно использовать выражение size. Использование -1
чтобы наследовать размер.
Port - Для входных и выходных символов, Port
указывает индекс порта на блоке данных о символе. Для символов параметров, Port
указывает порядок отображения символа в маске параметров блоков.
Закройте диалоговое окно параметров блоков. После заполнения данных в таблице, блок C Function теперь имеет один входной порт и два выходных порта с метками, указанными в таблице.
Добавьте блок Constant к холсту Simulink, который будет входом к блоку C Function. В блоке Constant создайте массив случайных строк со 100 элементами. Чтобы отобразить результаты, присоедините блоки отображения к выходам блока C Function.
Можно вызвать это подмножество функций C Math Library из блока C Function:
abs | acos | asin | atan | atan2 | ceil |
cos | cosh | exp | fabs | floor | fmod |
labs | ldexp | log | log10 | pow | sin |
sinh | sqrt | tan | tanh |
При вызове этих функций применяется двойная точность, если все входные параметры не являются явно одинарной точностью. Когда происходит несоответствие типа, приведение входных параметров к ожидаемому типу заменяет исходные аргументы. Для примера, если вы вызываете sin
функция с целым аргументом, приведение входного параметра к числу с плавающей запятой типа double
заменяет исходный аргумент.
Если вы хотите вызвать другие функции библиотеки C, которые не перечислены выше, создайте функцию внешнего оболочки, которая вызывает функцию библиотеки C.
abs
, fabs
, и labs
ФункцияИнтерпретация abs
, fabs
, и labs
функции в C Function блоке выходят за пределы стандартной версии C и включают в себя целое число и аргументы с плавающей точкой:
Если x
является целым числом, стандартная функция C применяется к x
, или abs(x)
.
Если x
является двойной, стандартной функцией C labs
применяется к x
, или labs(x)
.
Если x
является одной, стандартной функцией C fabs
применяется к x
, или fabs(x)
.
Вызов функции должен вызывать правильный CRL на основе типа данных, переданных в функцию. Если CRL не задан, вызов функции должен вызвать библиотеку для конкретного типа. CRL для C99 генерирует функцию для конкретного типа. Для примера:
Тип передан в | Вызов генерации кода |
---|---|
sin(doubleIn) | sin(doubleIn) |
sin(floatIn) | sinf(floatIn) |
Можно задать другой выходной код для симуляции и генерации кода для блока C Function путем определения MATLAB_MEX_FILE
. Для примера, чтобы задать код, который запускается только во время симуляции модели, вы используете следующее.
#ifdef MATLAB_MEX_FILE /* Enter Sim Code */ #else /* Enter code generation code */ #endif
В целях генерации кода, если у вас нет внешнего файла заголовка с объявлением функции (такого как драйвер целевого устройства), который вы хотите вызвать из блока C Function, можно включить объявление с правильной подписью в панель Output Code блока. Это действие создает вызов функции к ожидаемой функции, когда код генерируется, как в следующем примере:
#ifndef MATLAB_MEX_FILE extern void driverFcnCall(int16_T in, int16_T * out); driverFcnCall(blockIn, &blockOut); #endif
При симуляции модели, содержащей пользовательский код C or C++, у вас есть опция запустить пользовательский код в отдельном процессе вне MATLAB®. Эта опция может быть полезной при отладке пользовательского кода. При запуске в отдельном процессе проблемы с пользовательским кодом не вызывают сбоя MATLAB, и можно легче отлаживать и устранять такие проблемы. Проблемы могут возникнуть из-за неожиданных исключений в пользовательском коде или ошибок в интерфейсе между Simulink и пользовательским кодом. Для получения дополнительной информации смотрите Моделирование пользовательского кода в отдельном процессе.