<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                【86.1 定時中斷應用的四大關鍵詞。】 本節主要內容有四大個關鍵詞:1ms,互斥量,volatile,switch。 (1)1ms。把定時中斷設置為1ms中斷一次,幾乎是單片機界公認的“標配”。這個1 ms是系統時間的節拍來源,有了1ms“標配”意識,你的程序在不同單片機平臺上移植的時候會得心應手運用自如。 (2) 互斥量。“主函數”與“定時中斷函數”,本質上是兩個獨立進程在不斷切換并行運行,兩個進程之間不斷切換,就會涉及到數據的安全保護,數據的安全保護主要是針對多字節的變量,比如int類型(2個字節),long類型(4個字節)。但是單字節的char變量不用額外保護,因為“字節”是變量中的最小單位(在不考慮“位”的情況下),這里的“最小單位不可分”就像“原子是最小單位不可分”一樣,因此也有很多前輩把“互斥量”稱為“原子鎖”。為什么要用互斥量?因為,在多個線程同時訪問同一個全局變量的時候,如果雙方都是“讀操作”,則不會出現問題,但是,如果雙方都是“既有寫操作也有讀操作”的情況下,比如,我在主函數里正在修改(寫操作)一個unsigned int類型的變量,unsigned int類型的變量占用2個字節,在更改數據的時候至少需要2條指令,當我剛執行完第1條指令還沒來得及執行第2指令的時候,突然來了一個定時中斷,并且在定時中斷函數里也對這個變量進行了修改(寫操作)并且還進行了讀取判斷操作,這個瞬間就可能給程序帶來了隱患。話說回來,互斥量到底有沒有必要,其實還是有點爭議的,我曾經為這個問題糾結過很久,畢竟,如果不用互斥量,這么微觀的隱患到底存不存在,目前很難做一個“讓故障重現”的實驗去證明,最后,我是本著“寧可信其有不可信其無”的態度,把互斥量應用在了我的工作中。 (3) volatile。volatile是一個前綴的修飾關鍵詞,也是用來保護主函數與中斷函數共用的全局變量的,只不過,volatile是針對C編譯器的,預防“C編譯器在優化代碼的時候誤傷一些重要的共享數據”,就像預防殺毒軟件用力過猛把一些合法軟件當作病毒而誤殺。加了volatile修飾的全局變量,就能提醒C編譯器不要對這類特殊變量擅作主張去優化。 (4) switch。switch是“非阻塞程序框架”的核心語句,在以switch為核心的框架下,進行不同步驟之間的程序跳轉,是做大型裸機程序的常態。 【86.2 主函數與定時中斷函數的程序框架。】 主函數與定時中斷函數之間相互配合,主函數負責做什么,中斷函數負責做什么,對于初學者來說可能是一頭霧水,但是對于像我這種在單片機界深耕多年即將修煉成精的工程師來說,我心中是有很清晰的模板和套路的,這種模板和套路是經過多年沉淀下來的經驗。比如,定時中斷函數盡量放一些精簡的計時器代碼,一般不調用函數,但是“輸入IO口的消抖動”(按鍵掃描)以及“蜂鳴器鳴叫”這兩類特殊函數我是喜歡破例放在定時中斷函數里調用的。定時中斷如何產生時間,這個時間如何跟主函數關聯起來,請看下面的框架代碼: volatile unsigned char vGu8TimeFlag=0; //互斥量變量標志 volatile unsigned int vGu16TimeCnt=0; //計時器變量 void main() { vGu8TimeFlag=0; //在“寫操作”vGu16TimeCnt全局變量之前,互斥量vGu8TimeFlag的“加鎖” vGu16TimeCnt=1000; //全局變量的賦值,就是“寫操作” vGu8TimeFlag=1; //互斥量vGu8TimeFlag的“解鎖”。同時也起到“啟動計時器”的開關作用 while(1) //主循環 { if(0==vGu16TimeCnt) //時間變量為0則表示時間到了 { ...在這里執行具體的功能代碼 } } } void T0\_time() interrupt 1 //每1ms中斷一次的定時中斷函數 { if(1==vGu8TimeFlag&&vGu16TimeCnt>0) //判斷vGu8TimeFlag是否等于1,就是互斥量的判斷。 { vGu16TimeCnt--; //“自減一”的操作 } } 分析:上述代碼中,vGu8TimeFlag是一箭雙雕,既起到互斥量的作用,也起到了計數器vGu16TimeCnt開始計時的啟動開關作用。 【86.3 練習例程。】 現在根據上述程序框架,編寫一個LED燈閃爍的程序。 ![](https://img.kancloud.cn/0f/49/0f49cc4e7b34f0e8c13dd7e514906c88_214x279.png) 圖86.3.1 灌入式驅動8個LED \#include "REG52.H" \#define BLINK\_TIME 500 //時間是500ms sbit P0\_0=P0^0; volatile unsigned char vGu8TimeFlag=0; //互斥量變量標志 volatile unsigned int vGu16TimeCnt=0; //計時器變量 unsigned char Gu8Step=0; //switch的切換步驟 void main() { TMOD=0x01; //設置定時器0為工作方式1 TH0=0xfc; //產生1ms中斷的TH0初始值 TL0=0x66; //產生1ms中斷的TL0初始值 EA=1; //開總中斷 ET0=1; //允許定時0的中斷 TR0=1; //啟動定時0的中斷 while(1) //主循環 { switch(Gu8Step) { case 0: if(0==vGu16TimeCnt) //時間到 { P0\_0=0; //LED燈亮 vGu8TimeFlag=0; //互斥量“加鎖” vGu16TimeCnt=BLINK\_TIME; //計時器的寫操作。設定計時的長度 vGu8TimeFlag=1; //互斥量“解鎖”,同時蘊含了計時器“啟動”的動作 Gu8Step=1; //切換到case 1這個步驟 } break; case 1: if(0==vGu16TimeCnt) //時間到 { P0\_0=1; //LED燈滅。 vGu8TimeFlag=0; //互斥量“加鎖” vGu16TimeCnt=BLINK\_TIME; //計時器的寫操作。設定計時的長度 vGu8TimeFlag=1; //互斥量“解鎖”,同時蘊含了計時器“啟動”的動作 Gu8Step=0; //切換到case 0這個步驟,依次循環 } break; } } } void T0\_time() interrupt 1 //定時器0的中斷函數,每1ms單片機自動執行一次此函數 { if(1==vGu8TimeFlag&&vGu16TimeCnt>0) //判斷vGu8TimeFlag是否等于1,就是互斥量的判斷 { vGu16TimeCnt--; //“自減一”的操作 } TH0=0xfc; //重裝初值,不能忘 TL0=0x66; //重裝初值,不能忘 } 【86.4 解決閃爍出現不規則“非對稱感”現象的方法。】 上述例子,實驗現象應該是LED閃爍很有規則的每1s閃爍一次,但是也有一部分初學者可能會遇到閃爍出現不規則“非對稱感”的現象,這個問題的解決辦法如下:在Keil2的project下拉菜單下,選擇Options for Target選項,彈出的窗口中,切換到Target選項,在Memory Model選項中選擇small:variables in Data。 ![](https://img.kancloud.cn/8f/62/8f625296f7bfcca3047d9b0e26f69403_464x260.png) 圖86.4.1 設置窗口
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看