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

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

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

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

工程師進(jìn)階筆記 ? 來源:csdn ? 2024-04-29 11:00 ? 次閱讀

有時候,我們在進(jìn)行產(chǎn)品開發(fā)的時候,由于選用的處理器芯片資源有限的原因,沒有更多的硬件定時器外設(shè)提供給我們使用,但我們的程序設(shè)計又需要定時器進(jìn)行各種延時或者定時任務(wù)處理,這個時候,軟件定時器就應(yīng)運(yùn)而生。

1.什么是軟件定時器

軟件定時器是用程序模擬出來的定時器,可以由一個硬件定時器模擬出成千上萬個軟件定時器,這樣程序在需要使用較多定時器的時候就不會受限于硬件資源的不足,這是軟件定時器的一個優(yōu)點,即數(shù)量不受限制。

但由于軟件定時器是通過程序?qū)崿F(xiàn)的,其運(yùn)行和維護(hù)都需要耗費一定的CPU資源,同時精度也相對硬件定時器要差一些。

2.軟件定時器的實現(xiàn)原理

Linux,uC/OS,FreeRTOS操作系統(tǒng)中,都帶有軟件定時器,原理大同小異。典型的實現(xiàn)方法是:通過一個硬件定時器產(chǎn)生固定的時鐘節(jié)拍,每次硬件定時器中斷到,就對一個全局的時間標(biāo)記加一,每個軟件定時器都保存著到期時間。

程序需要定期掃描所有運(yùn)行中的軟件定時器,將各個到期時間與全局時鐘標(biāo)記做比較,以判斷對應(yīng)軟件定時器是否到期,到期則執(zhí)行相應(yīng)的回調(diào)函數(shù),并關(guān)閉該定時器。

以上是單次定時器的實現(xiàn),若要實現(xiàn)周期定時器,即到期后接著重新定時,只需要在執(zhí)行完回調(diào)函數(shù)后,獲取當(dāng)前時間標(biāo)記的值,加上延時時間作為下一次到期時間,繼續(xù)運(yùn)行軟件定時器即可。

3.基于STM32的軟件定時器

3.1 時鐘節(jié)拍

軟件定時器需要一個硬件時鐘源作為基準(zhǔn),這個時鐘源有一個固定的節(jié)拍(可以理解為秒針的每次滴答),用一個32位的全局變量tickCnt來記錄這個節(jié)拍的變化:

staticvolatileuint32_ttickCnt=0;//軟件定時器時鐘節(jié)拍

每來一個節(jié)拍就對tickCnt加一(記錄滴答了多少下):

/*需在定時器中斷內(nèi)執(zhí)行*/
voidtickCnt_Update(void)
{
tickCnt++;
}

一旦開始運(yùn)行,tickCnt將不停地加一,而每個軟件定時器都記錄著一個到期時間,只要tickCnt大于該到期時間,就代表定時器到期了。

3.2 數(shù)據(jù)結(jié)構(gòu)

軟件定時器的數(shù)據(jù)結(jié)構(gòu)決定了其執(zhí)行的性能和功能,一般可分為兩種:數(shù)組結(jié)構(gòu)和鏈表結(jié)構(gòu)。什么意思呢?這是(多個)軟件定時器在內(nèi)存中的存儲方式,可以用數(shù)組來存,也可以用鏈表來存。

兩者的優(yōu)劣之分就是兩種數(shù)據(jù)結(jié)構(gòu)的特性之分:數(shù)組方式的定時器查找較快,但數(shù)量固定,無法動態(tài)變化,數(shù)組大了容易浪費內(nèi)存,數(shù)組小了又可能不夠用,適用于定時事件明確且固定的系統(tǒng);鏈表方式的定時器數(shù)量可動態(tài)增減,易造成內(nèi)存碎片(如果沒有內(nèi)存管理),查找的時間開銷相對數(shù)組大,適用于通用性強(qiáng)的系統(tǒng),Linux,uC/OS,F(xiàn)reeRTOS等操作系統(tǒng)用的都是鏈表式的軟件定時器。

本文使用數(shù)組結(jié)構(gòu):

staticsoftTimertimer[TIMER_NUM];//軟件定時器數(shù)組

數(shù)組和鏈表是軟件定時器整體的數(shù)據(jù)結(jié)構(gòu),當(dāng)具體到單個定時器時,就涉及軟件定時器結(jié)構(gòu)體的定義,軟件定時器所具有的功能與其結(jié)構(gòu)體定義密切相關(guān),以下是本文中軟件定時器的結(jié)構(gòu)體定義

typedefstructsoftTimer{
uint8_tstate;//狀態(tài)
uint8_tmode;//模式
uint32_tmatch;//到期時間
uint32_tperiod;//定時周期
callback*cb;//回調(diào)函數(shù)指針
void*argv;//參數(shù)指針
uint16_targc;//參數(shù)個數(shù)
}softTimer;

定時器的狀態(tài)共有三種,默認(rèn)是停止,啟動后為運(yùn)行,到期后為超時。

typedefenumtmrState{
SOFT_TIMER_STOPPED=0,//停止
SOFT_TIMER_RUNNING,//運(yùn)行
SOFT_TIMER_TIMEOUT//超時
}tmrState;

模式有兩種:到期后就停止的是單次模式,到期后重新定時的是周期模式。

typedefenumtmrMode{
MODE_ONE_SHOT=0,//單次模式
MODE_PERIODIC,//周期模式
}tmrMode;

不管哪種模式,定時器到期后,都將執(zhí)行回調(diào)函數(shù),以下是該函數(shù)的定義,參數(shù)指針argv為void指針類型,便于傳入不同類型的參數(shù)。

typedefvoidcallback(void*argv,uint16_targc);

上述結(jié)構(gòu)體中的模式state和回調(diào)函數(shù)指針cb是可選的功能,如果系統(tǒng)不需要周期執(zhí)行的定時器,或者不需要到期后自動執(zhí)行某個函數(shù),可刪除此二者定義。

3.3 定時器操作

3.3.1 初始化

首先是軟件定時器的初始化,對每個定時器結(jié)構(gòu)體的成員賦初值,雖說static變量的初值為0,但個人覺得還是有必要保持初始化變量的習(xí)慣,避免出現(xiàn)一些奇奇怪怪的BUG。

voidsoftTimer_Init(void)
{
uint16_ti;
for(i=0;i

3.3.2 啟動

啟動一個軟件定時器不僅要改變其狀態(tài)為運(yùn)行狀態(tài),同時還要告訴定時器什么時候到期(當(dāng)前tickCnt值加上延時時間即為到期時間),單次定時還是周期定時,到期后執(zhí)行哪個函數(shù),函數(shù)的參數(shù)是什么,交代好這些就可以開跑了。

voidsoftTimer_Start(uint16_tid,tmrModemode,uint32_tdelay,callback*cb,void*argv,uint16_targc)
{
assert_param(id

上面函數(shù)中的assert_param()用于參數(shù)檢查,類似于庫函數(shù)assert()。

3.3.3 更新

本文中軟件定時器有三種狀態(tài):停止,運(yùn)行和超時,不同的狀態(tài)做不同的事情。停止?fàn)顟B(tài)最簡單,啥事都不做;運(yùn)行狀態(tài)需要不停地檢查有沒有到期,到期就執(zhí)行回調(diào)函數(shù)并進(jìn)入超時狀態(tài);超時狀態(tài)判斷定時器的模式,如果是周期模式就更新到期時間,繼續(xù)運(yùn)行,如果是單次模式就停止定時器。

這些操作都由一個更新函數(shù)來實現(xiàn):

voidsoftTimer_Update(void)
{
uint16_ti;

for(i=0;i

3.3.4 停止

如果定時器跑到一半,想把它停掉,就需要一個停止函數(shù),操作很簡單,改變目標(biāo)定時器的狀態(tài)為停止即可:

voidsoftTimer_Stop(uint16_tid)
{
assert_param(id

3.3.5 讀狀態(tài)

又如果想知道一個定時器是在跑著呢還是已經(jīng)停下來?也很簡單,返回它的狀態(tài):

uint8_tsoftTimer_GetState(uint16_tid)
{
returntimer[id].state;
}

或許這看起來很怪,為什么要返回,而不是直接讀?別忘了在前面3.2節(jié)中定義的定時器數(shù)組是個靜態(tài)全局變量,該變量只能被當(dāng)前源文件訪問,當(dāng)外部文件需要訪問它的時候只能通過函數(shù)返回,這是一種簡單的封裝,保持程序的模塊化。

3.4 測試

最后,當(dāng)然是來驗證一下我們的軟件定時器有沒達(dá)到預(yù)想的功能。

定義三個定時器:

定時器TMR_STRING_PRINT只執(zhí)行一次,1s后在串口1打印一串字符;

定時器TMR_TWINKLING為周期定時器,周期為0.5s,每次到期都將取反LED0的狀態(tài),實現(xiàn)LED0的閃爍;

定時器TMR_DELAY_ON執(zhí)行一次,3s后點亮LED1,跟第一個定時器不同的是,此定時器的回調(diào)函數(shù)是個空函數(shù)nop(),點亮LED1的操作通過主循環(huán)中判斷定時器的狀態(tài)來實現(xiàn),這種方式在某些場合可能會用到。

staticuint8_tdata[]={1,2,3,4,5,6,7,8,9,0};

intmain(void)
{
USART1_Init(115200);
TIM4_Init(TIME_BASE_MS);
TIM4_NVIC_Config();
LED_Init();

printf("Ijustgrabbedaspoon.
");

softTimer_Start(TMR_STRING_PRINT,MODE_ONE_SHOT,1000,stringPrint,data,5);
softTimer_Start(TMR_TWINKLING,MODE_PERIODIC,500,LED0_Twinkling,NULL,0);
softTimer_Start(TMR_DELAY_ON,MODE_ONE_SHOT,3000,nop,NULL,0);

while(1){
softTimer_Update();
if(softTimer_GetState(TMR_DELAY_ON)==SOFT_TIMER_TIMEOUT){
LED1_On();
}
}
}
審核編輯:黃飛

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

    關(guān)注

    68

    文章

    10696

    瀏覽量

    209321
  • 操作系統(tǒng)
    +關(guān)注

    關(guān)注

    37

    文章

    6544

    瀏覽量

    122727
  • 軟件定時器
    +關(guān)注

    關(guān)注

    0

    文章

    18

    瀏覽量

    6719

原文標(biāo)題:硬件定時器不夠用,如何實現(xiàn)一個軟件定時器?

文章出處:【微信號:工程師進(jìn)階筆記,微信公眾號:工程師進(jìn)階筆記】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    基于STM32的軟件定時器設(shè)計

    軟件定時器是用程序模擬出來的定時器,可以由硬件定時器模擬出成千上萬
    發(fā)表于 07-03 17:06 ?878次閱讀
    基于STM32的<b class='flag-5'>軟件</b><b class='flag-5'>定時器</b>設(shè)計

    請問怎么用硬件定時器實現(xiàn)多個不同的軟件定時器

    怎樣用硬件定時器,來實現(xiàn)多個軟件定時器的功能?每個定時器
    發(fā)表于 03-13 04:35

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

    什么是軟件定時器?軟件定時器實現(xiàn)原理是什么?
    發(fā)表于 11-24 06:43

    什么是軟件定時器?基于STM32的軟件定時器該怎樣去實現(xiàn)

    3.3.5 讀狀態(tài)3.4 測試4.參考鏈接1.什么是軟件定時器軟件定時器是用程序模擬出來的定時器,可以由
    發(fā)表于 12-22 07:47

    555定時器應(yīng)用設(shè)計軟件免費下載

    本文檔的主要內(nèi)容詳細(xì)介紹的是555定時器應(yīng)用設(shè)計軟件免費下載,本軟件款555定時器設(shè)計軟件
    發(fā)表于 12-17 08:00 ?51次下載
    555<b class='flag-5'>定時器</b>應(yīng)用設(shè)計<b class='flag-5'>軟件</b>免費下載

    ESP8266的管腳的控制和軟件定時器的使用

    先說定時器,ESP8266內(nèi)部的定時器分為軟件定時器和硬件定時器。手冊中指出硬件定時器其實就跟單
    的頭像 發(fā)表于 07-29 14:57 ?9328次閱讀
    ESP8266的管腳的控制和<b class='flag-5'>軟件</b><b class='flag-5'>定時器</b>的使用

    設(shè)計軟件定時器

    在MCU芯片內(nèi)部,往往硬件定時器的數(shù)量是非常有限的,而實際工程中卻需要大量的定時器來輔助完成具體的功能,如果函數(shù)占用
    發(fā)表于 11-05 18:35 ?2次下載
    設(shè)計<b class='flag-5'>軟件</b><b class='flag-5'>定時器</b>

    基于硬件定時器軟件定時器

    出現(xiàn)使用軟件定時器的情況,但是講定時器需要從硬件定時器開始講,軟件定時器是在其基礎(chǔ)之上延伸出來的
    發(fā)表于 11-25 09:51 ?8次下載
    基于硬件<b class='flag-5'>定時器</b>的<b class='flag-5'>軟件</b><b class='flag-5'>定時器</b>

    STM32開發(fā)項目:軟件虛擬定時器實現(xiàn)

    ,這主要體現(xiàn)在兩方面:其是硬件定時器數(shù)量十分有限(般4~8);其二是硬件定時器難以直接產(chǎn)
    發(fā)表于 12-24 19:15 ?1次下載
    STM32開發(fā)項目:<b class='flag-5'>軟件</b>虛擬<b class='flag-5'>定時器</b>的<b class='flag-5'>實現(xiàn)</b>

    軟件定時器簡介及程序配置

      軟件定時器就是允許函數(shù)設(shè)置定的等待時間,然后執(zhí)行。定時器執(zhí)行的函數(shù)被稱為定時器的回調(diào)函數(shù)。定時器
    的頭像 發(fā)表于 12-06 16:10 ?3671次閱讀
    <b class='flag-5'>軟件</b><b class='flag-5'>定時器</b>簡介及程序配置

    單片機(jī)軟件定時器實現(xiàn)方法

    定時器個數(shù)般都比較少,在些有多個周期性操作的應(yīng)用場合就無法滿足要求。這時,就可以基于硬件定時器派生出軟件
    的頭像 發(fā)表于 01-17 15:14 ?4399次閱讀
    單片機(jī)<b class='flag-5'>軟件</b><b class='flag-5'>定時器</b>的<b class='flag-5'>實現(xiàn)</b>方法

    freeRTOS軟件定時器的使用

    freeRTOS中加入了軟件定時器這個功能組件,是可選的、不屬于freeRTOS內(nèi)核的功能,由定時器服務(wù)(其實就是
    的頭像 發(fā)表于 02-10 13:55 ?1866次閱讀

    Free RTOS的軟件定時器

    軟件定時器是FreeRTOS中的重要模塊,使用軟件定時器可以方便的
    的頭像 發(fā)表于 02-10 15:53 ?2123次閱讀
    Free RTOS的<b class='flag-5'>軟件</b><b class='flag-5'>定時器</b>

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

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

    定時器設(shè)計實現(xiàn)

    返回ITimer類型的共享指針。其中ITimer類中定義了start和stop方法,用于啟動或停止當(dāng)前定時器。 TimerManager還有內(nèi)部類TimerMessageQueue用于實現(xiàn)
    的頭像 發(fā)表于 11-08 16:50 ?501次閱讀