0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

嵌入式軟件實現(xiàn)定時器的方法分析

嵌入式開發(fā)愛好者 ? 來源:嵌入式開發(fā)愛好者 ? 2023-05-12 13:54 ? 次閱讀

簡介

在一般的嵌入式產(chǎn)品設(shè)計中,介于成本、功耗等,所選型的MCU基本都是資源受限的,而里面的定時器的數(shù)量更是有限。在我們軟件設(shè)計中往往有多種定時需求,例如脈沖輸出、按鍵檢測、LCD切屏延時等等 ,我們不可能讓每一個定時業(yè)務(wù)都去開一個硬件定時器,一來硬件資源可能不足,二來會使軟件過度依賴于硬件平臺,從而導(dǎo)致較差的可移植性。

如果我們有一個軟件定時器,所有定時業(yè)務(wù)都依賴于軟件定時器,不僅節(jié)省硬件資源,以后在移植的時候也只需要將軟件定時器和硬件相關(guān)的部分修改就行了,其他部分都不用動。

軟件定時器實現(xiàn)方式:

一、用結(jié)構(gòu)體數(shù)組的方式實現(xiàn)軟件定時器

用結(jié)構(gòu)體數(shù)組的方式實現(xiàn)起來較簡單,也容易理解,除此之外與之后的鏈表實現(xiàn)方式比起來沒有其他優(yōu)點。

但還是介紹一下實現(xiàn)方法:在結(jié)構(gòu)體數(shù)組內(nèi)定義一個start標志和定時時長duration,還有一個為計數(shù)值count,這3個變量為最基本的3個變量,其他的可以自己補充,比如運行模式、回調(diào)函數(shù)指針等。還有就是每一個結(jié)構(gòu)體數(shù)組就是一個定時器,需要我們提前定義好這個結(jié)構(gòu)體數(shù)組有多大。

定義好之后,在開啟定時器的時候我們將對應(yīng)的數(shù)組內(nèi)start標志置位,在硬件tick中斷服務(wù)函數(shù)里面我們?nèi)ゲ樗薪Y(jié)構(gòu)體數(shù)組內(nèi)的start標志是否置位,當(dāng)查到當(dāng)前start被置位時,將此數(shù)組內(nèi)的duration和count做比較,如果相等就說明此定時器定時時間到了,如果不等就將count++,然后接著查其他數(shù)組的start標志,以此無限循環(huán)。

此種方式缺點非常明顯,那就是在硬件tick中斷服務(wù)函數(shù)內(nèi),我們得輪詢所有數(shù)組,如果我們軟件業(yè)務(wù)需求是20個定時任務(wù),那我們就得在軟件定時器的實現(xiàn)里定義20個數(shù)組,空間浪費倒是其次的,關(guān)鍵是硬件tick輪詢的數(shù)組越多,執(zhí)行到某個數(shù)組的時間就越長,若以后有50個、100個定時需求時,將會導(dǎo)致定時時間極不精準。

二、用鏈表實現(xiàn)軟件定時器

介于以上用結(jié)構(gòu)體數(shù)組實現(xiàn)軟件定時器的種種缺點,我們提出改進方案。經(jīng)過分析,在大多數(shù)定時業(yè)務(wù)中,往往只需要在某個時間段定時一次,也就是說定時器會開啟定時和結(jié)束定時,當(dāng)然,用數(shù)組的實現(xiàn)的定時器也可以開啟定時和關(guān)閉定時,只需要用start標志去決定就行了,但是用數(shù)組實現(xiàn)的方式中,即使你關(guān)閉了定時器,也就是去掉了start標志,此定時器雖然不運行了,但是數(shù)組的空間不會減少,硬件 tick依然要輪詢所有數(shù)組。

所以我們需要用鏈表來實現(xiàn)軟件定時器,在硬件tick中輪詢所有節(jié)點,開啟一個定時器就加入一個節(jié)點,關(guān)閉定時器就刪除一個節(jié)點,可以保證在當(dāng)前時刻只輪詢需要定時的節(jié)點,可以極大的保證定時準確性。

在加上可以讓用戶選擇定時時間到了直接在硬件tick內(nèi)執(zhí)行或者在硬件tick內(nèi)置標志,然后在while循環(huán)內(nèi)排隊執(zhí)行,可以非常有效的解決關(guān)鍵業(yè)務(wù)定時不精準的問題,比如脈沖輸出這種需要定時準確的業(yè)務(wù)。

鏈表實現(xiàn)方式

H文件:

/**
*sfor_timer_list.h
*鏈表實現(xiàn)的軟件定時器庫
*/
#ifndef__SOFT_TIMER_LIST_H
#define__SOFT_TIMER_LIST_H

/**
*硬件中斷tick
*/
#defineTIMER_HARD_TICK100U//ms,硬件tick取決于硬件定時中斷時間
#defineTIMER_200MS_TICK(200U/TIMER_HARD_TICK)//TIMER_HARD_TICK*(2)=100mS
#defineTIMER_SEC_TICK(1000U/TIMER_HARD_TICK)//TIMER_HARD_TICK*(20)=1S


/**
*定時模式選擇
*/
typedefenum
{
ONCE_MODE,/*單次定時模式,即超時后自動關(guān)閉定時器*/
CONTINUE_MODE,/*持續(xù)定時模式,只要開啟除非手動關(guān)閉否則永不停歇*/
DEFINE_NUM_MODE,/*定義次數(shù)的模式,運行指定的次數(shù)后關(guān)閉定時器*/
}TimerTimingModeType;

/**
*定時超時后運行的回調(diào)函數(shù)可以選擇在中斷直接運行或者掛起任務(wù)輪詢執(zhí)行
*只要在定時需求準確的時候才建議選擇中斷模式執(zhí)行,類似無磁傳感器脈沖測量
*像一些超時判斷類的應(yīng)用以輪詢的方式進行執(zhí)行
*中斷執(zhí)行模式越多,其他定時器越不準,畢竟中斷允許占時間,查詢其他定時器時
*會有延時
*/
typedefenum
{
RUN_IN_LOOP_MODE,/*輪詢執(zhí)行模式*/
RUN_IN_INTERRUPT_MODE,/*中斷實時執(zhí)行模式*/
}TimerRunModeType;

/**
*軟件定時器基本類型
*/
typedefstructSoftTimer
{
unsignedlongcounter;/*計數(shù)*/
unsignedlongduration;/*定時時長*/
unsignedlongrun_num;/*自定義的定時次數(shù)*/
BOOLstart_flag;/*啟動標志*/
BOOLloop_flag;/*輪詢標志*/
TimerRunModeTyperun_mode;
TimerTimingModeTypetiming_mode;
void(*callback_function)(void);/*回調(diào)函數(shù)*/
structSoftTimer*next;
}SoftTimer;

/*
*初始化軟件定時器的硬件tick
*/
externvoidsoft_timer_tick_init(void);

/*
*創(chuàng)建一個只運行一次的軟件定時器并立刻開始計時
*參數(shù)表:p:定時器結(jié)構(gòu)體指針,由用戶創(chuàng)建
*mode:選擇運行模式,可選定時器到了之后是直接在tick中斷內(nèi)執(zhí)行還是置起標志在while循環(huán)內(nèi)輪詢執(zhí)行
*duration:要計時的時長,單位為硬件中斷的tick
*timeout_handler:定時到了之后要執(zhí)行的函數(shù)指針
* return:無
*/
externvoidcreat_single_soft_timer(SoftTimer*p,TimerRunModeTypemode,unsignedlongduration,void(*timeout_handler)(void));

/*
*創(chuàng)建永遠運行的軟件定時器并立刻開始計時
*參數(shù)表:p:定時器結(jié)構(gòu)體指針,由用戶創(chuàng)建
*mode:選擇運行模式,可選定時器到了之后是直接在tick中斷內(nèi)執(zhí)行還是置起標志在while循環(huán)內(nèi)輪詢執(zhí)行
*duration:要計時的時長,單位為硬件中斷的tick
*timeout_handler:定時到了之后要執(zhí)行的函數(shù)指針
* return:無
*/
externvoidcreat_continue_soft_timer(SoftTimer*p,TimerRunModeTypemode,unsignedlongduration,void(*timeout_handler)(void));

/*
*創(chuàng)建指定次數(shù)運行的軟件定時器并立刻開始計時
*參數(shù)表:p:定時器結(jié)構(gòu)體指針,由用戶創(chuàng)建
*mode:選擇運行模式,可選定時器到了之后是直接在tick中斷內(nèi)執(zhí)行還是置起標志在while循環(huán)內(nèi)輪詢執(zhí)行
* run_num:要定時的次數(shù),比如1就是定時1次,5就是定時5次以后自動關(guān)閉定時器
*duration:要計時的時長,單位為硬件中斷的tick
*timeout_handler:定時到了之后要執(zhí)行的函數(shù)指針
* return:無
*/
externvoidcreat_limit_num_soft_timer(SoftTimer*p,TimerRunModeTypemode,unsignedlongrun_num,unsignedlongduration,void(*timeout_handler)(void));


/*
*重啟指定的單次軟件定時器
*參數(shù)表:p:定時器結(jié)構(gòu)體指針,由用戶創(chuàng)建
*mode:選擇運行模式,可選定時器到了之后是直接在tick中斷內(nèi)執(zhí)行還是置起標志在while循環(huán)內(nèi)輪詢執(zhí)行
*duration:要計時的時長,單位為硬件中斷的tick
*timeout_handler:定時到了之后要執(zhí)行的函數(shù)指針
* return:無
*/
externvoidrestart_single_soft_timer(SoftTimer*p,TimerRunModeTypemode,unsignedlongduration,void(*timeout_handler)(void));

/**
*刪除一個軟件定時器
*/
externvoidstop_timer(SoftTimer*p);


/**
*系統(tǒng)main循環(huán)進程,用于執(zhí)行輪詢模式的回調(diào)函數(shù)
*/
externvoidsoft_timer_main_loop(void);


/**
*此函數(shù)為tick中斷服務(wù)函數(shù),需要掛載在外部硬件定時器上
*因此軟件定時器的定時精度由此函數(shù)掛載的硬件定時時間決定,
*比如此函數(shù)掛載在定時50ms的外部定時器上,那么定時dutation
*為20時定時時間就是20*50ms=1S
*/
externvoidsystem_tick_IrqHandler(void);

#endif/*!1__SOFT_TIMER_LIST_H*/

C文件:

/**
*sfor_timer_list.c
*鏈表實現(xiàn)的軟件定時器庫
*/
#defineNULL((void*)0)
typedefenum{FALSE=0,TRUE=!FALSE}BOOL;

#include"meter_include.h"http://包含用戶的硬件定時器初始化函數(shù)
#include"soft_timer_list.h"

/**
*軟件定時器內(nèi)部變量
*/
staticSoftTimer*head_point=NULL;

staticstructSoftTimer*creat_node(SoftTimer*node);
staticchardelete_node(SoftTimer*node);
staticBOOLis_node_already_creat(SoftTimer*node);


/**
*初始化軟件定時器的硬件tick
*/
voidsoft_timer_tick_init(void)
{
R_IT_Create();/*由用戶初始化一個硬件定時器,當(dāng)前tick100ms*/
R_IT_Start();
}

/**
*系統(tǒng)main循環(huán)進程,用于執(zhí)行輪詢模式的回調(diào)函數(shù)
*/
voidsoft_timer_main_loop(void)
{
structSoftTimer*p1=head_point;

while(p1!=NULL)//下一個節(jié)點如果不為空
{
if(p1->loop_flag==TRUE)
{
p1->loop_flag=FALSE;
p1->callback_function();
if(p1->start_flag!=TRUE)
delete_node(p1);/*如果定時器被刪除就刪除節(jié)點*/
}
/*尋找下一個有意義的節(jié)點*/
p1=p1->next;
}
}

/*
*創(chuàng)建一個只運行一次的軟件定時器并立刻開始計時
*參數(shù)表:p:定時器結(jié)構(gòu)體指針,由用戶創(chuàng)建
*mode:選擇運行模式,可選定時器到了之后是直接在tick中斷內(nèi)執(zhí)行還是置起標志在while循環(huán)內(nèi)輪詢執(zhí)行
*duration:要計時的時長,單位為硬件中斷的tick
*timeout_handler:定時到了之后要執(zhí)行的函數(shù)指針
* return:無
*/
voidcreat_single_soft_timer(SoftTimer*p,TimerRunModeTypemode,unsignedlongduration,void(*timeout_handler)(void))
{
if((p==NULL)||(timeout_handler==NULL)||duration==0)return;

p->start_flag=TRUE;
p->counter=0;
p->loop_flag=FALSE;
p->duration=duration;
if(mode==RUN_IN_LOOP_MODE)
p->run_mode=RUN_IN_LOOP_MODE;
else
p->run_mode=RUN_IN_INTERRUPT_MODE;
p->callback_function=timeout_handler;
p->timing_mode=ONCE_MODE;
p->run_num=0;/*只有在自定義運行次數(shù)的情況下此值才有效*/
head_point=creat_node(p);
}

/*
*創(chuàng)建永遠運行的軟件定時器并立刻開始計時
*參數(shù)表:p:定時器結(jié)構(gòu)體指針,由用戶創(chuàng)建
*mode:選擇運行模式,可選定時器到了之后是直接在tick中斷內(nèi)執(zhí)行(除非實在必要)還是置起標志在while循環(huán)內(nèi)輪詢執(zhí)行
*duration:要計時的時長,單位為硬件中斷的tick
*timeout_handler:定時到了之后要執(zhí)行的函數(shù)指針
* return:無
*/
voidcreat_continue_soft_timer(SoftTimer*p,TimerRunModeTypemode,unsignedlongduration,void(*timeout_handler)(void))
{
if((p==NULL)||(timeout_handler==NULL)||duration==0)return;

p->start_flag=TRUE;
p->counter=0;
p->loop_flag=FALSE;
p->duration=duration;
if(mode==RUN_IN_LOOP_MODE)
p->run_mode=RUN_IN_LOOP_MODE;
else
p->run_mode=RUN_IN_INTERRUPT_MODE;
p->callback_function=timeout_handler;
p->timing_mode=CONTINUE_MODE;
p->run_num=0;/*只有在自定義運行次數(shù)的情況下此值才有效*/
head_point=creat_node(p);
}



/*
*創(chuàng)建指定次數(shù)運行的軟件定時器并立刻開始計時
*參數(shù)表:p:定時器結(jié)構(gòu)體指針,由用戶創(chuàng)建
*mode:選擇運行模式,可選定時器到了之后是直接在tick中斷內(nèi)執(zhí)行還是置起標志在while循環(huán)內(nèi)輪詢執(zhí)行
* run_num:要定時的次數(shù),比如1就是定時1次,5就是定時5次以后自動關(guān)閉定時器
*duration:要計時的時長,單位為硬件中斷的tick
*timeout_handler:定時到了之后要執(zhí)行的函數(shù)指針
* return:無
*/
voidcreat_limit_num_soft_timer(SoftTimer*p,TimerRunModeTypemode,unsignedlongrun_num,unsignedlongduration,void(*timeout_handler)(void))
{
if((p==NULL)||(timeout_handler==NULL)||duration==0)return;
p->start_flag=TRUE;
p->counter=0;
p->loop_flag=FALSE;
p->duration=duration;
if(mode==RUN_IN_LOOP_MODE)
p->run_mode=RUN_IN_LOOP_MODE;
else
p->run_mode=RUN_IN_INTERRUPT_MODE;
p->callback_function=timeout_handler;
p->timing_mode=DEFINE_NUM_MODE;
p->run_num=run_num;/*只有在自定義運行次數(shù)的情況下此值才有效*/
head_point=creat_node(p);
}


/*
*重啟指定的單次軟件定時器
*參數(shù)表:p:定時器結(jié)構(gòu)體指針,由用戶創(chuàng)建
*mode:選擇運行模式,可選定時器到了之后是直接在tick中斷內(nèi)執(zhí)行還是置起標志在while循環(huán)內(nèi)輪詢執(zhí)行
*duration:要計時的時長,單位為硬件中斷的tick
*timeout_handler:定時到了之后要執(zhí)行的函數(shù)指針
* return:無
*/
voidrestart_single_soft_timer(SoftTimer*p,TimerRunModeTypemode,unsignedlongduration,void(*timeout_handler)(void))
{
if((p==NULL)||(timeout_handler==NULL)||duration==0)return;

p->start_flag=TRUE;
p->counter=0;
p->loop_flag=FALSE;
p->duration=duration;
if(mode==RUN_IN_LOOP_MODE)
p->run_mode=RUN_IN_LOOP_MODE;
else
p->run_mode=RUN_IN_INTERRUPT_MODE;
p->callback_function=timeout_handler;
p->timing_mode=ONCE_MODE;
p->run_num=0;/*只有在自定義運行次數(shù)的情況下此值才有效*/
if(is_node_already_creat(p)!=TRUE)/*若之前的節(jié)點已被刪除就重新創(chuàng)建*/
head_point=creat_node(p);
}


/**
*封裝后給用戶使用
*/
voidstop_timer(SoftTimer*p)
{
if(p!=NULL){
p->counter=0;
p->start_flag=FALSE;
delete_node(p);
}
}


staticstructSoftTimer*creat_node(SoftTimer*node)
{
structSoftTimer*p1;//p1保存當(dāng)前需要檢查的節(jié)點的地址
if(node==NULL)
returnhead_point;

if(is_node_already_creat(node)!=FALSE){
delete_node(node);/*當(dāng)節(jié)點已經(jīng)存在的時候在這里選擇退出還是刪除后重新創(chuàng)建,目前重新創(chuàng)建*/
}
//當(dāng)頭節(jié)點為空時,將傳入的節(jié)點作為頭節(jié)點,返回頭節(jié)點
if(head_point==NULL){
head_point=node;
node->next=NULL;
returnhead_point;
}
p1=head_point;
while(p1->next!=NULL)
{
p1=p1->next;//后移一個節(jié)點
}

if(p1->next==NULL)//將該節(jié)點插入鏈表的末尾
{
p1->next=node;
node->next=NULL;
}
else
{

}
returnhead_point;
}


staticchardelete_node(SoftTimer*node)
{
structSoftTimer*p1;//p1保存當(dāng)前需要檢查的節(jié)點的地址
structSoftTimer*temp;
if(node==NULL)
return1;

p1=head_point;
if(node==head_point){
head_point=head_point->next;/*如果要刪除頭指針,就將頭指針后移*/
}else{
while(p1!=NULL)/*頭節(jié)點如果不為空*/
{
temp=p1;/*記錄當(dāng)前節(jié)點*/
p1=p1->next;/*檢索的是下一個節(jié)點*/
if(p1==NULL){
return1;
}
if(p1==node){
temp->next=p1->next;/*刪除此節(jié)點*/
return0;
}
}
}
return0;
}


staticBOOLis_node_already_creat(SoftTimer*node)
{
structSoftTimer*p1;//p1保存當(dāng)前需要檢查的節(jié)點的地址
if(node==NULL)
returnFALSE;

p1=head_point;
while(p1!=NULL)
{
if(p1==node)
returnTRUE;
p1=p1->next;//后移一個節(jié)點
}
returnFALSE;
}


/**
*此函數(shù)為tick中斷服務(wù)函數(shù),需要掛載在外部硬件定時器上
*因此軟件定時器的定時精度由此函數(shù)掛載的硬件定時時間決定,
*比如此函數(shù)掛載在定時50ms的外部定時器上,那么定時dutation
*為20時定時時間就是20*50ms=1S
*/
voidsystem_tick_IrqHandler(void)
{
structSoftTimer*p1=head_point;
close_global_ir();//關(guān)閉中斷,根據(jù)硬件平臺修改
while(p1!=NULL)//下一個節(jié)點如果不為空
{
if(p1->start_flag!=FALSE)/*判斷當(dāng)前定時器是否被開啟*/
{
if(++p1->counter>=p1->duration)/*判斷當(dāng)前計時有沒有到達*/
{
switch(p1->timing_mode)
{
caseONCE_MODE:
p1->start_flag=FALSE;
break;
caseCONTINUE_MODE:
break;
caseDEFINE_NUM_MODE:
if(p1->run_num>0)
{
if(--p1->run_num==0)
{
p1->start_flag=FALSE;
}
}
default:
break;
}
if(p1->run_mode==RUN_IN_INTERRUPT_MODE)
{
p1->callback_function();/*中斷內(nèi)直接運行回調(diào)函數(shù),用于實時性比較高的程序*/
if(p1->start_flag!=TRUE)
delete_node(p1);
}
else
p1->loop_flag=TRUE;
p1->counter=0;
}
}
/*尋找下一個有意義的節(jié)點*/
p1=p1->next;
}
open_global_ir();//打開中斷,根據(jù)硬件平臺修改
}

結(jié)構(gòu)體實現(xiàn)方式

最后在附上用結(jié)構(gòu)體數(shù)組實現(xiàn)的軟件定時器以作參考。

H文件:

/**
*sfor_timer_array.h
*數(shù)組實現(xiàn)的軟件定時器庫
*一個軟件定時器解決整個項目中所有的定時需求,回調(diào)函數(shù)可根據(jù)應(yīng)用
*自動切換中斷實時操作或者不實時的輪詢操作,可以有效解決硬件資源
*不足或者軟件定時器定時不準的問題,定時誤差就幾個C語言語句,倘若
*配置最大10個軟件定時器,誤差就是最多10個for循環(huán)的時間
*/
#ifndef__SOFT_TIMER_ARRAY_H
#define__SOFT_TIMER_ARRAY_H


/**
*定義最大的可用的軟件定時器數(shù)量
*理論上可以無限大,但是數(shù)量越大定時誤差越大,所以用幾個開幾個
*誤差在于輪詢檢測所有定時器,定時器越多輪詢到自己的定時器就越慢,
*此外,數(shù)量增多亦會帶來空間增大
*/
#defineMAX_TIMER_NUM10


/**
*定時模式選擇
*/
typedefenum
{
ONCE_MODE,/*單次定時模式,即超時后自動關(guān)閉定時器*/
CONTINUE_MODE,/*持續(xù)定時模式,只要開啟除非手動關(guān)閉否則永不停歇*/
DEFINE_NUM_MODE,/*定義次數(shù)的模式,運行指定的次數(shù)后關(guān)閉定時器*/
}TimerTimingModeType;


/**
*定時超時后運行的回調(diào)函數(shù)可以選擇在中斷直接運行或者掛起任務(wù)輪詢執(zhí)行
*只要在定時需求準確的時候才建議選擇中斷模式執(zhí)行,類似無磁傳感器脈沖測量
*像一些超時判斷類的應(yīng)用以輪詢的方式進行執(zhí)行
*中斷執(zhí)行模式越多,其他定時器越不準,畢竟中斷允許占時間,查詢其他定時器時
*會有延時
*/
typedefenum
{
RUN_IN_LOOP_MODE,/*輪詢執(zhí)行模式*/
RUN_IN_INTERRUPT_MODE,/*中斷實時執(zhí)行模式*/
}TimerRunModeType;


/**
*軟件定時器基本類型
*/
typedefstruct
{
unsignedlongcounter;/*計數(shù)*/
unsignedlongduration;/*定時時長*/
unsignedlongrun_num;/*自定義的定時次數(shù)*/
unsignedcharstart_flag;/*啟動標志*/
unsignedcharloop_flag;/*輪詢標志*/
TimerRunModeTyperun_mode;
TimerTimingModeTypetiming_mode;
void(*callback_function)(void);/*回調(diào)函數(shù)*/
}SoftTimer;



/**
*刪除一個軟件定時器
*/
externvoidstop_timer(void(*callback_function)(void));



/*
*創(chuàng)建一個軟件定時器并立刻開始計時
* return:沒有空閑定時器時返回1,創(chuàng)建成功時返回0
*/
externcharsoft_timer_start(TimerTimingModeTypetiming_mode,
TimerRunModeTyperun_mode,
unsignedlongrun_num,
unsignedlongduration,
void(*callback_function)(void));



/**
*系統(tǒng)main循環(huán)進程,用于執(zhí)行輪詢模式的回調(diào)函數(shù)
*/
externvoidsoft_timer_main_loop(void);



/**
*此函數(shù)為tick中斷服務(wù)函數(shù),需要掛載在外部硬件定時器上
*因此軟件定時器的定時精度由此函數(shù)掛載的硬件定時時間決定,
*比如此函數(shù)掛載在定時50ms的外部定時器上,那么定時dutation
*為20時定時時間就是20*50ms=1S
*/
externvoidsystem_tick_IrqHandler(void);



#endif/*!1__SOFT_TIMER_LIB_H*/

C文件:

/**
*sfor_timer_array.c
*數(shù)組實現(xiàn)的軟件定時器庫
*一個軟件定時器解決整個項目中所有的定時需求,回調(diào)函數(shù)可根據(jù)應(yīng)用
*自動切換中斷實時操作或者不實時的輪詢操作,可以解決硬件資源
*不足或者軟件定時器定時不準的問題
*/
#include"soft_timer_array.h"


/**
*軟件定時器內(nèi)部變量
*/
staticSoftTimersoft_timer[MAX_TIMER_NUM];


/*
*創(chuàng)建一個軟件定時器并立刻開始計時
* return:沒有空閑定時器時返回1,創(chuàng)建成功時返回0
*/
charsoft_timer_start(TimerTimingModeTypetiming_mode,TimerRunModeTyperun_mode,unsignedlongrun_num,unsignedlongduration,
void(*callback_function)(void))
{
unsignedchari=0;

if(!callback_function)return1;
stop_timer(callback_function);/*先判斷有沒有一樣的定時器,有的話先刪除*/
for(i=0;i=soft_timer[i].duration)/*判斷當(dāng)前計時有沒有到達*/
{
switch(soft_timer[i].timing_mode)
{
caseONCE_MODE:
soft_timer[i].start_flag=0;
break;
caseCONTINUE_MODE:
break;
caseDEFINE_NUM_MODE:
if(soft_timer[i].run_num>0)
{
if(--soft_timer[i].run_num==0)
{
soft_timer[i].start_flag=0;
}
}
default:
break;
}
if(soft_timer[i].run_mode==RUN_IN_INTERRUPT_MODE)
soft_timer[i].callback_function();/*中斷內(nèi)直接運行回調(diào)函數(shù),用于實時性比較高的程序*/
else
soft_timer[i].loop_flag=1;
soft_timer[i].counter=0;
}
//else
//{
//soft_timer[i].counter++;
//}

}
}
}


審核編輯:湯梓紅
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 嵌入式
    +關(guān)注

    關(guān)注

    5083

    文章

    19131

    瀏覽量

    305544
  • 中斷
    +關(guān)注

    關(guān)注

    5

    文章

    898

    瀏覽量

    41516
  • 定時器
    +關(guān)注

    關(guān)注

    23

    文章

    3250

    瀏覽量

    114882
  • 數(shù)組
    +關(guān)注

    關(guān)注

    1

    文章

    417

    瀏覽量

    25960
  • 結(jié)構(gòu)體
    +關(guān)注

    關(guān)注

    1

    文章

    130

    瀏覽量

    10848

原文標題:嵌入式軟件實現(xiàn)定時器的方法分析

文章出處:【微信號:嵌入式開發(fā)愛好者,微信公眾號:嵌入式開發(fā)愛好者】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    #嵌入式軟件設(shè)計 定時器實例

    嵌入式定時器編程語言嵌入式軟件python
    電子技術(shù)那些事兒
    發(fā)布于 :2022年09月03日 14:28:49

    怎么實現(xiàn)嵌入式PPPoE軟件模塊的設(shè)計?

    本文在對PPPoE協(xié)議深入分析的基礎(chǔ)上,結(jié)合嵌入式系統(tǒng)的特點,提出了PPPoE在嵌入式系統(tǒng)上的具體實現(xiàn)方法,通過運用這些優(yōu)化
    發(fā)表于 05-28 06:09

    定時器的作用?

    文章目錄前言一、定時器的作用?二、定時器幾個概念1.硬件定時器2.軟件定時器3.系統(tǒng)定時器4.S
    發(fā)表于 12-14 07:52

    基于模塊化設(shè)計的嵌入式軟件測試方法

    分析嵌入式軟件的特點,綜述傳統(tǒng)的軟件測試方法;針對嵌入式軟件
    發(fā)表于 05-18 13:26 ?23次下載

    基于模塊化設(shè)計的嵌入式軟件測試方法

    摘要:分析嵌入式軟件的特點,綜述傳統(tǒng)的軟件測試方法;針對嵌入式
    發(fā)表于 04-07 00:32 ?2052次閱讀
    基于模塊化設(shè)計的<b class='flag-5'>嵌入式</b><b class='flag-5'>軟件</b>測試<b class='flag-5'>方法</b>

    基于C51單片機的星載嵌入式軟件定時器管理

    在航天嵌入式軟件領(lǐng)域,尤其是星載51系列單片機軟件中,采用C51語言進行開發(fā)的配置項一直占有較高的比例,其中對于定時器的使用極為常見,是完成某些功能的必要手段。
    發(fā)表于 11-28 16:57 ?0次下載
    基于C51單片機的星載<b class='flag-5'>嵌入式</b><b class='flag-5'>軟件</b><b class='flag-5'>定時器</b>管理

    嵌入式C實現(xiàn)延時程序的不同變量的區(qū)別 幾種Linux嵌入式開發(fā)環(huán)境的簡單介紹

    嵌入式C實現(xiàn)延時程序的不同變量的區(qū)別 幾種Linux嵌入式開發(fā)環(huán)境的簡單介紹 ARM嵌入式開發(fā)基礎(chǔ) 對話微軟MVP:走進嵌入式
    發(fā)表于 04-14 07:24 ?1650次閱讀
    <b class='flag-5'>嵌入式</b>C<b class='flag-5'>實現(xiàn)</b>延時程序的不同變量的區(qū)別 幾種Linux<b class='flag-5'>嵌入式</b>開發(fā)環(huán)境的簡單介紹

    基于VxWorks嵌入式實時操作系統(tǒng)和UDP網(wǎng)絡(luò)系統(tǒng)實現(xiàn)多重定時器的設(shè)計

    VxWorks是一種嵌入式實時操作系統(tǒng)(RTOS),具有內(nèi)核小、可裁剪、實時性強等特點。VxWorks內(nèi)核(Wind)提供了共享內(nèi)存、信號量、消息隊列、套接字通信和定時器等多種機制。為了實現(xiàn)
    的頭像 發(fā)表于 10-04 12:36 ?3461次閱讀
    基于VxWorks<b class='flag-5'>嵌入式</b>實時操作系統(tǒng)和UDP網(wǎng)絡(luò)系統(tǒng)<b class='flag-5'>實現(xiàn)</b>多重<b class='flag-5'>定時器</b>的設(shè)計

    SAM器件上的各種定時器

    定時器是基于單片機的嵌入式應(yīng)用中的基本模塊。很難想象不使用定時器如何設(shè)計嵌入式應(yīng)用。定時器作為外設(shè),可生成周期性事件,用于測量時間間隔、生成
    發(fā)表于 03-30 15:55 ?6次下載
    SAM器件上的各種<b class='flag-5'>定時器</b>

    嵌入式軟件開發(fā)技術(shù)實驗報告-定時器

    實驗?zāi)康模?)掌握嵌入式系統(tǒng)軟件設(shè)計方法,培養(yǎng)分析問題、解決問題、應(yīng)用知識的能力和創(chuàng)新精神,全面提高綜合素質(zhì)。(2)熟悉嵌入式Linux開發(fā)
    發(fā)表于 11-03 19:51 ?12次下載
    <b class='flag-5'>嵌入式</b><b class='flag-5'>軟件</b>開發(fā)技術(shù)實驗報告-<b class='flag-5'>定時器</b>

    設(shè)計軟件定時器

    在MCU芯片內(nèi)部,往往硬件定時器的數(shù)量是非常有限的,而實際工程中卻需要大量的定時器來輔助完成具體的功能,如果一個函數(shù)占用一個定時器,那么顯然不夠用,怎么辦?思路有2種:1、直接將開源嵌入式
    發(fā)表于 11-05 18:35 ?2次下載
    設(shè)計<b class='flag-5'>軟件</b><b class='flag-5'>定時器</b>

    MCU中定時器的可能應(yīng)用場景

    還可用于其他應(yīng)用場景,如生成 PWM 輸出和捕捉輸入等。? 在任何嵌入式應(yīng)用中,CPU 和資源利用對實現(xiàn)應(yīng)用功能具有至關(guān)重要的作用。例如,如果沒有定時器,要使 LED 每 2秒閃爍一次,則應(yīng)用需要連續(xù)檢查經(jīng)過的時間。當(dāng)應(yīng)用定期檢
    的頭像 發(fā)表于 11-17 10:46 ?3379次閱讀

    AN5324_基于STM32F334單片機嵌入式高分辨率定時器實現(xiàn)太陽能轉(zhuǎn)換

    AN5324_基于STM32F334單片機嵌入式高分辨率定時器實現(xiàn)太陽能轉(zhuǎn)換
    發(fā)表于 11-21 08:11 ?13次下載
    AN5324_基于STM32F334單片機<b class='flag-5'>嵌入式</b>高分辨率<b class='flag-5'>定時器</b><b class='flag-5'>實現(xiàn)</b>太陽能轉(zhuǎn)換<b class='flag-5'>器</b>

    什么是軟件定時器軟件定時器實現(xiàn)原理

    軟件定時器是用程序模擬出來的定時器,可以由一個硬件定時器模擬出成千上萬個軟件定時器,這樣程序在需
    的頭像 發(fā)表于 05-23 17:05 ?2815次閱讀

    如何實現(xiàn)一個軟件定時器?

    在Linux,uC/OS,F(xiàn)reeRTOS等操作系統(tǒng)中,都帶有軟件定時器,原理大同小異。典型的實現(xiàn)方法是:通過一個硬件定時器產(chǎn)生固定的時鐘節(jié)
    的頭像 發(fā)表于 04-29 11:00 ?671次閱讀