Вызов и интеграция внешних алгоритмов C в Simulink

Можно вызвать и интегрировать внешний код С в 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 блоки, чтобы вычислить сумму и среднее значение входов.

Запись файлов внешнего исходного кода

Начните с создания внешних исходных файлов.

  1. Создайте заголовочный файл с именем 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);

  2. В той же папке создайте новый файл, 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;
    }

Введите внешний код в Simulink

  1. Создайте новую, пустую модель и добавьте блок C Function. Блок C Function находится в User-Defined Functions библиотеке браузера библиотек.

  2. Дважды кликните C Function блок, чтобы открыть диалоговое окно блока. Щелкните, чтобы открыть диалоговое окно Configuration Parameters. На панели Simulation Target определите файл заголовка в разделе Insert custom C code in generated: > Header file.

  3. Определите исходный файл по пути 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, чтобы закрыть параметры конфигурации.

  4. На панели 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 панелях.

  5. Используйте таблицу 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 теперь имеет один входной порт и два выходных порта с метками, указанными в таблице.

  6. Добавьте блок Constant к холсту Simulink, который будет входом к блоку C Function. В блоке Constant создайте массив случайных строк со 100 элементами. Чтобы отобразить результаты, присоедините блоки отображения к выходам блока C Function.

Вызов функций библиотеки C из блока C Function

Можно вызвать это подмножество функций C Math Library из блока C Function:

absacosasinatanatan2ceil
coscoshexpfabsfloorfmod
labsldexploglog10powsin
sinhsqrttantanh  

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

См. также

Функции

Объекты

Блоки