Руководство программиста
Глава 2. Создание моделей блоков
§2.9. Использование таймеров
Рассматривается использование таймеров – объектов RDS, позволяющих организовать вызов модели блока через определенные промежутки времени. Описываются циклические таймеры, вызывающие модель постоянно с заданным интервалом, и однократные, вызывающие модель один раз через указанный промежуток времени и требующие явного перезапуска. Отдельно рассматриваются особенности работы модели блока с несколькими таймерами одновременно.
§2.9.1. Таймеры в RDS
Описывается создание таймеров в RDS, режимы их работы и возможные способы вызова модели блока при срабатывании таймера.
Достаточно часто модели блока приходится выполнять различные действия через заданный интервал времени. Это может быть опрос каких-либо датчиков, обновление информации на экране и т.п. RDS включает в себя набор сервисных функций, позволяющих модели создавать произвольное число таймеров и получать информацию об их срабатывании. Таймеры могут быть как однократными, срабатывающими один раз по истечении заданного интервала времени, так и циклическими, вызывающими функцию модели с заданной периодичностью.
Для создания нового таймера или изменения параметров существующего используется сервисная функция rdsSetBlockTimer, которая возвращает идентификатор созданного таймера:
RDS_TIMERID RDSCALL rdsSetBlockTimer( RDS_TIMERID timer, // Идентификатор таймера DWORD delay, // Интервал срабатывания, мс DWORD mode, // Режим и флаги BOOL start); // Запустить таймер немедленно
Первый параметр функции timer – это идентификатор таймера, параметры которого необходимо изменить, или NULL, если необходимо создать новый таймер. Параметр delay указывает интервал работы таймера в миллисекундах. Если логический параметр start – истина (TRUE), созданный или измененный таймер будет немедленно запущен и начнет отсчитывать время до интервала delay, в противном случае он будет ждать команды запуска. И, наконец, в параметре mode передается режим работы таймера, способ информирования модели о его срабатывании, а также дополнительные флаги, объединенные побитовой операцией ИЛИ (или простым сложением) в одно целое число типа DWORD.
Таймер может работать в одном из трех режимов:
- RDS_TIMERM_LOOP – циклическая работа. Отсчитав заданный интервал времени, таймер уведомляет об этом модель и автоматически перезапускается. Этот режим используется в тех случаях, когда модели необходимо получать сигнал от таймера через равные промежутки времени.
- RDS_TIMERM_STOP – однократное срабатывание. Запущенный таймер отсчитывает заданный интервал, уведомляет модель и останавливается. После этого его, при необходимости, можно запустить снова. Этот режим используется для создания задержек, или в тех случаях, когда нужно динамически менять интервал срабатывания у постоянно работающего таймера.
- RDS_TIMERM_DELETE – однократное срабатывание с автоматическим удалением таймера. Запущенный таймер отсчитывает заданный интервал, сообщает об этом модели и удаляется. Этот режим удобен для блоков, достаточно редко выполняющих какое-либо действие с задержкой.
Таймер уведомляет модель о своем срабатывании несколькими разными способами:
- RDS_TIMERS_SIGNAL – при срабатывании таймера первой сигнальной переменной блока (то есть сигналу запуска, по умолчанию он называется «Start») присваивается значение 1. Таким образом, если блок в режиме расчета работает по сигналу, модель блока будет автоматически вызвана в режиме RDS_BFM_MODEL в первом после срабатывания таймера такте расчета. Никаких других вызовов модели при срабатывании таймера не производится. Такое уведомление удобно тем, что в текст модели блока не нужно добавлять каких-либо новых реакций, однако, модель в данном случае не сможет определить, вызвана она из-за срабатывания таймера или из-за срабатывания связи, подключенной к сигнальному входу запуска.
- RDS_TIMERS_TIMER – при срабатывании таймера модель вызывается в потоке расчета в режиме RDS_BFM_TIMER. При этом в третьем параметре функции модели (LPVOID ExtParam) передается идентификатор сработавшего таймера.
- RDS_TIMERS_WINREF – при срабатывании таймера модель блока вызывается в главном потоке в режиме RDS_BFM_WINREFRESH. Этот способ используется для обновления окон, принадлежащих блокам. В третьем параметре функции модели при этом передается указатель на структуру RDS_WINREFRESHDATA, по полям которой модель может понять, вызвана ли необходимость обновлять окна таймером или вызовом сервисной функции, и если таймером, то каким именно.
- RDS_TIMERS_SYSTIMER – при срабатывании таймера модель вызывается в главном потоке в режиме RDS_BFM_TIMER. От всех остальных способов срабатывания, включая RDS_TIMERS_TIMER (при котором модель вызывается в этом же режиме, но в потоке расчета) этот отличается тем, что таймер работает не только в режиме расчета, но и в режимах редактирования и моделирования. Таймеры, для которых указаны способы срабатывания RDS_TIMERS_SIGNAL, RDS_TIMERS_TIMER и RDS_TIMERS_WINREF, останавливаются в момент остановки расчета и продолжают работу при его повторном запуске. Таймер RDS_TIMERS_SYSTIMER работает все время, вне зависимости от режима работы RDS.
Вместе со способом уведомления модели RDS_TIMERS_WINREF можно, при необходимости, указать флаг RDS_TIMERF_FIXFREQ – это исключит данный таймер из автоподстройки частоты обновления окон. При включенной автоподстройке RDS постоянно вычисляет суммарное время обновления всех окон системы, и, если это время будет слишком большим, частота обновления будет автоматически понижаться. Если в параметрах таймера указать флаг RDS_TIMERF_FIXFREQ, его частота изменяться не будет. При всех остальных способах уведомления модели о срабатывании таймера никакой автоподстройки не происходит и этот флаг игнорируется.