Навигация:
<< >> Оглавление Указатель
Текст С++

Руководство программиста

Глава 2. Создание моделей блоков

§2.9. Использование таймеров

§2.9.3. Однократно срабатывающий таймер

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

В приведенном в §2.9.2 примере использовался циклический таймер – рассмотрим теперь работу с однократно срабатывающим. Допустим, нам нужен похожий индикатор, но скважность его мигания не должна равняться двум, то есть время «горения» и время «паузы» индикатора должно быть разным. Создадим блок, который при единичном значении входа «Flash» будет зажигаться на 500 миллисекунд, затем гаснуть на одну секунду, затем снова зажигаться на 500 мс и т.д. Циклический таймер нам здесь не поможет – интервал между его срабатываниями постоянен. Воспользуемся однократно срабатывающим таймером, запуская его то на 500 мс, то на тысячу. При той же структуре переменных модель нового блока будет очень похожа на модель из предыдущего примера с некоторыми отличиями (выделены цветом):

  //====== Модель неравномерно мигающего блока ======
  // Функция модели блока
  extern "C" __declspec(dllexport) int  SimpleFlash1(
          int CallMode,
           BlockData,
           ExtParam)
  {
  // 
  #define pStart ((char *)(BlockData->VarTreeData))
  #define Start (*((char *)(pStart)))
  #define Ready (*((char *)(pStart+RDS_VSZ_S)))
  #define Flash (*((char *)(pStart+2*RDS_VSZ_S)))
  #define State (*((char *)(pStart+2*RDS_VSZ_S+RDS_VSZ_L)))
    // Вспомогательная переменная – указатель на личную область
    // В личной области хранится только идентификатор таймера
     *data=(*)(BlockData->BlockData);
     descr;

    switch(CallMode)
      { // Инициализация блока
        case :
          // Отводим место для хранения идентификатора таймера
          BlockData->BlockData=data=new ;
          // Создаем таймер, интервал пока не устанавливаем
          *data=(NULL,0,
                  |,FALSE);
          break;

        // Очистка данных блока
        case :
          // Уничтожаем таймер
          (*data);
          // Освобождаем память, где он хранился
          delete data;
          break;

        // Проверка типа статических переменных
        case :
          if(strcmp((char*)ExtParam,"{SSLL}"))
            return ;
          return ;

        // Такт расчета
        case :
          // Запрашиваем параметры таймера
          descr.servSize=sizeof(descr);
          (*data,&descr);
          if(Flash) // Включаем мигание, если таймер остановлен
            { if(!descr.On) // Таймер остановлен
                { // Запускаем таймер на 500 мс
                  (*data,500);
                  State=1;
                }
            }
          else // Выключаем мигание, если таймер работает
            { if(descr.On) // Таймер работает
                { // Останавливаем таймер
                  (*data);
                  State=0;
                }
            }
          break;

// Срабатывание таймера case : if(State) // Индикатор был "зажжен" { // Гасим и запускаем таймер на 1 сек State=0; (*data,1000); } else // Индикатор был "погашен" { // Зажигаем и запускаем таймер на 500 мс State=1; (*data,500); } break;
} return ; // Отмена макроопределений для переменных #undef State #undef Flash #undef Ready #undef Start #undef pStart } //=================================================

Фактически, в модели изменились только параметры функции создания таймера и реакция на срабатывание таймера. Таймер теперь создается с параметром RDS_TIMERM_STOP вместо (однократное срабатывание вместо циклического). В реакции на срабатывание таймера (RDS_BFM_TIMER) теперь анализируется значение переменной State. Если оно равно 1 (индикатор был зажжен), ей присваивается 0 и таймер запускается на одну секунду для отработки паузы. Если же оно равно нулю (индикатор погашен), ей присваивается единица и таймер запускается на 500 мс для отработки «горения». Таким образом, остановившийся таймер немедленно перезапускается с новым значением задержки.

Реакцию на срабатывание таймера можно переписать компактнее – в тексте модели выше она просто расписана подробно с комментариями для большей ясности программы. Те же действия могут быть выполнены и так:

        case :
          (*data,State?1000:500);
          State=!State;
          break;

Мы в любом случае заново запускаем таймер, просто его интервал зависит от значения State. Само значение State инвертируется, как и в предыдущей модели с циклическим таймером.


<< >> Оглавление Указатель