Список временных задач - PullRequest
       23

Список временных задач

2 голосов
/ 16 февраля 2011

Ищу помощь по встроенному приложению на 16-битном устройстве. Мне нужно запустить несколько простых «задач / функций» через указатели функций. Эти задачи выполняются с заранее заданными интервалами.

typedef struct
{
  int  timeToRun;
  void (*fcn)(void);

} task_t;

task_t tasks[] =
{
  { 13_MSEC,  fcn1 },
  { 50_MSEC,  fcn2 },
  { 0, NULL }
};

volatile unsigned int time;   

main()
{

  for (ptr = tasks; ptr->timeToRun !=0; ptr++)
  {
    if (!(time % ptr->timeToRun))
       (ptr->fcn)();
  }
}

У меня есть возможность запустить прерывание по таймеру на 1 мс.

interrupt void TimerTick(void)
{
 time++;
}

Есть идеи, как рассчитать прошедшее время? Как убедиться, что% (по модулю) работает с определенной скоростью, если время переполнено. В любом случае, как избежать переполнения времени и иметь правильную синхронизацию через% (по модулю)?

Ответы [ 2 ]

2 голосов
/ 16 февраля 2011

Вот код из моего очень похожего приложения, подходящего для небольших приложений MCU, и совместимого с MISRA-C.Он основан на статическом размещении «программных таймеров» в вызывающем приложении.Несколько модулей в вашем проекте могут использовать один и тот же модуль таймера, поскольку он использует внутренний список для отслеживания всех таймеров.

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

Если вам нужнодля более длительных задержек, чем 65535 мс, просто измените счетчик и интервал на uint32.

    typedef struct timer
    {
      struct timer* next;                            /* Next timer in the linked list   */

      uint16 counter;                                /* 16-bit timer counter            */
      uint16 interval;                               /* The interval between triggers   */
      BOOL   is_enabled;                             /* Timer enabled/disabled          */

      void (*callback_func)(void);                   /* Callback timer function         */

    } Timer;



    static Timer* timer_list;


    void tim_init (void)
    {
      timer_list = NULL;
    }

    void tim_add (Timer*   timer,
                  void (*  callback_func)(void),
                  uint16   interval_ms,
                  BOOL     enabled)
    {
      tim_enable_interrupt (FALSE);                  /* hardware function disabling timer interrupt */

      timer->callback_func  = callback_func;
      timer->counter        = 0U;
      timer->interval       = interval_ms;
      timer->is_enabled     = enabled;

      timer->next           = timer_list;
      timer_list            = timer;

      tim_enable_interrupt (TRUE);
    }



    void tim_enable (Timer* timer, BOOL enable)
    {
      if(enable)
      {
        timer->counter    = 0U;                      /* Reset counter each time function is called */
      }

      timer->is_enabled = enable;
    }

    void tim_traverse_timers  (void)
    {
      Timer* timer;

      for(timer=timer_list; timer!=NULL; timer=timer->next)
      {
        if(timer->is_enabled == TRUE)
        {
          timer->counter++;

          if(timer->counter == timer->interval)
          {
            timer->counter = 0U;
            timer->callback_func();
          }

        }
      }
    }

#include "timer.h"

void my_func (void);  /* lights some LED etc... */
void my_other_func (void);

void main (void)
{
  Timer some_task;
  Timer some_other_task;
  ...

  tim_init();
  ...

  tim_add(&some_task, &my_func, SOME_DELAY_IN_MS, TRUE);
  tim_add(&some_other_task, &my_other_func, SOME_OTHER_DELAY_IN_MS, TRUE);
  ...


}
0 голосов
/ 16 февраля 2011

Я бы сделал что-то вроде этого:

typedef struct
{
  unsigned int nextRunTime
  int  period;
  unsigned int  rollover;
  void (*fcn)(void);
} task_t;


main()
{
  //setup goes here
  /*...*/
  //loop
  while (1)
  {
     for (ptr = tasks; ptr->period!=0; ptr++)
     {
       if ((time > ptr->nextRunTime) && (time <= ptr->rollover) )
       {
           ptr->nextRunTime+=ptr->period;
           ptr->rollover = (ptr->nextRunTime < ptr->period)? 2*ptr->period : 0xFFFF;
           (ptr->fcn)();
       }
       ptr->nextRunTime = timeToRun;
     }
  }
}

Это должно работать до тех пор, пока вы можете гарантировать, что а) ни один из периодов не больше половины времени пролонгации (0x8000 мс), ивыполнить все функции в кратчайшие сроки.

...