これは、小さな MCU アプリケーションに適した、MISRA-C 準拠の、私の非常によく似たアプリのコードです。これは、呼び出し元アプリでの静的な「ソフトウェア タイマー」の割り当てに基づいています。プロジェクト内の複数のモジュールが同じタイマー モジュールを使用できます。これは、リンクされたリストを内部で使用してすべてのタイマーを追跡しているためです。
1ms 割り込みから tim_traverse_timers() を呼び出します。非常に高い精度が要求される場合は、関数を呼び出す前に割り込みソースをクリアして、関数自体からの「コード ジッター」オーバーヘッドがタイマーに影響を与えないようにする必要があります。
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);
...
}