В модели могут существовать два периодических перехода частоты дискретизации:
Более быстрый блок, управляющий более медленным блоком
Более медленный блок, приводящий в действие более быстрый блок
Следующие разделы касаются моделей с периодическими шагами расчета только с нулевым смещением. Другие факторы применяются к многоскоростным моделям, которые включают асинхронные задачи. Для получения дополнительной информации о том, как сгенерировать код для асинхронной многозадачности, смотрите Asynchronous Support.
В многозадачных и псевдозадачных системах различие частот дискретизации может привести к выполнению блоков в неправильном порядке. Чтобы предотвратить возможные ошибки в вычисленных данных, вы должны контролировать выполнение модели в этих переходах. При соединении блоков быстрее и медленнее, вы или Simulink® двигатель должен добавить между ними блоки Rate Transition. Быстрые и медленные переходы проиллюстрированы на следующем рисунке.
Медленные переходы к быстрым показаны на следующем рисунке.
Примечание
Хотя блок Rate Transition предлагает супермножество возможностей блока Unit Delay (для медленных и быстрых переходов) и блока Zero-Order Hold (для быстрых и медленных переходов), следует использовать блок Rate Transition вместо этих блоков.
Блоки Rate Transition имеют дело с вопросами целостности данных и детерминизма, связанными с передачей данных между блоками, работающими с различными скоростями.
Целостность данных: Проблема целостности данных существует, когда вход в блок изменяется во время выполнения этого блока. Проблемы целостности данных могут быть вызваны упреждением.
Примите во внимание следующий сценарий:
Более быстрый блок подает вход в более медленный блок.
Более медленный блок считывает значение входа, V1 из более быстрого блока, и начинает расчеты использовать это значение.
Расчеты вытесняются другим выполнением более быстрого блока, который вычисляет новый выход значения V2.
Теперь возникает проблема целостности данных: когда медленный блок возобновляет выполнение, он продолжает свои расчеты, теперь используя «новую» входа V2 значения.
Такая передача данных называется незащищенной. Более быстрый и медленный переход в режиме реального времени показывает незащищенную передачу данных.
При защищенной передаче данных выходная V1 более быстрого блока сохраняется до тех пор, пока медленный блок не закончит выполнение.
Детерминированная и недетерминированная передача данных: В детерминированной передаче данных, время передачи данных полностью предсказуемо, как определяется скоростями дискретизации блоков.
Время недетерминированной передачи данных зависит от доступности данных, скоростей дискретизации блоков и времени, в которое принимающий блок начинает выполняться относительно ведущего блока.
Можно использовать блок Rate Transition, чтобы защитить передачи данных в вашем приложении и сделать их детерминированными. Эти характеристики считаются желательными в большинстве применений. Однако блок Rate Transition поддерживает гибкие опции, которые позволяют вам скомпрометировать целостность данных и детерминизм в пользу более низкой задержки. В следующем разделе описаны эти опции.
При обработке передачи данных между задачами генератор кода делает следующие предположения:
Переходы данных происходят между одной задачей чтения и одной задачей записи.
Чтение или запись переменной размера байта является атомарной.
Когда две задачи взаимодействуют через переход данных, только одна из них может превалировать другой.
Для периодических задач задача с более высокой скоростью имеет более высокий приоритет, чем задача с более низкой скоростью; более быстрая задача прерывает задачу более медленной скорости.
Все задачи выполняются на одном процессоре. Квантование времени не разрешено.
Процессы не прерываются и не перезапускаются (особенно в то время как данные передаются между задачами).
Несколько параметров блока Rate Transition имеют отношение к его использованию в генерации кода для выполнения в реальном времени, как обсуждается ниже. Полное описание блока см. в разделе Rate Transition.
Блок Rate Transition обрабатывает периодические (быстро и медленно) и асинхронные переходы. При вставке между двумя блоками различных частот дискретизации, блок Rate Transition автоматически конфигурирует свои входные и выходные скорости дискретизации для типа перехода; вам не нужно указывать, является ли переход медленным к быстрому или быстрым к медленному (низкие к высокому или высокие к низкому приоритеты для асинхронных задач).
Критическое решение, которое необходимо принять при конфигурировании блока Rate Transition, является выбором механизма передачи данных, который будет использоваться между двумя скоростями. Ваш выбор диктуется факторами безопасности, использования памяти и эффективности. Как параметры блоков диалоговое окно Rate Transition на следующем рисунке показов, механизм передачи данных управляются двумя опциями.
Ensure data integrity during data transfer: Когда вы выбираете этот параметр, данные, переданные между скоростями, поддерживают его целостность (передача данных защищена). Когда вы очищаете этот параметр, данные могут не поддерживать его целостность (передача данных не защищена). По умолчанию выбирается Ensure data integrity during data transfer параметра.
Ensure deterministic data transfer (maximum delay): Этот параметр поддерживается для периодических задач с смещением нуля и быстрыми и медленными скоростями, которые являются кратными друг другу. Когда этот параметр выбран, блок Rate Transition ведет себя как блок Zero-Order Hold (для быстрых и медленных переходов) или блок Unit Delay (для медленных и быстрых переходов). Блок Rate Transition управляет синхронизацией передачи данных полностью предсказуемым способом. Когда этот параметр очищен, передача данных является недетерминированной. По умолчанию Ensure deterministic data transfer (maximum delay) выбирается для переходов между периодическими скоростями со смещением в нуле; для асинхронных переходов он не может быть выбран.
Блок Rate Transition предлагает три режима работы в отношении передачи данных. В порядке безопасности:
Protected/Deterministic (default): Это самый безопасный режим. Недостатком этого режима является то, что он вводит детерминированную задержку в систему для случая медленных к быстрым периодических переходов скорости. В этом случае задержка, введенная блоком Rate Transition, является одним периодом дискретизации более медленной задачи. В случае быстрых к медленным периодических переходов скорости блок Rate Transition не вводит дополнительную задержку.
Protected/NonDeterministic: В этом режиме для медленных и быстрых периодических переходов скорости целостность данных защищена двойной буферизацией данных, переданных между скоростями. Для быстрых к медленным периодических переходов скорости используется флаг семафора. Блоки, расположенные ниже по потоку от блока Rate Transition, используют последние доступные данные из блока, который управляет блоком Rate Transition. Максимальная задержка меньше или равна одному периоду дискретизации более быстрой задачи.
Недостатками этого режима являются недетерминированные сроки. Преимуществом этого режима является его низкая задержка.
Unprotected/NonDeterministic: Этот режим не рекомендуется для критически важных приложений. Задержка этого режима такая же, как и для режима Protected/NonDeterministic, но требования к памяти уменьшаются, так как не требуются ни двойная буферизация, ни семафоры. То есть блок Rate Transition ничего не делает в этом режиме кроме как передавать сигналы через; он просто существует, чтобы уведомить вас о существовании перехода скорости (и может привести к тому, что сгенерированный код вычислит неправильные ответы). Однако выбор этого режима генерирует наименьшее количество кода.
Примечание
В незащищенном режиме (Ensure data integrity during data transfer выбран) блок Rate Transition не делает ничего кроме как позволить переходу скорости существовать в модели.
Шаг расчета в выход порте блока Rate Transition может быть только дискретным или фиксированным в незначительном временном шаге. Это означает, что, когда блок Rate Transition наследует непрерывный шаг расчета от своего целевого блока, он обрабатывает унаследованный шаг расчета как Фиксированное на Незначительном Временном Шаге. Поэтому выходная функция блока Rate Transition запускается только на основных временных шагах. Если шаг расчета целевого блока является непрерывным, блок Rate Transition выхода шаг расчета являются временем расчета базовой скорости (если решатель является фиксированным шагом) или нуля шагом расчета (если решатель является переменным шагом ).
Механизм Simulink может обнаружить несоответствующие переходы скорости в многозадачной модели во время схемы обновления и автоматически вставить блоки Rate Transition, чтобы обработать их. Чтобы включить это, выберите Automatically handle rate transition for data transfer параметра конфигурации модели. По умолчанию этот параметр очищается. Когда вы выбираете этот параметр:
Simulink обрабатывает переходы между периодическими шагами расчета и асинхронными задачами.
Simulink вставляет скрытые блоки Rate Transition в блок-схему.
Генератор кода создает код для блоков Rate Transition, которые были вставлены автоматически. Этот код идентичен коду, сгенерированному для блоков Rate Transition, которые были вставлены вручную.
Автоматически вставленные блоки Rate Transition работают в защищенном режиме для периодических задач и асинхронных задач. Вы не можете изменить это поведение. Для периодических задач автоматически вставленные блоки Rate Transition работают с уровнем детерминизма, заданным параметром конфигурации <reservedrangesplaceholder1> модели. Настройкой по умолчанию является Whenever possible
, что позволяет проводить детерминизм для передачи данных между периодическими шагами расчета, которые связаны целым числом, кратным. Для получения дополнительной информации смотрите Детерминированный перенос данных. Чтобы использовать другие режимы, необходимо вставить блоки Rate Transition и установить их режимы вручную.
Например, в этой модели SineWave2 имеет время расчета 2, и SineWave3 имеет время расчета 3.
Когда вы выбираете Automatically handle rate transition for data transfer параметра конфигурации модели, Simulink вставляет блок Rate Transition между каждым блоком Sine Wave и блоком Product. Вставленные блоки имеют значения параметров для согласования шагов расчета Sine Wave блока.
Если скорости выборки входного порта и данных выходного порта в модели не множители друг другу, Simulink вставляет блок Rate Transition, чья частота дискретизации является наибольшим общим делителем (GCD) из этих двух скоростей. Если ни один другой блок в модели не содержит эту новую скорость, ошибка возникает во время симуляции. В этом случае необходимо вставить блок Rate Transition вручную.
Когда вы выбираете Automatically handle rate transition for data transfer параметра конфигурации модели, Simulink вставляет блоки Rate Transition в пути, которые имеют несоответствующие скорости перехода. Эти блоки по умолчанию скрыты. Чтобы визуализировать вставленные блоки, обновите схему. Метки значков появляются в модели и указывают, где Simulink вставил блоки Rate Transition во время фазы компиляции. Для примера в этой модели были вставлены три блока Rate Transition между двумя блоками Sine Wave и Мультиплексором и Интегратором при компиляции модели. Значок ZOH и DbBuf меток указать эти блоки.
Можно показывать или скрывать метки значков. Откройте вкладку Debug. В Diagnostics разделе Information Overlays/Sample Time галереи выберите или очистите Automatic Rate Transitions.
Чтобы сконфигурировать скрытые блоки Rate Transition так, чтобы блоки были видны, щелкните правой кнопкой мыши метку значка и выберите Insert rate transition block.
Когда вы делаете скрытые блоки Rate Transition видимыми:
Можно увидеть тип вставленного блока Rate Transition и расположение блока в модели.
Можно задать параметры блоков Initial Conditions.
Можно изменить параметры блоков настройки для переноса ставки.
Проверьте изменения в модели, обновив схему.
Отображение вставленных блоков Rate Transition несовместимо с моделями export-function.
Дополнительные сведения о типах блоков Rate Transition см. в разделе Rate Transition.
Дополнительные сведения о типах блоков Rate Transition см. в разделе Rate Transition.
В этих разделах описываются случаи, когда блоки Rate Transition требуются для периодических переходов частоты дискретизации. Обсуждение и временные диаграммы в этих разделах основаны на предположении, что блок Rate Transition используется в своем стандартном (защищенном/детерминированном) режиме. Выбираются параметры конфигурации <reservedrangesplaceholder1> и <reservedrangesplaceholder0> модели. Это настройки, используемые для автоматически вставляемых блоков Rate Transition.
В модели, где более быстрый блок управляет более медленным блоком, имеющим прямое сквозное соединение, выходы более быстрого блока вычисляются первыми. В интервалах симуляции, где медленный блок не выполняется, симуляция прогрессирует быстрее, потому что существует меньше блоков, которые нужно выполнять. Следующий рисунок иллюстрирует эту ситуацию.
Симуляция Simulink не выполняется в реальном времени, что означает, что она не связана ограничениями в реальном времени. Симуляция ожидает или продвигается вперед, какие задачи требуются для завершения потока симуляции. Фактический временной интервал между временными шагами расчета может варьироваться.
В моделях, где более быстрый блок управляет более медленным блоком, вы должны компенсировать тот факт, что выполнение более медленного блока может охватывать более одного периода выполнения более быстрого блока. Это означает, что выходы более быстрого блока могут измениться, прежде чем более медленный блок закончит вычислять свои выходы. Следующий рисунок показывает ситуацию, в которой возникает эта проблема (T = шаг расчета). Обратите внимание, что задачи с более низким приоритетом перед завершением прерываются задачами с более высоким приоритетом.
На приведенном выше рисунке более быстрый блок выполняется второй раз, прежде чем более медленный блок завершает выполнение. Это может вызвать непредсказуемые результаты, потому что входные данные медленной задачи изменяются. Данные могут не поддерживать свою целостность в этой ситуации.
Чтобы избежать этой ситуации, механизм Simulink должен удерживать выходы блока 1 секунды (быстрее) до тех пор, пока не концы выполнение блока 2 секунды (медленнее). Способ выполнить это - вставить блок Rate Transition между блоками 1 и 2 секунды. Вход в более медленный блок не меняется во время его выполнения, поддерживая целостность данных.
Принято, что блок Rate Transition используется в своем режиме по умолчанию (protected/deterministic).
Блок Rate Transition выполняется со скоростью дискретизации более медленного блока, но с приоритетом более быстрого блока.
Когда вы добавляете блок Rate Transition, блок выполняется перед 2-вторым блоком (его приоритет выше), и его выходное значение остается постоянным, в то время как 2-й блок выполняется (он выполняется с более медленной частотой дискретизации).
В модели, где более медленный блок управляет более быстрым блоком, двигатель Simulink снова сначала вычисляет выход ведущего блока. Во время интервалов расчета, где выполняется только более быстрый блок, симуляция прогрессирует более быстро.
Следующий рисунок показывает последовательность выполнения.
Как видно из предыдущих рисунков, механизм Simulink может эффективно моделировать модели с несколькими скоростями дискретизации. Однако симуляция Simulink не работает в реальном времени.
В моделях, где более медленный блок управляет более быстрым блоком, сгенерированный код присваивает более быстрый блок более высокий приоритет, чем более медленный блок. Это означает, что более быстрый блок выполняется перед более медленным блоком, что требует особой осторожности, чтобы избежать неправильных результатов.
Эта временная схема иллюстрирует две проблемы:
Выполнение более медленного блока разделяется на более чем один более быстрый интервал блоков. В этом случае более быстрая задача выполняется второй раз до завершения выполнения более медленной задачи. Это означает, что входы более быстрой задачи могут иметь неправильные значения в некоторых случаях.
Более быстрый блок выполняется перед более медленным блоком (который находится назад от способа работы симуляции Simulink). В этом случае первый выполняется 1-й блок; но входы для более быстрой задачи не были вычислены. Это может привести к непредсказуемым результатам.
Чтобы устранить эти проблемы, необходимо вставить блок Rate Transition между медленными и более быстрыми блоками.
Принято, что блок Rate Transition используется в своем режиме по умолчанию (protected/deterministic).
Следующий рисунок показывает последовательность синхронизации, которая приводит к добавлению блока Rate Transition.
Три ключевые точки о переходах в этой схеме (см. обведенные номера):
Блок Rate Transition выхода запусков в 1-секундной задаче, но с меньшей скоростью (2 секунды). Выходы блока Rate Transition подают 1-секундные блоки задач.
Обновление Rate Transition использует выход 2-секундной задачи, чтобы обновить ее внутреннее состояние.
Выходной выход Rate Transition в 1-секундной задаче использует состояние Rate Transition, которое было обновлено во 2-секундной задаче.
Первая проблема устранена, потому что блок Rate Transition обновляется с более медленной скоростью и с приоритетом более медленного блока. Вход в блок Rate Transition (который является выходом более медленного блока) считывается после завершения выполнения более медленного блока.
Вторая проблема устранена, потому что блок Rate Transition выполняется с меньшей скоростью, и его выход не меняется во время расчета более быстрого блока, которым он управляет. Выход фрагмента блока Rate Transition выполняется со скоростью дискретизации более медленного блока, но с приоритетом более быстрого блока. Поскольку блок Rate Transition управляет более быстрым блоком и имеет фактически тот же приоритет, он выполняется перед более быстрым блоком.
Примечание
Это использование блока Rate Transition изменяет модель. Вывод более медленного блока теперь задерживается на один временной шаг по сравнению с выходом без блока Rate Transition.
volatile
Ключевое словоКогда вы выбираете Ensure data integrity during data transfer параметра конфигурации модели, код, сгенерированный для блока Rate Transition, задает глобальные буферы и семафоры и использует их, чтобы защитить целостность переданных данных.
В частности, для многозадачного приложения, задачи (скорости), участвующие в передаче данных, могут записываться в переданные данные, буферы и семафоры в моменты, которые ваш компилятор не может предвидеть. Чтобы предотвратить оптимизацию вашего компилятора кода сборки способом, который ухудшает целостность переданных данных, генератор кода применяет ключевое слово volatile
к буферам и семафорам. Генератор кода не применяется volatile
глобальной переменной, которая представляет переданные данные, поскольку volatile
буферы и семафоры обычно обеспечивают достаточную защиту.
С Embedded Coder®, можно явным образом применить volatile
к переданным данным путем применения встроенного пользовательского класса памяти Volatile
на вход блока Rate Transition. Для примера можно использовать этот метод, чтобы помочь защитить целостность данных, которые ваш внешний код использует с сгенерированным кодом.
Кроме того, чтобы защитить данные, которые ваш внешний код использует с сгенерированным кодом, можно записать собственные функции C, которые считывают и записывают данные защищенным способом. Затем можно применить пользовательский класс памяти GetSet
к данным в модели, что заставляет сгенерированный код вызывать ваши функции вместо прямого доступа к данным.
Для получения дополнительной информации о применении volatile
, см. Protect Global Data with const and Volatile Type Qualifiers (Embedded Coder). Для получения дополнительной информации о GetSet
, см. «Доступ к данным через функции с GetSet (Embedded Coder) класса памяти».
Можно задать, строит ли генератор кода код и данные, которые он производит для Rate Transition, блоки с кодом модели или помещает код и данные в отдельные функции, которые вызывает код модели. Вы управляете этим, выбрав параметр Rate Transition block code. Отделение блочного кода Rate Transition и данных от кода и данных алгоритма позволяет вам независимо анализировать, оптимизировать и тестировать блок и код алгоритма Rate Transition. По умолчанию блочный код Rate Transition устанавливается в строке с кодом алгоритма и данными. Можно разделить код и данные так, чтобы сгенерированный код содержал отдельные get
и set
функции, которые model
_step
вызов функций и выделенная структура для данных о состоянии. Сгенерированный код также содержит отдельные start
и initialize
функции, которые model
_initialize
вызовы функций.
Пример модели
Откройте пример модели rtwdemo_ratetrans
. Эта многозадачная модель содержит несколько блоков Rate Transition, работающих в разных режимах.
open_system('rtwdemo_ratetrans'); set_param('rtwdemo_ratetrans','SystemTargetFile','ert.tlc'); set_param('rtwdemo_ratetrans','GenerateComments', 'Off');
Отдельный код для блоков переходов по скорости
В диалоговом окне Параметров конфигурации параметр Rate Transition блока code установлен в Function
. Сгенерируйте код для модели. Код находится в файлах rtwdemo_ratetrans.c
и rtwdemo_ratetrans.h
.
currentDir = pwd;
[~,cgDir] = rtwdemodir();
slbuild('rtwdemo_ratetrans');
### Starting build procedure for: rtwdemo_ratetrans ### Successful completion of build procedure for: rtwdemo_ratetrans Build Summary Top model targets built: Model Action Rebuild Reason ================================================================================================== rtwdemo_ratetrans Code generated and compiled Code generation information file does not exist. 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 16.581s
hfile=fullfile(cgDir, 'rtwdemo_ratetrans_ert_rtw','rtwdemo_ratetrans.h'); rtwdemodbtype(hfile,'typedef struct {','} DW;', 1, 1);
typedef struct { real_T OutportBufferForOut3[20]; real_T Integrator1_DSTATE[20]; real_T Integrator2_DSTATE[20]; real_T Integrator3_DSTATE[20]; real_T Integrator1_PREV_U[20]; real_T Integrator2_PREV_U[20]; real_T Integrator3_PREV_U[20]; uint32_T Algorithm_PREV_T; struct { uint_T Algorithm_RESET_ELAPS_T:1; } bitsForTID1; uint8_T Integrator1_SYSTEM_ENABLE; uint8_T Integrator2_SYSTEM_ENABLE; uint8_T Integrator3_SYSTEM_ENABLE; } DW;
Для блоков Rate Transition данные о состоянии не находятся в глобальной структуре состояния, DW_rtwdemo_ratetrans_T
. Эти данные находятся в собственной структуре в файле rtwdemo_ratetrans_rtb.h
.
Этот код находится в файле rtwdemo_ratetrans.c
.
cfile=fullfile(cgDir, 'rtwdemo_ratetrans_ert_rtw','rtwdemo_ratetrans.c'); rtwdemodbtype(cfile,'void rtwdemo_ratetrans_step0','void rtwdemo_ratetrans_terminate(void)', 1, 0);
void rtwdemo_ratetrans_step0(void) { (rtM->Timing.RateInteraction.TID0_1)++; if ((rtM->Timing.RateInteraction.TID0_1) > 1) { rtM->Timing.RateInteraction.TID0_1 = 0; } rtwdemo_rate_DetAndIntegS2F_get(rtY.Out1); rtwdemo_ratetr_IntegOnlyS2F_get(rtY.Out2); memcpy(&rtY.Out3[0], &rtDW.OutportBufferForOut3[0], 20U * sizeof(real_T)); rtwdemo_rate_DetAndIntegF2S_set(rtU.In1); rtwdemo_ratetr_IntegOnlyF2S_set(rtU.In2); } void rtwdemo_ratetrans_step1(void) { real_T rtb_DetAndIntegF2S[20]; real_T rtb_IntegOnlyF2S[20]; real_T tmp; int32_T i; uint32_T Algorithm_ELAPS_T; rtwdemo_rate_DetAndIntegF2S_get(rtb_DetAndIntegF2S); rtwdemo_ratetr_IntegOnlyF2S_get(rtb_IntegOnlyF2S); if (rtDW.bitsForTID1.Algorithm_RESET_ELAPS_T) { Algorithm_ELAPS_T = 0U; } else { Algorithm_ELAPS_T = rtM->Timing.clockTick1 - rtDW.Algorithm_PREV_T; } rtDW.Algorithm_PREV_T = rtM->Timing.clockTick1; rtDW.bitsForTID1.Algorithm_RESET_ELAPS_T = false; tmp = 0.001 * (real_T)Algorithm_ELAPS_T; for (i = 0; i < 20; i++) { if (rtDW.Integrator1_SYSTEM_ENABLE == 0) { rtDW.Integrator1_DSTATE[i] += tmp * rtDW.Integrator1_PREV_U[i]; } if (rtDW.Integrator2_SYSTEM_ENABLE == 0) { rtDW.Integrator2_DSTATE[i] += tmp * rtDW.Integrator2_PREV_U[i]; } if (rtDW.Integrator3_SYSTEM_ENABLE == 0) { rtDW.Integrator3_DSTATE[i] += tmp * rtDW.Integrator3_PREV_U[i]; } rtDW.OutportBufferForOut3[i] = rtDW.Integrator3_DSTATE[i]; rtDW.Integrator1_PREV_U[i] = rtb_DetAndIntegF2S[i]; rtDW.Integrator2_PREV_U[i] = rtb_IntegOnlyF2S[i]; rtDW.Integrator3_PREV_U[i] = rtU.In3[i]; } rtDW.Integrator1_SYSTEM_ENABLE = 0U; rtDW.Integrator2_SYSTEM_ENABLE = 0U; rtDW.Integrator3_SYSTEM_ENABLE = 0U; rtwdemo_rate_DetAndIntegS2F_set(rtDW.Integrator1_DSTATE); rtwdemo_ratetr_IntegOnlyS2F_set(rtDW.Integrator2_DSTATE); rtM->Timing.clockTick1++; } void rtwdemo_ratetrans_initialize(void) { rtDW.bitsForTID1.Algorithm_RESET_ELAPS_T = true; rtDW.Integrator1_SYSTEM_ENABLE = 1U; rtDW.Integrator2_SYSTEM_ENABLE = 1U; rtDW.Integrator3_SYSTEM_ENABLE = 1U; }
The rtwdemo_ratetrans_step0
и rtwdemo_ratetrans_step1
функции содержат вызовы в get
и set
функций. Эти функции содержат блочный код Rate Transition. Эти определения функций находятся в файле rtwdemo_ratetrans_rtb.c
.
Сгенерируйте Inlined Code для блоков перехода скорости
В диалоговом окне Параметров конфигурации установите параметр Rate Transition блока code равным Inline
. Сгенерируйте код для модели. Код находится в файлах rtwdemo_ratetrans.c
и rtwdemo_ratetrans.h
.
set_param('rtwdemo_ratetrans','RateTransitionBlockCode','Inline'); slbuild('rtwdemo_ratetrans')
### Starting build procedure for: rtwdemo_ratetrans ### Successful completion of build procedure for: rtwdemo_ratetrans Build Summary Top model targets built: Model Action Rebuild Reason ================================================================================= rtwdemo_ratetrans Code generated and compiled Generated code was out of date. 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 12.189s
Теперь этот код находится в файле rtwdemo_ratetrans.h
.
hfile=fullfile(cgDir, 'rtwdemo_ratetrans_ert_rtw','rtwdemo_ratetrans.h'); rtwdemodbtype(hfile, 'typedef struct {', '} DW;', 1, 1);
typedef struct { real_T Integrator1_DSTATE[20]; real_T Integrator2_DSTATE[20]; real_T Integrator3_DSTATE[20]; real_T DetAndIntegS2F_Buffer0[20]; volatile real_T IntegOnlyS2F_Buffer[40]; real_T DetAndIntegF2S_Buffer[20]; volatile real_T IntegOnlyF2S_Buffer0[20]; real_T Integrator1_PREV_U[20]; real_T Integrator2_PREV_U[20]; real_T Integrator3_PREV_U[20]; uint32_T Algorithm_PREV_T; struct { uint_T Algorithm_RESET_ELAPS_T:1; } bitsForTID1; volatile int8_T IntegOnlyS2F_ActiveBufIdx; volatile int8_T IntegOnlyF2S_semaphoreTaken; uint8_T Integrator1_SYSTEM_ENABLE; uint8_T Integrator2_SYSTEM_ENABLE; uint8_T Integrator3_SYSTEM_ENABLE; } DW;
Для блоков Rate Transition данные о состоянии не находятся в глобальной структуре состояния, DW_rtwdemo_ratetrans_T
. Эти данные находятся в собственной структуре в файле rtwdemo_ratetrans_rtb.h
.
Теперь этот код находится в файле rtwdemo_ratetrans_rtb.c
.
cfile=fullfile(cgDir, 'rtwdemo_ratetrans_ert_rtw','rtwdemo_ratetrans.c'); rtwdemodbtype(cfile,'void rtwdemo_ratetrans_step0','void rtwdemo_ratetrans_terminate(void)', 1, 0);
void rtwdemo_ratetrans_step0(void) { int32_T i; int32_T i_0; (rtM->Timing.RateInteraction.TID0_1)++; if ((rtM->Timing.RateInteraction.TID0_1) > 1) { rtM->Timing.RateInteraction.TID0_1 = 0; } if (rtM->Timing.RateInteraction.TID0_1 == 1) { memcpy(&rtY.Out1[0], &rtDW.DetAndIntegS2F_Buffer0[0], 20U * sizeof(real_T)); } i = rtDW.IntegOnlyS2F_ActiveBufIdx * 20; for (i_0 = 0; i_0 < 20; i_0++) { rtY.Out2[i_0] = rtDW.IntegOnlyS2F_Buffer[i_0 + i]; } if (rtM->Timing.RateInteraction.TID0_1 == 1) { memcpy(&rtDW.DetAndIntegF2S_Buffer[0], &rtU.In1[0], 20U * sizeof(real_T)); } if (rtDW.IntegOnlyF2S_semaphoreTaken == 0) { for (i = 0; i < 20; i++) { rtDW.IntegOnlyF2S_Buffer0[i] = rtU.In2[i]; } } } void rtwdemo_ratetrans_step1(void) { real_T rtb_IntegOnlyF2S[20]; real_T tmp; int32_T i; uint32_T Algorithm_ELAPS_T; rtDW.IntegOnlyF2S_semaphoreTaken = 1; for (i = 0; i < 20; i++) { rtb_IntegOnlyF2S[i] = rtDW.IntegOnlyF2S_Buffer0[i]; } rtDW.IntegOnlyF2S_semaphoreTaken = 0; if (rtDW.bitsForTID1.Algorithm_RESET_ELAPS_T) { Algorithm_ELAPS_T = 0U; } else { Algorithm_ELAPS_T = rtM->Timing.clockTick1 - rtDW.Algorithm_PREV_T; } rtDW.Algorithm_PREV_T = rtM->Timing.clockTick1; rtDW.bitsForTID1.Algorithm_RESET_ELAPS_T = false; tmp = 0.001 * (real_T)Algorithm_ELAPS_T; for (i = 0; i < 20; i++) { if (rtDW.Integrator1_SYSTEM_ENABLE == 0) { rtDW.Integrator1_DSTATE[i] += tmp * rtDW.Integrator1_PREV_U[i]; } if (rtDW.Integrator2_SYSTEM_ENABLE == 0) { rtDW.Integrator2_DSTATE[i] += tmp * rtDW.Integrator2_PREV_U[i]; } if (rtDW.Integrator3_SYSTEM_ENABLE != 0) { rtY.Out3[i] = rtDW.Integrator3_DSTATE[i]; } else { rtY.Out3[i] = tmp * rtDW.Integrator3_PREV_U[i] + rtDW.Integrator3_DSTATE[i]; } rtDW.Integrator1_PREV_U[i] = rtDW.DetAndIntegF2S_Buffer[i]; rtDW.Integrator2_PREV_U[i] = rtb_IntegOnlyF2S[i]; rtDW.Integrator3_DSTATE[i] = rtY.Out3[i]; rtDW.Integrator3_PREV_U[i] = rtU.In3[i]; rtDW.DetAndIntegS2F_Buffer0[i] = rtDW.Integrator1_DSTATE[i]; } rtDW.Integrator1_SYSTEM_ENABLE = 0U; rtDW.Integrator2_SYSTEM_ENABLE = 0U; rtDW.Integrator3_SYSTEM_ENABLE = 0U; for (i = 0; i < 20; i++) { rtDW.IntegOnlyS2F_Buffer[i + (rtDW.IntegOnlyS2F_ActiveBufIdx == 0) * 20] = rtDW.Integrator2_DSTATE[i]; } rtDW.IntegOnlyS2F_ActiveBufIdx = (int8_T)(rtDW.IntegOnlyS2F_ActiveBufIdx == 0); rtM->Timing.clockTick1++; } void rtwdemo_ratetrans_initialize(void) { rtDW.bitsForTID1.Algorithm_RESET_ELAPS_T = true; rtDW.Integrator1_SYSTEM_ENABLE = 1U; rtDW.Integrator2_SYSTEM_ENABLE = 1U; rtDW.Integrator3_SYSTEM_ENABLE = 1U; }
Код встроен в функции rtwdemo_ratetrans_step0
и rtwdemo_ratetrans_step1
.
Ограничение
Генератор кода не разделяет код и данные для блоков Rate Transition, которые имеют сигналы переменного размера или находятся внутри блока For Each Subsystem.
См. также
Код блока перехода скорости (Embedded Coder)
bdclose('rtwdemo_ratetrans');
rtwdemoclean;
cd(currentDir)