Question

Je cherche de l'aide sur une application intégrée sur le périphérique 16 bits. Je dois exécuter plusieurs "tâches / fonctions simples" via des pointeurs de fonction.Ces tâches fonctionnent dans des intervalles prédéterminés.

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)();
  }
}

J'ai la possibilité d'exécuter une interruption de minuterie à 1 ms.

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

Une idée de la façon de calculer le temps écoulé?Comment s'assurer que% (modulo) fonctionne dans le taux défini si le temps déborde.Quoi qu'il en soit, comment éviter le débordement de temps et avoir le timing correct via% (modulo)?

Était-ce utile?

La solution

Je ferais quelque chose comme ça:

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;
     }
  }
}

Ceci devrait fonctionner aussi longtemps que vous pouvez garantir la moitié de la moitié de la moitié du temps de roulement (0x8000 ms), et b) Vous pouvez exécuter toutes les fonctions dans la période la plus courte.

Autres conseils

Voici un certain code d'une application très similaire de mienne, adaptée aux petites applications MCU et à MISRA-C Conforme.Il est basé sur l'attribution de «minuteries logicielles» statiquement dans l'application appelante.Plusieurs modules de votre projet peuvent utiliser le même module de minuterie, car il utilise une liste liée en interne pour garder une trace de toutes les minuteries.

Call Tim_traverse_timers () à partir de votre interruption de 1 ms.Si vous avez des exigences de précision très élevées, vous devrez peut-être effacer la source d'interruption avant d'appeler la fonction, de sorte que la "gabarit de code" de la fonction elle-même n'affecte pas la minuterie.

Si vous avez besoin de retards plus longs, puis de 65535ms, changez simplement le compteur et l'intervalle à 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);
  ...


}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top