一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

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

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

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

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

冬至子 ? 來源:嵌入式大雜燴 ? 作者:嵌入式大雜燴 ? 2023-05-23 17:05 ? 次閱讀

1.什么是軟件定時(shí)器

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

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

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

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

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

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

3.基于STM32的軟件定時(shí)器

3.1 時(shí)鐘節(jié)拍

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

static volatile uint32_t tickCnt = 0;    //軟件定時(shí)器時(shí)鐘節(jié)拍

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

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

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

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

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

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

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

static softTimer timer[TIMER_NUM];        //軟件定時(shí)器數(shù)組

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

typedef struct softTimer {    uint8_t state;           //狀態(tài)    uint8_t mode;            //模式    uint32_t match;          //到期時(shí)間    uint32_t period;         //定時(shí)周期    callback *cb;            //回調(diào)函數(shù)指針    void *argv;              //參數(shù)指針    uint16_t argc;           //參數(shù)個(gè)數(shù)}softTimer;

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

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

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

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

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

typedef void callback(void *argv, uint16_t argc);

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

3.3 定時(shí)器操作

3.3.1 初始化

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

void softTimer_Init(void)
{
    uint16_t i;
    for(i=0; i

3.3.2 啟動(dòng)

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

void softTimer_Start(uint16_t id, tmrMode mode, uint32_t delay, callback *cb, void *argv, uint16_t argc)
{
    assert_param(id < TIMER_NUM);
    assert_param(mode == MODE_ONE_SHOT || mode == MODE_PERIODIC);
    
    timer[id].match = tickCnt_Get() + delay;
    timer[id].period = delay;
    timer[id].state = SOFT_TIMER_RUNNING;
    timer[id].mode = mode;
    timer[id].cb = cb;
    timer[id].argv = argv;
    timer[id].argc = argc;
}

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

3.3.3 更新

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

void softTimer_Update(void)
{
    uint16_t i;
    
    for(i=0; i

3.3.4 停止

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

void softTimer_Stop(uint16_t id)
{
    assert_param(id < TIMER_NUM);
    timer[id].state = SOFT_TIMER_STOPPED;
}

3.3.5 讀狀態(tài)

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

uint8_t softTimer_GetState(uint16_t id)
{
    return timer[id].state;
}

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

3.4 測(cè)試

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

定義三個(gè)定時(shí)器:

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

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

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

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

int main(void)
{
    USART1_Init(115200);
    TIM4_Init(TIME_BASE_MS);
    TIM4_NVIC_Config();
    LED_Init();
    
    printf("I just grabbed a spoon.\\r\\n");
    
    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)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • led燈
    +關(guān)注

    關(guān)注

    22

    文章

    1593

    瀏覽量

    109191
  • 嵌入式系統(tǒng)
    +關(guān)注

    關(guān)注

    41

    文章

    3662

    瀏覽量

    130635
  • 軟件定時(shí)器
    +關(guān)注

    關(guān)注

    0

    文章

    18

    瀏覽量

    6886
  • FreeRTOS
    +關(guān)注

    關(guān)注

    12

    文章

    485

    瀏覽量

    63518
收藏 人收藏

    評(píng)論

    相關(guān)推薦

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

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

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

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

    定時(shí)器初值計(jì)算軟件工具

    定時(shí)器初值計(jì)算軟件工具
    發(fā)表于 03-20 10:23 ?239次下載

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

    555定時(shí)器電路設(shè)計(jì)軟件
    發(fā)表于 03-02 11:29 ?288次下載

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

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

    ESP8266的管腳的控制和軟件定時(shí)器的使用

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

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

    軟件定時(shí)器搬來使用2、自己設(shè)計(jì)軟件定時(shí)器這里我只介紹第二種方法,我們知道,硬件定時(shí)器是通過對(duì)系統(tǒng)時(shí)鐘周期進(jìn)行計(jì)數(shù)
    發(fā)表于 11-05 18:35 ?2次下載
    設(shè)計(jì)<b class='flag-5'>軟件</b><b class='flag-5'>定時(shí)器</b>

    基于硬件定時(shí)器軟件定時(shí)器

    概括硬件定時(shí)器很精確,軟件定時(shí)器無論如何都有延遲,主要用在不需要精確定時(shí)的地方,而且軟件定時(shí)比較
    發(fā)表于 11-25 09:51 ?8次下載
    基于硬件<b class='flag-5'>定時(shí)器</b>的<b class='flag-5'>軟件</b><b class='flag-5'>定時(shí)器</b>

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

    目錄背景軟件定時(shí)器庫特性源碼介紹softwaretimer.csoftwaretimer.h使用指南背景在不運(yùn)行實(shí)時(shí)操作系統(tǒng)的單片機(jī)中,面對(duì)一些復(fù)雜的項(xiàng)目需求時(shí),僅有的幾個(gè)硬件定時(shí)器顯得有些捉襟見肘
    發(fā)表于 12-24 19:15 ?1次下載
    STM32開發(fā)項(xiàng)目:<b class='flag-5'>軟件</b>虛擬<b class='flag-5'>定時(shí)器</b>的<b class='flag-5'>實(shí)現(xiàn)</b>

    軟件定時(shí)器簡(jiǎn)介及程序配置

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

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

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

    freeRTOS軟件定時(shí)器的使用

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

    Free RTOS的軟件定時(shí)器

    軟件定時(shí)器是FreeRTOS中的一個(gè)重要模塊,使用軟件定時(shí)器可以方便的實(shí)現(xiàn)一些與超時(shí)或周期性相關(guān)的功能。
    的頭像 發(fā)表于 02-10 15:53 ?2700次閱讀
    Free RTOS的<b class='flag-5'>軟件</b><b class='flag-5'>定時(shí)器</b>

    關(guān)于軟件定時(shí)器的一些討論

    這就是簡(jiǎn)單的軟件定時(shí)器,是的,這就是特別簡(jiǎn)潔版本的軟件定時(shí)器。當(dāng)然它是有缺點(diǎn)的,比如systick_ms每1ms加1,所以軟件
    的頭像 發(fā)表于 10-13 16:14 ?725次閱讀
    關(guān)于<b class='flag-5'>軟件</b><b class='flag-5'>定時(shí)器</b>的一些討論

    如何實(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 ?971次閱讀