裸機開發利器:超精簡的軟件定時器multi_timer ---- 使用、代碼分析和修改

一、概括

在裸機開發中,經常要使用定時器來實現某些定時功能,面對需要比較多定時器的場合,以前都是使用一個吻硬件定時器作爲提供時間基準,然後使用計數器+標誌位的方法來實現,其實就是採用時間片的方法。
比如:

while(1)
{
	// 2ms執行 軟件時鐘系統
	if(1 == sys_var._1msFlag)  
	{
	   sys._1msFlag = 0;	// 該標誌由定時器中斷置位
	
	   clock_system();      // 管理各種時間標誌(將各個時鐘標誌置位)
	}
	
	// 200ms執行
	if(1 == sys_var.System200msFlag)
	{   
	    sys_var.System200msFlag = 0;
	    // 執行各種任務
	}
}

現在發現了某位大佬開源的軟件定時器multi_timer項目,令人耳目一新。
很棒的是,軟件定時器multi_timer 將上面的方法抽象出來,同樣也是基於一個硬件定時器,但是無需自己在while循環上加各種判斷語句,讓程序看起來更加簡潔,更加好維護。

二、使用和代碼分析

這邊文章《超輕量級網紅軟件定時器multi_timer(51+stm32雙平臺實戰)》已經將軟件定時器multi_timer的使用和代碼分析講的非常清楚了,我就不贅述了。

三、項目源代碼和個人的註釋

  • multi_timer.h
/*
 * Copyright (c) 2016 Zibin Zheng <[email protected]>
 * All rights reserved
 */
#ifndef _MULTI_TIMER_H_
#define _MULTI_TIMER_H_

#include "stdint.h"

typedef struct Timer {
    uint32_t timeout;   		// 超時時間(用來與定時器心跳比較)
    uint32_t repeat;			// 循環定時觸發時間(週期定時設置),爲0時代表單次定時
    void (*timeout_cb)(void);	// 定時器回調處理函數
    struct Timer* next;			// 指向下一個定時器節點
}Timer;

#ifdef __cplusplus  
extern "C" {  
#endif  

void timer_init(struct Timer* handle, void(*timeout_cb)(), uint32_t timeout, uint32_t repeat);
int  timer_start(struct Timer* handle);
void timer_stop(struct Timer* handle);
void timer_ticks(void);
void timer_loop(void);

#ifdef __cplusplus
} 
#endif

#endif
  • multi_timer.c
/*
 * Copyright (c) 2016 Zibin Zheng <[email protected]>
 * All rights reserved
 */
#include "multi_timer.h"
//timer handle list head.
static struct Timer* head_handle = NULL;
//Timer ticks
static uint32_t _timer_ticks = 0;

/**
  * @brief  Initializes the timer struct handle.
  * @param  handle: the timer handle strcut.
  * @param  timeout_cb: timeout callback.
  * @param  repeat: repeat interval time.
  * @retval None
  */
void timer_init(struct Timer* handle, void(*timeout_cb)(), uint32_t timeout, uint32_t repeat)
{
	handle->timeout_cb = timeout_cb;
	handle->timeout = _timer_ticks + timeout;
	handle->repeat = repeat;
}

/**
  * @brief  Start the timer work, add the handle into work list.
  * @param  btn: target handle strcut.
  * @retval 0: succeed. -1: already exist.
  */
int timer_start(struct Timer* handle)
{
    struct Timer* target = head_handle; // 設置一個臨時變量就不會改變

	// 遍歷查找判斷該節點是否已存在
    while(target) 
    {
        if(target == handle) return -1;	//already exist.

        target = target->next; // 不斷遍歷下一個節點
    }

	// 採用鏈表前插的方式,最新的定時器放在前面並作爲頭結點
    handle->next = head_handle;
    head_handle = handle;
    return 0;
}

/**
  * @brief  Stop the timer work, remove the handle off work list.
  * @param  handle: target handle strcut.
  * @retval None
  */
void timer_stop(struct Timer* handle)
{
	struct Timer** curr;
	for(curr = &head_handle; *curr; ) {
		struct Timer* entry = *curr;
		if (entry == handle) {
			*curr = entry->next; // 將當前節點脫離隊列
		} else
			curr = &entry->next; // 二級指針curr不斷後移
	}
}

/**
  * @brief  main loop.
  * @param  None.
  * @retval None
  */
void timer_loop() // 在While循環中使用,定時器纔會起作用
{
	struct Timer* target;
	for(target=head_handle; target; target=target->next) {
		if(_timer_ticks >= target->timeout) {
			if(target->repeat == 0) {
				timer_stop(target);
			} else {
				target->timeout = _timer_ticks + target->repeat;
			}
			target->timeout_cb();
		}
	}
}

/**
  * @brief  background ticks, timer repeat invoking interval 1ms.
  * @param  None.
  * @retval None.
  */
void timer_ticks() // 在定時器中斷中調用該函數
{
	_timer_ticks++;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章