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

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

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

3天內不再提示

基于單片機的非阻塞式延時設計

我快閉嘴 ? 來源:玩轉單片機與嵌入式 ? 作者:玩轉單片機與嵌入 ? 2022-09-02 09:15 ? 次閱讀

對于每個單片機愛好者及工程開發設計人員,在剛接觸單片機的那最初的青蔥歲月里,都有過點亮跑馬燈的經歷。從看到那一排排小燈按著我們的想法在跳動時激動心情。到隨著經驗越多,越來又會感覺到這個小燈是個好東西,尤其是在調試資源有限的環境中,有時會幫上大忙。

一:阻塞式延時

但對于絕大多數人,我們在最最初讓燈閃爍起來時大約都會用到阻塞延時實現,會像如下代碼的樣子:
    while(1){LED=OFF;Delay_ms(500);LED=ON;Delay_ms(500);}
這時我們就會慢慢意識到,第一種(阻塞延時)方法效率很低,讓芯片在那兒空運行幾百毫米,什么也不做,真是莫大的浪費,尤其在芯片頻率較高,任務又很多時,這樣做就像在平坦寬闊的高速公路上挖了一大坑,出現事故可想而知。

二:定時器延時

然后,在我們接觸到定時器,我們會發現,原來用定時中斷來處理會更好。比如我們可以500ms中斷一次,讓燈亮或滅,其余的時間系統還可以做非常之多的事情,效率一下提升了很多。
但一個單片機中的定時器畢竟有限,如果我需要幾十個或者更多不同時間的定時中斷,每一個時間到都完成不同的處理動作,如何去做呢。一般我們會想到在一個定時中斷函數中再定義static 變量繼續定時,到了所需時間,做不同的動作。而這樣又會導致在一個中斷里做了很多不同的事情,會搶占主輪詢更多時間,有時甚至喧賓奪主,并也不是很如的思維邏輯。

那么有沒有更好的方法來實現呢,答案是肯定的。下面介紹我在一個項目中偶遇,一個精妙設計的非阻塞定時延時軟件的設計(此設計主要針對于無操作系統的裸機程序)。

三:非阻塞式延時設計

在之前的文章中有對systick的介紹,比如我要設置其10ms中斷一次,如何實現呢?

也很簡單,只需調用core_cm3.h文件中 SysTick_Config函數 ,當系統時鐘為72MHZ,則設置成如下即可SysTick_Config(720000); (遞減計數720000次后中斷一次) 。此時SysTick_Handler中斷函數就會10ms進入一次;
任務定時用軟件是如何設計的呢 ?
且先看其數據結構,這也是精妙所在之處,在此作自頂向下的介紹:

其定義結構體類型如:

typedef struct{        uint8_t Tick10Msec;    Char_Field Status;} Timer_Struct;

其中Char_Field 為一聯合體,設計如下:

typedefunion{    unsigned char byte;    Timer_Bit field;} Char_Field{

?而它內部的Timer_Bit是一個可按位訪問的結構體:

typedef struct{    unsigned char bit0: 1;    unsigned char bit1: 1;    unsigned char bit2: 1;    unsigned char bit3: 1;    unsigned char bit4: 1;    unsigned char bit5: 1;    unsigned char bit6: 1;    unsigned char bit7: 1;} Timer_Bit

此聯合體的這樣設計的目的將在后面的代碼中體現出來。

如此結構體的設計就完成了。

然后我們定義的一全局變量,Timer_Struct gTimer;

并在頭文件中宏定義如下:

#define bSystem10Msec        gTimer.Status.field.bit0#define bSystem50Msec        gTimer.Status.field.bit1#define bSystem100Msec       gTimer.Status.field.bit2#define bSystem1Sec          gTimer.Status.field.bit3#define bTemp10Msec          gTimer.Status.field.bit4#define bTemp50Msec          gTimer.Status.field.bit5#define bTemp100Msec         gTimer.Status.field.bit6#define bTemp1Sec            gTimer.Status.field.bit7

另外為了后面程序清晰,再定義一狀態指示:

typedef enum{    TIMER_RESET = 0,    TIMER_SET = 1,} TimerStatus;

至此,準備工作就完成了。下面我們就開始大顯神通了!

首先,10ms定時中斷處理函數如,可以看出,每到達10ms 將把bTemp10Msec置1,每50ms 將把bTemp50Msec置1,每100ms 將把bTemp100Msec置1,每1s 將把bTemp1Sec置1。

void SysTick_Handler(void){        bTemp10Msec = TIMER_SET;                ++gTimer.Tick10Msec;        if (0 == (gTimer.Tick10Msec % 5))        {            bTemp50Msec = TIMER_SET;        }                if (0 == (gTimer.Tick10Msec % 10))        {            bTemp100Msec = TIMER_SET;        }                if (100 == gTimer.Tick10Msec)        {            gTimer.Tick10Msec = 0;            bTemp1Sec = TIMER_SET;        }}

而這又有什么用呢 ?

這時,我們需在主輪詢while(1)內最開始調用一個定時處理函數如下:

void SysTimer _Process(void){    gTimer.Status.byte &= 0xF0;        if (bTemp10Msec)    {        bSystem10Msec = TIMER_SET;    }        if (bTemp50Msec)    {        bSystem50Msec = TIMER_SET;    }        if (bTemp100Msec)    {        bSystem100Msec = TIMER_SET;    }        if (bTemp1Sec)    {        bSystem1Sec = TIMER_SET;    }        gTimer.Status.byte &= 0x0F;}

此函數開頭與結尾兩句:

gTimer.Status.byte &= 0xF0;gTimer.Status.byte &= 0x0F

就分別巧妙的實現了bSystemXXX (低4位) 和 bTempXXX(高4位)的清零工作,不用再等定時到達后還需手動把計數值清零。此處清零工作用到了聯合體中的變量共用一個起始存儲空間的特性。

但要保證while(1)輪詢時間要遠小于10ms,否則將導致定時延時不準確。這樣,在每輪詢一次,就先把bSystemXXX ,再根據bTempXXX判斷是否時間到達,并把對應的bSystemXXX 置1,而后面所有的任務就都可以通過bSystemXXX來進行定時延時,在最后函數退出時,又會把bTempXXX清零,為下一次時間到達后查詢判斷作好了準備。

說了這么多,舉例說明一下如何應用:

void Task_A_Processing(void){    if(TIMER_SET == bSystem50Msec){        //do something    }}
void Task_B_Processing(void){    if(TIMER_SET == bSystem100Msec){        //do something    }}
void Task_C_Processing(void){    static uint8_t ticks = 0;    if(TIMER_SET == bSystem100Msec){       ticks ++ ;    }
    if(5 == ticks){        ticks = 0;         //do something    }
}
void Task_D_Processing(void){    if(TIMER_SET == bSystem1Sec){        //do something    }}

以上示例四個任務進程,

在主輪詢里可進行如下處理:

int main(void){    while(1)    {        SysTimer _Process();
        Task_A_Processing();        Task_B_Processing();        Task_C_Processing();Task_D_Processing();    }}

這樣,就可以輕松且清晰實現了多個任務,不同時間內處理不同事件。(但注意,每個任務處理中不要有阻塞延時,也不要處理過多的事情,以致處理時間較長。可設計成狀態機來處理不同任務。

審核編輯:湯梓紅


聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 單片機
    +關注

    關注

    6043

    文章

    44623

    瀏覽量

    638727
  • 延時
    +關注

    關注

    0

    文章

    107

    瀏覽量

    25586
  • STM32
    +關注

    關注

    2272

    文章

    10925

    瀏覽量

    357698
  • 定時器
    +關注

    關注

    23

    文章

    3256

    瀏覽量

    115407

原文標題:【軟件】精妙的用STM32單片機設計的非阻塞延時程序

文章出處:【微信號:玩轉單片機與嵌入式,微信公眾號:玩轉單片機與嵌入式】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    STM32單片機延時原理和延時函數方法

    當涉及到單片機編程時,延時是一項常見但關鍵的任務。在許多應用中,我們需要控制程序暫停一段時間,以實現精確的時間控制或協調不同設備之間的操作。本文將以STM32為例,介紹關于單片機延時
    發表于 08-09 09:13 ?1.8w次閱讀

    精妙的單片機阻塞延時程序設計

    [導讀]對于每個單片機愛好者及工程開發設計人員,在剛接觸單片機的那最初的青蔥歲月里,都有過點亮跑馬燈的經歷。從看到那一排排小燈按著我們的想法在跳動時激動心情。到隨著經驗越多,越來又會感覺到這個小燈
    發表于 05-23 15:23

    精妙的單片機阻塞延時程序設計

    對于每個單片機愛好者及工程開發設計人員,在剛接觸單片機的那最初的青蔥歲月里,都有過點亮跑馬燈的經歷。從看到那一排排小燈按著我們的想法在跳動時激動心情。到隨著經驗越多,越來又會感覺到這個小燈是個
    發表于 07-09 15:12

    精妙的單片機阻塞延時程序設計

    對于每個單片機愛好者及工程開發設計人員,在剛接觸單片機的那最初的青蔥歲月里,都有過點亮跑馬燈的經歷。從看到那一排排小燈按著我們的想法在跳動時激動心情。到隨著經驗越多,越來又會感覺到這個小燈是個好東西
    發表于 03-26 16:53

    PIC單片機精確延時函數的延時時間怎么計算?

    PIC單片機精確延時函數的延時時間怎么計算?
    發表于 04-25 12:52

    基于單片機+CPLD的多路精確延時控制系統設計

    根據多路精確延時控制系統的設計參數指標,利用單片機和CPLD的功能特性與片上資源,設計了基于CPLD與多個單片機的多路精確延時控制系統,實現了多路獨立調整、顯示,并能輸出
    發表于 12-16 16:15 ?43次下載

    51單片機匯編語言教程_單片機延時程序分析

    51單片機匯編語言教程:5課單片機延時程序分析
    發表于 01-19 15:26 ?0次下載

    單片機延時計算小程序

    單片機延時計算小程序
    發表于 12-01 16:44 ?2次下載

    單片機延時計算小程序

    單片機延時計算小程序
    發表于 12-28 11:07 ?6次下載

    單片機延時函數的資料合集免費下載

    本文檔的主要內容詳細介紹的是單片機延時函數的資料合集免費下載包括了:1.51單片機延時,晶振為11.0592MHz,(粗略延時,定時器
    發表于 08-02 17:34 ?8次下載
    <b class='flag-5'>單片機</b><b class='flag-5'>延時</b>函數的資料合集免費下載

    STM8S_002_TIM精確延時阻塞

    STM8S_002_TIM精確延時阻塞
    的頭像 發表于 03-20 10:51 ?3447次閱讀
    STM8S_002_TIM精確<b class='flag-5'>延時</b> (<b class='flag-5'>阻塞</b><b class='flag-5'>式</b>)

    單片機延時問題20問

    簡介:延時與中斷出錯,是單片機新手在單片機開發應用過程中,經常會遇到的問題,本文匯總整理了包含了MCS-51系列單片機、MSP430單片機
    發表于 11-13 21:06 ?6次下載
    <b class='flag-5'>單片機</b><b class='flag-5'>延時</b>問題20問

    51單片機 利用定時中斷做“阻塞”點燈

    。 今天的自學筆記記錄的例程是如何利用定時中斷,來做一個“阻塞”的閃燈程序。 這節內容,看似簡單,實際項目中卻有很多地方可以應用,比如模擬PWM波形,還有接下來要寫的 按鍵消抖清零 應用一、 “
    發表于 11-21 21:06 ?15次下載
    51<b class='flag-5'>單片機</b> 利用定時中斷做“<b class='flag-5'>非</b><b class='flag-5'>阻塞</b><b class='flag-5'>式</b>”點燈

    STM32單片機SysTick實現精確延時

    STM32單片機SysTick實現精確延時
    發表于 11-23 18:21 ?11次下載
    STM32<b class='flag-5'>單片機</b>SysTick實現精確<b class='flag-5'>延時</b>

    什么是阻塞阻塞

    什么是阻塞阻塞?我們就用管道的讀寫來舉例子。
    的頭像 發表于 03-25 10:04 ?559次閱讀
    主站蜘蛛池模板: 中文字幕三级 | 免费看又爽又黄禁片视频1000 | 黄色a∨| 亚洲另类电击调教在线观看 | 日韩毛片高清在线看 | 成人夜色视频网站在线观看 | 久久大尺度 | 丁香婷婷网 | 91午夜剧场| 日日干夜夜操s8 | 女同激情视频 | 国产亚洲一区二区三区啪 | 天天做天天爱天天一爽一毛片 | 婷婷激情小说网 | 91大神在线观看精品一区 | 黄 色 免费网 站 成 人 | 激情综合婷婷 | www.一区二区三区 | 天天干2018| 免费污视频在线 | 在线视频亚洲一区 | 天天看天天干天天操 | 无毒不卡在线播放 | 亚洲欧美日韩一区 | 免费精品视频在线 | 看a网站 | 国产小视频在线看 | 国产成人综合亚洲怡春院 | 国产一区二区三区在线观看视频 | 黄网观看| 四虎国产精品成人永久免费影视 | 亚洲人成网站在线 | 免费网站日本永久免费观看 | www.av免费| xvideos国产 | 国产精品久久久久久影院 | 欧美屁屁影院 | 无遮挡很爽很污很黄的网站w | 国产一级特黄在线播放 | 日韩亚射| 欧美黄色一级片视频 |