Входные и выходные порты

Создание входных портов для S-функций C

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

  • Размерности входного порта (см. «Инициализация размеров Input port»)

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

  • Позволяет ли входной порт скалярное расширение входов (см. Скалярное расширение входных параметров)

  • Имеет ли порт входа прямые сквозные соединения, использование ssSetInputPortDirectFeedThrough

    Порт имеет прямое сквозное соединение, если вход используется в mdlOutputs или mdlGetTimeOfNextVarHit функций. Флаг прямой передачи для каждого входного порта может быть установлен на любое 1=yes или 0=no. Оно должно быть установлено равным 1, если вход, u, используется в mdlOutputs или mdlGetTimeOfNextVarHit стандартная программа. Установка флага прямой передачи равного 0 говорит Simulink® двигатель, который u не используется ни в одной из этих стандартных программ S-функций. Нарушение этого приводит к непредсказуемым результатам.

  • Тип данных входного порта, если не тип по умолчанию double

    Использовать ssSetInputPortDataType для установки типа данных порта входа. Если необходимо, чтобы тип данных порта зависел от типа данных порта, к которому он подключен, укажите тип данных следующим DYNAMICALLY_TYPED. В этом случае вы должны предоставить реализации mdlSetInputPortDataType и mdlSetDefaultPortDataTypes методы, позволяющие правильно задать тип данных во время распространения сигнала.

  • Числовой тип входного порта, если порт принимает комплексные сигналы

    Использовать ssSetInputPortComplexSignal для установки числового типа порта входа. Если необходимо, чтобы числовой тип порта зависел от числового типа порта, к которому он подключен, задайте числовой тип следующим COMPLEX_INHERITED. В этом случае вы должны предоставить реализации mdlSetInputPortComplexSignal и mdlSetDefaultPortComplexSignals методы, позволяющие правильно задать числовой тип во время распространения сигнала.

Можно сконфигурировать дополнительные свойства входного порта, используя другие макросы S-функций. Смотрите Входные и Выходные Порты в разделе «Макросы SimStruct и функции, перечисленные при использовании» для получения дополнительной информации.

Примечание

The mdlInitializeSizes метод должен указать количество портов, прежде чем устанавливать какие-либо свойства. Если он пытается задать свойство порта, который не существует, он обращается к недопустимой памяти, и происходит нарушение сегментации.

Инициализация размерностей Input port

Можно задать размерности входного порта с помощью одного из следующих макросов:

  • Если входной сигнал должен быть одномерным, и ширина входного порта w, использование

    ssSetInputPortWidth(S, inputPortIdx, w)
    
  • Если входной сигнал должен быть матрицей размерности m-by- n, использование

    ssSetInputPortMatrixDimensions(S, inputPortIdx, m, n)
    
  • В противном случае, если входной сигнал может иметь одну или две размерности, используйте

    ssSetInputPortDimensionInfo(S, inputPortIdx, dimsInfo)
    

    Можно использовать эту функцию для полной или частичной инициализации размерностей портов (см. следующий раздел).

Динамическое определение размеров Input port

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

Для динамического измерения порта входа:

  • Задайте некоторые или все размерности входного порта в динамическом размере mdlInitializeSizes.

    Если вход порт может принять сигнал любой размерности, используйте

    ssSetInputPortDimensionInfo(S, inputPortIdx, DYNAMIC_DIMENSION)
    

    для установки размерности порта входа.

    Если вход порт может принимать только вектор (1-D) сигналы, но сигналы могут быть любого размера, используйте

    ssSetInputPortWidth(S, inputPortIdx, DYNAMICALLY_SIZED)
    

    для определения размерности входного порта.

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

    ssSetInputPortMatrixDimensions(S, inputPortIdx, 
       DYNAMICALLY_SIZED, DYNAMICALLY_SIZED)
    
  • Предоставить mdlSetInputPortDimensionInfo метод, который устанавливает размерности входного порта равным размеру сигнала, соединенного с ним.

    Механизм Simulink вызывает этот метод во время распространения сигнала, когда он определил размерность сигнала, соединенного с портом входа.

  • Предоставить mdlSetDefaultPortDimensionInfo метод, который устанавливает размерности портов блока в значение по умолчанию. См. sfun_dynsize.c для примера, который реализует этот макрос.

    Механизм вызывает этот метод во время распространения сигнала, когда он не может определить размерность сигнала, соединенного с некоторыми или всеми входными портами блока. Это может произойти, пример, если вход порт не подключен. Если S-функция не предоставляет этот метод, стандартная программа распространения сигнала устанавливает размерность портов блока 1-D скаляром.

Пример: Определение нескольких входных портов S-функции

Следующий код в mdlInitializeSizes конфигурирует S-функцию с двумя входными портами. Смотрите Входные и Выходные Порты в разделе «Макросы SimStruct и функции, перечисленные по использованию» для получения дополнительной информации о макросах, используемых в этом примере.

if (!ssSetNumInputPorts(S, 2)) return;

for (i = 0; i < 2; i++) {
  /* Input has direct feedthrough */
  ssSetInputPortDirectFeedThrough(S, i, 1);

  /* Input is a real signal */
  ssSetInputPortComplexSignal(S, i, COMPLEX_NO);

  /* Input is a dynamically sized 2-D matrix */
  ssSetInputPortMatrixDimensions(S ,i, 
     DYNAMICALLY_SIZED, DYNAMICALLY_SIZED);

  /* Input inherits its sample time */
  ssSetInputPortSampleTime(S, i,INHERITED_SAMPLE_TIME);

  /* Input signal must be contiguous */
  ssSetInputPortRequiredContiguous(S, i, 1);

  /* The input port cannot share memory */
  ssSetInputPortOverWritable(S, i, 0);
}

Во время распространения сигнала механизм Simulink вызывает mdlSetInputPortDimensionInfo этой S-функции макрос для инициализации размерностей входного порта. В этом примере mdlSetInputPortDimensionInfo устанавливает входные размерности кандидатов, переданные макросу механизмом.

#if defined(MATLAB_MEX_FILE)
#define MDL_SET_INPUT_PORT_DIMENSION_INFO
static void mdlSetInputPortDimensionInfo(SimStruct        *S,
                                  int_T            port,
                                  const DimsInfo_T *dimsInfo)
{
    if(!ssSetInputPortDimensionInfo(S, port, dimsInfo)) return;
}
#endif

Для примера, который конфигурирует S-функцию с несколькими входными и выходными портами, откройте модель Simulink sfcndemo_sfun_multiport и осмотрите S-функцию sfun_multiport.c.

Создание выходных портов для S-функций C

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

  • Размерности выходного порта

    Можно задать размерности выходного порта с помощью одного из следующих макросов:

    Если вы хотите, чтобы размерности порта зависели от связности блоков, задайте размерности DYNAMIC_DIMENSIONS при использовании ssSetOutputPortDimensionInfo или к DYNAMICALLY_SIZED для всех других макросов. В таком случае S-функция должна обеспечивать mdlSetOutputPortDimensionInfo и mdlSetDefaultPortDimensionInfo методы, чтобы убедиться, что размерности выходного порта установлены на правильные значения в генерации кода.

  • Тип данных порта выхода

    Использовать ssSetOutputPortDataType для установки типа данных выходного порта. Если необходимо, чтобы тип данных порта зависел от связности блоков, укажите тип данных следующим DYNAMICALLY_TYPED. В этом случае вы должны предоставить реализации mdlSetOutputPortDataType и mdlSetDefaultPortDataTypes методы, позволяющие правильно задать тип данных во время распространения сигнала.

  • Числовой тип выходного порта, если порт выводит комплексные сигналы

    Использовать ssSetOutputPortComplexSignal для установки числового типа выходного порта. Если необходимо, чтобы числовой тип порта зависел от числового типа порта, к которому он подключен, задайте числовой тип следующим COMPLEX_INHERITED. В этом случае вы должны предоставить реализации mdlSetOutputPortComplexSignal и mdlSetDefaultPortComplexSignals методы, позволяющие правильно задать числовой тип во время распространения сигнала.

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

Скалярное расширение входов

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

A Level-2 MATLAB® S-функция использует скалярные правила расширения по умолчанию, если входной и выходной порты заданы как динамически определенные (см. «Скалярное расширение входов и параметров в использовании Simulink»).

При включенном скалярном расширении S-функция mdlInitializeSizes метод должен указать, что входной и выходной порты имеют динамический размер. Механизм Simulink использует метод по умолчанию, чтобы задать размерности входного и выходного портов. Если блок имеет более двух входов, входные сигналы могут быть скалярными или широкими сигналами, где все широкие сигналы имеют одинаковое количество элементов. В этом случае двигатель устанавливает размерности выходных портов на ширину широких входных сигналов и расширяет любые скалярные входы до этой ширины. Если широкие входы управляются 1-D и 2-D векторами, выход является 2-D векторным сигналом, и скалярные входы расширяются до 2-D векторного сигнала.

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

Примечание

Механизм игнорирует опцию скалярного расширения, если S-функция задает или управляет размерностями своих входных и выходных портов либо путем инициализации размерностей в mdlInitializeSizes, использование mdlSetInputPortWidth и mdlSetOutputPortWidth, или использование mdlSetInputPortDimensionInfo, mdlSetOutputPortDimensionInfo, и mdlSetDefaultPortDimensionInfo.

Лучший способ понять, как использовать скалярное расширение, это рассмотреть пример sfcndemo_sfun_multiport. Эта модель содержит три блоков s-function, каждый с несколькими входными портами. S-функция sfun_multiport.c используется в этих блоках, устанавливает SS_OPTION_ALLOW_INPUT_SCALAR_EXPANSION опция в своей mdlInitializeSizes способ, позволяющий скалярное расширение входов. S-функция задает, что ее входы и выходы динамически. Поэтому во время распространения сигнала двигатель устанавливает ширину входных портов на ширину сигнала, соединенного с портом, и ширину выходных портов на ширину любого широкого входного сигнала. The mdlOutputs способ выполняет поэлементную сумму входных сигналов, расширяя при необходимости любые скалярные входы.

/* Calculate an element-by-element sum of the input signals.
   yWidth is the width of the output signal. */

for (el = 0; el < yWidth; el++) {

   int_T  port;
   real_T sum = 0.0;
   for (port = 0; port < nInputPorts; port++) {
      /* Get the input signal value */
      InputRealPtrsType uPtrs = 
                   ssGetInputPortRealSignalPtrs(S,port);

      if (el < ssGetInputPortWidth(S,port)) {
         /* Input is a wide signal. Use specific element */
         sum = sum + ((real_T)signs[port] * (*uPtrs[el]));

      } else { 
         /* Use the scalar value to expand the signal */
         sum = sum + ((real_T)signs[port] * (*uPtrs[0]));
      }
   }
}

Маскированные мультипортовые S-функции

Если вы разрабатываете маскированные мультипортовые блоки s-function, количество портов которых изменяется на основе некоторого параметра и хотите поместить их в библиотеку Simulink, необходимо указать, что маска изменяет внешний вид блока. Для этого выполните команду

  set_param(blockname,'MaskSelfModifiable','on')

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