Взаимодействие Simulink Engine с S-функциями C

Можно изучить, как Simulink® двигатель взаимодействует с S-функциями с двух точек зрения:

  • Перспектива процесса, то есть, в каких точках симуляции двигатель вызывает S-функцию.

  • Перспектива данных, т.е. как механизм и S-функция обмениваются информацией во время симуляции.

Представление процесса

Следующие рисунки показывают порядок, в котором механизм Simulink вызывает методы коллбэка в S-функции. Твердые прямоугольники указывают коллбэки, которые всегда происходят во время инициализации модели или на каждом временном шаге. Пунктирные прямоугольники указывают коллбэки, которые могут происходить во время инициализации и/или в некоторые или все временные шаги во время цикла симуляции. Смотрите документацию для каждого метода коллбэка, чтобы определить точные обстоятельства, при которых механизм вызывает коллбэк.

Примечание

Схема представления процесса представляет выполнение S-функций, которые содержат непрерывные и дискретные состояния, включают обнаружение пересечения нулем и проживают в модели, которая использует решатель с переменным шагом. Другие решатели опускают определенные шаги в схеме. Для лучшего понимания того, как механизм Simulink выполняет вашу конкретную S-функцию, запустите модель, содержащую S-функцию, используя отладчик Simulink. Для получения дополнительной информации смотрите Введение в отладчик.

В следующем цикле инициализации модели механизм Simulink конфигурирует S-функцию для предстоящей симуляции. Двигатель всегда выполняет необходимые вызовы для mdlInitializeSizes и mdlInitializeSampleTime для настройки основных атрибутов S-функции, включая входные и выходные порты, параметры диалога S-функции, рабочие векторы, шаги расчета и т.д.

Двигатель вызывает дополнительные методы, по мере необходимости, чтобы завершить инициализацию S-функции. Например, если S-функция использует рабочие векторы, механизм вызывает mdlSetWorkWidths. Кроме того, если mdlInitializeSizes метод отложил настройку атрибутов входного и выходного портов, механизм вызывает любые методы, необходимые для завершения инициализации порта, такие как mdlSetInputPortWidth, во время распространения сигнала. The mdlStart метод вызывает mdlCheckParameters и mdlProcessParameters методы, если S-функция использует диалоговые параметры.

Примечание

The mdlInitializeSizes метод коллбэка также запускается, когда вы вводите имя скомпилированной S-функции в диалоговое окно Блок S-function Parameters.

После инициализации механизм Simulink выполняет следующий цикл симуляции. Если цикл симуляции прерывается, либо вручную, либо когда возникает ошибка, двигатель перескакивает непосредственно к mdlTerminate способ. Если симуляция была остановлена вручную, двигатель сначала завершает текущий временной шаг перед вызовом mdlTerminate.

Если ваша модель содержит несколько блоков S-Function на заданном уровне иерархии модели, механизм вызывает конкретный метод для каждой S-функции, прежде чем переходить к следующему методу. Например, двигатель вызывает все mdlInitializeSizes методы перед вызовом любого mdlInitializeSampleTimes методы. Механизм использует блок отсортированный порядок, чтобы определить порядок выполнения S-функций. Дополнительные сведения о том, как механизм определяет порядок выполнения блока, см. в разделе Управление и отображение порядка выполнения.

Структура вызова для генерации кода

Если вы используете продукт Simulink Coder™, чтобы сгенерировать код для модели, содержащей S-функции, механизм Simulink не выполняет целую последовательность вызовов, описанную выше. Инициализация выполняется так, как описано выше, пока двигатель не достигнет mdlStart способ. Затем двигатель вызывает методы S-функции, показанные на следующем рисунке, где mdlRTW метод уникален для продукта Simulink Coder.

Если S-функция находится в условно выполненной подсистеме, можно, чтобы сгенерированный код перемежал вызовы в mdlInitializeConditions и mdlStart. Рассмотрим следующую модель Simulink.

Модель содержит две невиртуальные подсистемы, условно выполненную включенную подсистему с именем Reset и атомарную подсистему с именем Atomic. Каждая подсистема содержит блок S-Function, который вызывает S-функцию dsfunc.c, который моделирует дискретную систему в пространстве состояний с двумя состояниями. Включенная подсистема Reset сбрасывает значения состояния, когда подсистема включена, и выходные значения, когда подсистема отключена.

Используя общую цель в реальном времени (GRT), сгенерированный код для всей модели Start функция вызывает Start функции двух подсистем перед вызовом общемодельных MdlInitialize функция, как показано на следующем коде:

void MdlStart(void)
{
  /* snip */

  /* Start for enabled SubSystem: '<Root>/Reset' */
  sfcndemo_enablesub_Reset_Start();

  /* end of Start for SubSystem: '<Root>/Reset' */

  /* Start for atomic SubSystem: '<Root>/Atomic' */
  sfcndemo_enablesub_Atomic_Start();

  /* end of Start for SubSystem: '<Root>/Atomic' */

MdlInitialize();

The Start функция для включенной подсистемы вызывает функцию InitializeConditions функция:

void sfcndemo_enablesub_Reset_Start(void)
{
   sfcndemo_enablesub_Reset_Init();
   /* snip */
}

The MdlInitialize функция, вызываемая в MdlStart, содержит вызов на InitializeConditions функция для атомарной подсистемы:

void MdlInitialize(void)
{
   /* InitializeConditions for atomic SubSystem: 
        '<Root>/Atomic' */

   sfcndemo_enablesub_Atomic_Init();
}

Поэтому во всей модели Start функция перемежает вызовы к Start и InitializeConditions функций для двух подсистем и S-функций, которые они содержат.

Для получения дополнительной информации о продукте Simulink Coder и о том, как он взаимодействует с S-функциями, смотрите S-Functions и Генерация Кода (Simulink Coder).

Альтернативная структура вызова для режима external mode

Когда вы запускаете модель Simulink во режиме external mode, последовательность вызовов для стандартных программ S-функций изменяется, как показано на следующем рисунке.

Механизм вызывает mdlRTW один раз, когда он входит во режим external mode и снова каждый раз, когда параметр изменяется или когда вы кликаете Update Model на вкладке Modeling.

Примечание

Выполнение модели Simulink во режиме external mode требует продукта Simulink Coder.

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

Блоки s-function имеют входные и выходные сигналы, параметры и внутренние состояния, плюс другие общие рабочие области. В целом, блочные входы и выходы записываются в вектор ввода-вывода блока и считываются с него. Входные параметры также могут исходить от

  • Внешние входы через корневые блоки Inport

  • Заземлите, если входной сигнал не соединен или заземлен

Выходы блоков могут также переходить к внешним выходам через корневые блоки Outport. В дополнение к входным и выходным сигналам S-функции могут иметь

  • Непрерывные состояния

  • Дискретные состояния

  • Другие рабочие области, такие как действительные, целое число или рабочие векторы

Можно параметризовать блоки s-function путем передачи им параметров с помощью диалогового окна Блок S-function Parameters.

Следующий рисунок показывает общее отображение между этими различными типами данных.

S-функции mdlInitializeSizes стандартная программа устанавливает размеры различных сигналов и векторов. Методы S-функции, вызываемые во время цикла симуляции, могут определять размеры и значения сигналов.

Метод S-функции может обращаться к входным сигналам двумя способами:

  • Через указатели

  • Использование смежных входов

Доступ к сигналам с помощью указателей

Во время цикла симуляции получайте доступ к входным сигналам, используя

InputRealPtrsType uPtrs = 
  ssGetInputPortRealSignalPtrs(S,portIndex)

Это возвращает массив указателей для порта входа с индексом portIndex, где portIndex начинается с 0. Для каждого входного порта существует по одному массиву указателей. Для доступа к элементу этого массива необходимо использовать

*uPtrs[element]

Следующий рисунок описывает, как получить доступ к входным сигналам S-функции с двумя входами.

Как показано на предыдущем рисунке, указатели входного массива могут указывать на несмежные места в памяти.

Вы можете извлечь выходной сигнал при помощи этого кода.

real_T *y = ssGetOutputPortSignal(S,outputPortIndex);

Доступ к смежным входным сигналам

mdlInitializeSizes S-функции метод может указать, что элементы его входных сигналов должны занимать смежные области памяти, используя ssSetInputPortRequiredContiguous. Если входы смежны, другие методы могут использовать ssGetInputPortSignal для доступа к входам.

Доступ к входным сигналам отдельных портов

В этом разделе описывается, как получить доступ ко всем входным сигналам конкретного порта и записать их в выходной порт. Предыдущий рисунок показывает, что входной массив указателей может указывать на несмежные значения в векторе ввода-вывода блока. Сигналы выхода конкретного порта образуют смежный вектор. Поэтому правильный способ доступа к входным элементам и записи их в выходные элементы (если входной и выходной порты имеют равные ширины) - использовать этот код.

int_T element;
int_T portWidth = ssGetInputPortWidth(S,inputPortIndex);
InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S,inputPortIndex);
real_T *y = ssGetOutputPortSignal(S,outputPortIdx);

for (element=0; element<portWidth; element++) {
  y[element] = *uPtrs[element];
}

Распространенной ошибкой является попытка получить доступ к входным сигналам через арифметику указателя. Для примера, если бы вы разместили

real_T *u = *uPtrs; /* Incorrect */

чуть ниже инициализации uPtrs и замените внутреннюю часть указанного цикла на

*y++ = *u++; /* Incorrect */

код компилируется, но файл MEX может аварийно завершить работу программного обеспечения Simulink. Это происходит потому, что возможен доступ к недопустимой памяти (которая зависит от того, как вы создаете свою модель). При неправильном доступе к входным сигналам происходит сбой, когда сигналы, входящие в ваш Блок s-function, не смежны. Несмежные данные сигнала возникают, когда сигналы проходят через блоки виртуальных соединений, такие как блоки Mux или Selector.

Чтобы убедиться, что ваша S-функция правильно обращается к широким входным сигналам, передайте реплицированный сигнал к каждому входному порту вашей S-функции. Для этого создайте блок Mux с количеством входа портов, равным ширине необходимого сигнала, входящего в вашу S-функцию. Затем подключите ведущий источник к каждому входному порту S-функции, как показано на следующем рисунке. Наконец, запустите свою S-функцию, используя этот входной сигнал, чтобы убедиться, что он не падает и выдает ожидаемые результаты.

См. также

| | |

Похожие темы