以下爲看視頻筆記..........
軟件定時器是由操作系統提供的一:類系統接口,它構建在硬件定時器基礎之上(系統滴答定時器)。軟件定時器使系統能夠提供不受數目限制的定時器服務。
RT-Thread操作系統提供的軟件定時器,以系統節拍(OS Tick)的時間長度爲定時單位,提供了基於系統節拍整數倍的定時能力,即定時數值是OSTick的整數倍。例如一個OS Tick是10ms,那麼上層軟件定時器只能提供10ms,20ms,, 100ms等時間精度的定時服務,而不能定時爲15ms、25ms、35ms等。
當軟件定時器所設定的定時時間到了後,會調用用戶設置的定時器timeout回調函數,用戶需要定時運行的程序會在回調函數中得到處理。
2. 定時模式
HARDTIMER模式
HARD_ _TIMER 模式的定時器超時函數在中斷上下文環境中執行,此模式在定時器初始化時指定。在中斷上下文環境中執行時,對於超時函數的要求與中斷服務例程的要求相同:執行時間應該儘量短,執行時不應導致當前,上”下文掛起。HARD_ TIMER 模式是RT-Thread軟件定時器的默認方式。
SOFTTIMER模式
SOFTTIMER模式的定時器超時函數在系統的timer線程的線程上下文中執行。通過宏定義RT_USING_TIMER_SOFT 來決定是否啓用該模式。當啓用SOFTTIMER模式後,我們可以在定時器初始化時指定定時器工作在SOFTTIMER模式。
3. 軟件定時器控制塊
在RTT中,軟件定時器控制塊是操作系統用於管理軟件定時器的一個數據結構
struct rt_timer
{
struct rt_object parent;
rt_list_t row[RT_TIMER_SKIP_LIST_LEVEL];//定時器列表節點
void (*timeout_func)(void *parameter); //超時函數的函數指針,傳入函數給指針
void *parameter; //超時函數的參數,不用時賦值0
rt_tick_t init_tick; //定時器超時 時間,超時時間到了就調用超時函數。以系統節拍爲時間單位
rt_tick_t timeout_tick;
}
typedef struct rt_timer *rt_time_t
定義靜態軟件定時器:struct rt_timer static_timer;
定義動態軟件定時器:rt_timer_t dynamic_timer;
4. 系統提供一組API對定時器的操作
靜態定時器的初始化與脫離
void rt_timer_init(rt_timer_t timer,const char *name,void (*timeout)(void *parameter),
void *parameter,rt_tick_t time,rt_uint8_t flag)
/*第一個參數是說明定時器控制塊的地址,指明那個軟件定時器。第三個參數就是把一個函數給到函數指針,即回調函數,回調函數先寫好後傳入地址。第四個參數是回調函數的參數。第五個參數是指定軟件定時器超時時間,以系統節拍爲單位。最後一個參數可以選擇定時器工作模式:RT_TIMER_FLAG_ONE_SHOT(指定超時到了第三個函數運行的次數,即只執行一次回調函數),RT_TIMER_FLAG_PERIODIC(週期性執行回調函數),RT_TIME_FLAG_HARD_TIMER(軟件定時器工作在硬件模式),RT_TIMER_FLAG_SOFT_TIMER(軟件模式)*/
//flag參數在前兩個選一個在或上後兩個中的一個。
rt_err_t rt_timer_detach(rt_timer_t timer)
動態定時器的創建與刪除
rt_timer_t rt_rimer_creater(const char*name,void (*timeout)(void *parameter),
void *parameter,rt_tick_t time,rt_uint8_t flag)
//參數含義和靜態初始化的API一樣
rt_err_t rt_timer_delete(rt_timer_t timer)
定時器啓動
rt_err_t rt_timer_start(rt_timer_t timer)
定時器停止
rt_err_t rt_timer_stop(rt_timer_t timer)
5. 軟件定時器使用示例
在timer_sample.c中
/*
* 程序清單:定時器例程
*
* 這個例程會創建兩個動態定時器,一個是單次定時,一個是週期性定時
* 並讓週期定時器運行一段時間(10次)後停止運行
*/
#include <rtthread.h>
/* 定時器的控制塊 */
static rt_timer_t timer1;
static rt_timer_t timer2;
static int cnt = 0;
/* 定時器1超時函數 */
static void timeout1(void *parameter)
{
rt_kprintf("periodic timer is timeout %d\n", cnt);
/* 運行第10次,停止週期定時器 */
if (cnt++ >= 9)
{
rt_timer_stop(timer1);
rt_kprintf("periodic timer was stopped! \n");
}
}
/* 定時器2超時函數 */
static void timeout2(void *parameter)
{
rt_kprintf("one shot timer is timeout\n");
}
int timer_sample(void)
{
/* 創建定時器1 週期定時器 */
timer1 = rt_timer_create("timer1", timeout1, //回調函數爲timeout1
RT_NULL, 10,
RT_TIMER_FLAG_PERIODIC);//週期執行會回調函數。
/* 啓動定時器1 */
if (timer1 != RT_NULL) rt_timer_start(timer1);
/* 創建定時器2 單次定時器 */
timer2 = rt_timer_create("timer2", timeout2,//回調函數timeout2
RT_NULL, 30,
RT_TIMER_FLAG_ONE_SHOT);//執行一次回調函數
/* 啓動定時器2 */
if (timer2 != RT_NULL) rt_timer_start(timer2);
return 0;
}
/* 導出到 msh 命令列表中 */
MSH_CMD_EXPORT(timer_sample, timer sample);