Список цеховой задачи
Вопрос
Я ищу помощь в встроенном приложении на 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++;
}
.
Есть идеи, как рассчитать прошедшее время?Как убедиться, что% (Modulo) работает в опасном ставке, если переполнение времени.Во всяком случае, как избежать переполнения времени и иметь правильное время с временем через% (модуло)?
Решение
Я бы сделал что-то подобное:
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 мс), а б) вы можете выполнить все функции в течение кратчайшего периода.
Другие советы
Вот какой-то код от очень похожего приложения моего, подходит для небольших приложений 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);
...
}
.