在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

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

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

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

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

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

簡介

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

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

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

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

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

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

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

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

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

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

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

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

鏈表實(shí)現(xiàn)方式

H文件:

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

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


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

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

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

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

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

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

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


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

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


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


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

#endif/*!1__SOFT_TIMER_LIST_H*/

C文件:

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

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

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

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


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

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

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

/*
*創(chuàng)建一個(gè)只運(yùn)行一次的軟件定時(shí)器并立刻開始計(jì)時(shí)
*參數(shù)表:p:定時(shí)器結(jié)構(gòu)體指針,由用戶創(chuàng)建
*mode:選擇運(yùn)行模式,可選定時(shí)器到了之后是直接在tick中斷內(nèi)執(zhí)行還是置起標(biāo)志在while循環(huán)內(nèi)輪詢執(zhí)行
*duration:要計(jì)時(shí)的時(shí)長,單位為硬件中斷的tick
*timeout_handler:定時(shí)到了之后要執(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;/*只有在自定義運(yùn)行次數(shù)的情況下此值才有效*/
head_point=creat_node(p);
}

/*
*創(chuàng)建永遠(yuǎn)運(yùn)行的軟件定時(shí)器并立刻開始計(jì)時(shí)
*參數(shù)表:p:定時(shí)器結(jié)構(gòu)體指針,由用戶創(chuàng)建
*mode:選擇運(yùn)行模式,可選定時(shí)器到了之后是直接在tick中斷內(nèi)執(zhí)行(除非實(shí)在必要)還是置起標(biāo)志在while循環(huán)內(nèi)輪詢執(zhí)行
*duration:要計(jì)時(shí)的時(shí)長,單位為硬件中斷的tick
*timeout_handler:定時(shí)到了之后要執(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;/*只有在自定義運(yùn)行次數(shù)的情況下此值才有效*/
head_point=creat_node(p);
}



/*
*創(chuàng)建指定次數(shù)運(yùn)行的軟件定時(shí)器并立刻開始計(jì)時(shí)
*參數(shù)表:p:定時(shí)器結(jié)構(gòu)體指針,由用戶創(chuàng)建
*mode:選擇運(yùn)行模式,可選定時(shí)器到了之后是直接在tick中斷內(nèi)執(zhí)行還是置起標(biāo)志在while循環(huán)內(nèi)輪詢執(zhí)行
* run_num:要定時(shí)的次數(shù),比如1就是定時(shí)1次,5就是定時(shí)5次以后自動(dòng)關(guān)閉定時(shí)器
*duration:要計(jì)時(shí)的時(shí)長,單位為硬件中斷的tick
*timeout_handler:定時(shí)到了之后要執(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;/*只有在自定義運(yùn)行次數(shù)的情況下此值才有效*/
head_point=creat_node(p);
}


/*
*重啟指定的單次軟件定時(shí)器
*參數(shù)表:p:定時(shí)器結(jié)構(gòu)體指針,由用戶創(chuàng)建
*mode:選擇運(yùn)行模式,可選定時(shí)器到了之后是直接在tick中斷內(nèi)執(zhí)行還是置起標(biāo)志在while循環(huán)內(nèi)輪詢執(zhí)行
*duration:要計(jì)時(shí)的時(shí)長,單位為硬件中斷的tick
*timeout_handler:定時(shí)到了之后要執(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;/*只有在自定義運(yùn)行次數(shù)的情況下此值才有效*/
if(is_node_already_creat(p)!=TRUE)/*若之前的節(jié)點(diǎn)已被刪除就重新創(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é)點(diǎn)的地址
if(node==NULL)
returnhead_point;

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

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

}
returnhead_point;
}


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

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


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

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


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

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

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

H文件:

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


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


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


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


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



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



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



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



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



#endif/*!1__SOFT_TIMER_LIB_H*/

C文件:

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


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


/*
*創(chuàng)建一個(gè)軟件定時(shí)器并立刻開始計(jì)時(shí)
* return:沒有空閑定時(shí)器時(shí)返回1,創(chuàng)建成功時(shí)返回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);/*先判斷有沒有一樣的定時(shí)器,有的話先刪除*/
for(i=0;i=soft_timer[i].duration)/*判斷當(dāng)前計(jì)時(shí)有沒有到達(dá)*/
{
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)直接運(yùn)行回調(diào)函數(shù),用于實(shí)時(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)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • 嵌入式
    +關(guān)注

    關(guān)注

    5087

    文章

    19153

    瀏覽量

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

    關(guān)注

    5

    文章

    900

    瀏覽量

    41590
  • 定時(shí)器
    +關(guān)注

    關(guān)注

    23

    文章

    3254

    瀏覽量

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

    關(guān)注

    1

    文章

    417

    瀏覽量

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

    關(guān)注

    1

    文章

    130

    瀏覽量

    10860

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

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

收藏 人收藏

    評(píng)論

    相關(guān)推薦

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

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

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

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

    定時(shí)器的作用?

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

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

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

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

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

    基于C51單片機(jī)的星載嵌入式軟件定時(shí)器管理

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

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

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

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

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

    SAM器件上的各種定時(shí)器

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

    嵌入式軟件開發(fā)技術(shù)實(shí)驗(yàn)報(bào)告-定時(shí)器

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

    設(shè)計(jì)軟件定時(shí)器

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

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

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

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

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

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

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

    如何實(shí)現(xiàn)一個(gè)軟件定時(shí)器

    在Linux,uC/OS,F(xiàn)reeRTOS等操作系統(tǒng)中,都帶有軟件定時(shí)器,原理大同小異。典型的實(shí)現(xiàn)方法是:通過一個(gè)硬件定時(shí)器產(chǎn)生固定的時(shí)鐘節(jié)
    的頭像 發(fā)表于 04-29 11:00 ?707次閱讀
    主站蜘蛛池模板: 午夜在线观看免费高清在线播放| 欧美一区二区不卡视频| 久久精品高清视频| 免费看真人a一级毛片| 色版视频| 日本网络视频www色高清免费| 亚洲人成电影| 天堂资源吧| 高清不卡免费一区二区三区| 成人三级网址| 亚洲xxx视频| 日本骚视频| 国产婷婷色一区二区三区 | 手机看片1024在线| 夜夜爽爽| 去毛片| 午夜色大片在线观看| 7777奇米影视| 操一操日一日| 亚洲天堂视频在线播放| 伊人久久天堂| 亚洲www| 青草99| 美女18毛片| 久久女人网| 久久国产乱子伦精品免费强| 成人sese| 久久v| 女生扒开尿口让男生舔| 午夜综合| 日韩一级片免费看| 欧美性天天影院| 牛牛精品| 久青草免费视频| 国产主播在线一区| 丁香四月婷婷| 新午夜影院| 奇米影视99| 亚洲欧洲一区二区三区在线观看| 亚洲一区二区三区免费视频 | 国产视频久|