Порты ввода и вывода

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

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

  • Размерности входного порта (см. Размерности Входного порта Инициализации),

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

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

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

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

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

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

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

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

Можно сконфигурировать дополнительные свойства входного порта с помощью других макросов S-функции. Смотрите Порты Ввода и вывода в разделе “SimStruct Macros and Functions Listed by Usage” для получения дополнительной информации.

Примечание

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

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

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

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

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

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

    ssSetInputPortDimensionInfo(S, inputPortIdx, dimsInfo)
    

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

Калибровка входного порта динамически

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

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

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

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

    ssSetInputPortDimensionInfo(S, inputPortIdx, DYNAMIC_DIMENSION)
    

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

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

    ssSetInputPortWidth(S, inputPortIdx, DYNAMICALLY_SIZED)
    

    задавать размерность входного порта.

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

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

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

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

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

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

Следующий код в mdlInitializeSizes конфигурирует S-функцию с двумя входными портами. Смотрите Порты Ввода и вывода в разделе “SimStruct Macros and Functions Listed by Usage” для получения дополнительной информации о макросах, используемых в этом примере.

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-функция Level 2 MATLAB® использует скалярные правила расширения по умолчанию, если порты ввода и вывода заданы, как динамически измерено (см. Скалярное Расширение Входных параметров и Параметров в Использовании Simulink).

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

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

Примечание

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

Лучший способ понять, как использовать скалярное расширение, состоит в том, чтобы считать пример sfcndemo_sfun_multiport. Эта модель содержит три Блока s-function, каждого с несколькими входными портами. S-функция sfun_multiport.c, используемый в этих блоках, устанавливает опцию SS_OPTION_ALLOW_INPUT_SCALAR_EXPANSION в своем методе mdlInitializeSizes, позволяя скалярное расширение входных параметров. S-функция указывает, что ее вводы и выводы динамически измерены. Поэтому во время распространения сигнала, механизм устанавливает ширину входных портов к ширине сигнала, соединенного с портом и шириной выходных портов к ширине любого широкого входного сигнала. Метод 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]));
      }
   }
}