2

我想在纯 Simulink 模型中实现一个非常巨大的(10^6 个元素 - 固定大小)循环缓冲区(没有更多的工具箱,没有 S-Function)。

在某些时候,我需要阅读一些元素(任何地方,不仅仅是开始或结束)。

以下解决方案我不能使用:

  1. “队列块”或“缓冲块”(我没有可用的信号处理工具箱)
  2. “离散延迟”(我需要一个巨大的缓冲区,并且不会将 10^6 延迟放入模型中)
  3. “模拟事件”(我需要从这个模型生成代码)

我还没有尝试过的“S-Function”,我正在寻找替代解决方案。

你知道什么进一步的方法?

4

2 回答 2

5

可以使用 MATLAB Fcn 模块创建一个简单的循环缓冲区:

function y = CircularBuffer(u, N)
%#codegen
% Function to implement a simple N element circular buffer

% Define the internal buffer variable as persistent so
% so that it will maintain its values from one time step
% to the next.
persistent buffer writeIdx

% Initialize the buffer the first time through
if isempty(buffer)
    % Initialize the buffer
    buffer = zeros(N,1);
    writeIdx = 1;
else
    buffer(writeIdx) = u;
    if (writeIdx == N)
        writeIdx = 1;
    else
        writeIdx = writeIdx+1;
    end
end

% Output the buffer
y = buffer;

这完全支持代码生成(并且不执行 memcpy)。

如果需要,您可以轻松更改缓冲区的数据类型,但如果您想在输入和输出信号上使用不同的采样率(与 Signal Processing 模块集中的缓冲区一样),那么您需要恢复使用 S -功能。

于 2013-06-21T15:47:27.973 回答
2

首先,让我恭维您对纯 Simulink 的追求!这是很有可能的,但是,Mathworks 代码生成器不处理这个用例。它非常草率,并创建了整个队列的缓冲副本。这是一个例子:

顶级模型 读操作 写操作

然后,看一些代码。哎呀!

/* Model output function */
static void queue_output(int_T tid)
{
  {
    real_T rtb_MathFunction;

    /* DataStoreRead: '<S1>/Data Store Read' */
    memcpy((void *)(&queue_B.DataStoreRead[0]), (void *)(&queue_DWork.A[0]),
           100000U * sizeof(uint16_T));

    /* Outport: '<Root>/Out1' incorporates:
     *  DataStoreRead: '<S1>/Data Store Read1'
     *  Selector: '<S1>/Selector'
     */
    queue_Y.Out1 = queue_B.DataStoreRead[(int32_T)queue_DWork.idx];

    /* If: '<Root>/If' incorporates:
     *  ActionPort: '<S2>/Action Port'
     *  Constant: '<Root>/Constant'
     *  SubSystem: '<Root>/WriteToQueue'
     */
    if (queue_P.Constant_Value > 0.0) {
      /* DataStoreRead: '<S2>/Data Store Read3' */
      memcpy((void *)(&queue_B.Assignment[0]), (void *)(&queue_DWork.A[0]),
             100000U * sizeof(uint16_T));

      /* Math: '<S2>/Math Function' incorporates:
       *  Constant: '<S2>/Constant1'
       *  Constant: '<S3>/FixPt Constant'
       *  DataStoreRead: '<S2>/Data Store Read2'
       *  Sum: '<S3>/FixPt Sum1'
       */
      rtb_MathFunction = rt_mod_snf(queue_DWork.idx +
        queue_P.FixPtConstant_Value, queue_P.Constant1_Value);

      /* Assignment: '<S2>/Assignment' incorporates:
       *  Constant: '<S2>/Constant'
       */
      queue_B.Assignment[(int32_T)rtb_MathFunction] = queue_P.Constant_Value_h;

      /* DataStoreWrite: '<S2>/Data Store Write' */
      memcpy((void *)(&queue_DWork.A[0]), (void *)(&queue_B.Assignment[0]),
             100000U * sizeof(uint16_T));

      /* DataStoreWrite: '<S2>/Data Store Write1' */
      queue_DWork.idx = rtb_MathFunction;
    }
  }

Memcpy 10000 uint16 的每个循环!在 Mathworks 以稳健的方式解决这个问题之前,这是一个需要硬编码索引的初始尝试,S-Function 是唯一的方法。

于 2013-06-20T19:25:39.177 回答