Вот код из моего очень похожего приложения, подходящего для небольших приложений 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);
...
}