久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 23018|回復: 42
打印 上一主題 下一主題
收起左側

51單片機入門經驗分享4-定時器的使用

  [復制鏈接]
跳轉到指定樓層
樓主
本帖最后由 dabing89 于 2018-10-14 18:56 編輯

                                                    定時器的使用 ---20181013


好,繼續更新這個帖子,前邊我們點亮了流水燈,然而定時是用DELAY實現的,實際上在實際的項目中,DELAY基本上不會用,如果一個程序中,主循環有大量的DELAY出現,那么就不合理了,所以必須要用定時器 ,保證程序的實時性,這一貼,我們寫一個程序,用定時器0來實現LED間隔500MS閃爍的效果   ,代碼如下:   
  1. /*******************************************************************
  2. * 文件名  LED0 500MS閃爍
  3. * 描述:        點亮LED---用定時器的辦法
  4. * 2018-09-19 調試通過
  5. * 功能  入門模板
  6. * 作者: 大核桃
  7. * 版本號:V1.00(2018.09.19)
  8. ********************************************************************/
  9. #include "config.h"
  10. #include "intrins.h"


  11. /*******************************************************************
  12. * 文件名 變量重新定義區域
  13. * 描述:        
  14. * 功 能
  15. * 作者:大核桃
  16. * 版本號:V1.00(2018.09.17)
  17. ********************************************************************/

  18. typedef unsigned char uint8;//無符號字符型
  19. typedef unsigned int  uint16;//無符號整型
  20. typedef unsigned long uint32;//無符號長整型


  21. /*******************************************************************
  22. * 文件名:位重新定義區域 函數前置聲明
  23. * 描述:        
  24. * 功 能
  25. * 作者:大核桃
  26. * 版本號:V1.00(2018.09.17)
  27. ********************************************************************/
  28. void Delay500ms();                //@11.0592MHz
  29. void MCU_Port_Init(void);
  30. void Bsp_Tim0_Init(void);

  31. sbit LED0 = P1^0;
  32. sbit LED1 = P1^1;
  33. sbit LED2 = P1^2;
  34. sbit LED3 = P1^3;
  35. sbit LED4 = P1^4;
  36. sbit LED5 = P3^2;
  37. sbit LED6 = P0^0;
  38. sbit LED7 = P0^1;

  39. bit flag500ms = 0;//500ms定時標志位


  40. /*******************************************************************
  41. * 文件名 main函數入口
  42. * 描述:        
  43. * 功 能
  44. * 作者:大核桃
  45. * 版本號:V1.00(2018.09.17)
  46. ********************************************************************/
  47. void main(void)
  48. {
  49.         MCU_Port_Init();//端口模式初始化函數
  50.         Bsp_Tim0_Init();//定時器0初始化函數


  51.         while(1)
  52.         {           
  53.                 if(flag500ms)
  54.                 {
  55.                         P2 = 0XFE;//1111_1110;
  56.                 }
  57.                 else
  58.                 {
  59.                    P2 = 0XFF;//1111_1111;        
  60.                 }

  61.         }
  62. }

  63. /*******************************************************************
  64. * 文件名:void MCU_Port_Init(void)
  65. * 描述:        MCU端口上電初始化函數
  66. * 功 能
  67. * 作者:大核桃
  68. * 版本號:V1.00(2018.09.17)
  69. ********************************************************************/
  70. void MCU_Port_Init(void)
  71. {
  72.         //第0 和1位配置推完輸出模式,大電流
  73.         P0M1 = 0XFC; //        1111_1100
  74.         P0M0 = 0X03; // 0000_0011

  75.         //第01234位配置推完輸出模式,大電流,567配置高阻輸入,用于ADC
  76.         P1M1 = 0XE0; //1110_0000        
  77.         P1M0 = 0X1F; //0001_1111

  78.         //P2配置位準雙向口
  79.         P2M1 = 0X00; //0000_0000        
  80.         P2M0 = 0X00; //0000_0000

  81.         P2 = 0XFF;//P2口初始化為1

  82.         //P5配置位準雙向口
  83.         P5M1 = 0X00; //0000_0000        
  84.         P5M0 = 0X00; //0000_0000

  85.         P5 = 0XFF;//P5口初始化為1

  86.         //P3 23467推完輸出
  87.         P3M1 = 0X00; //0000_0000        
  88.         P3M0 = 0XFC; //1101_1100

  89.         P3 = 0X23;  //0010_0011


  90.         //上電IO默認是0
  91.         LED0 = 1;//輸出1
  92.         LED1 = 0;
  93.         LED2 = 0;
  94.         LED3 = 0;
  95.         LED4 = 0;
  96.         LED5 = 0;
  97.         LED6 = 0;
  98.         LED7 = 0;//
  99.                
  100. }

  101. /*******************************************************************
  102. * 文件名:void Bsp_Tim0_Init(void)
  103. * 描述:        定時器0初始化函數
  104. * 功 能
  105. * 作者:大核桃
  106. * 版本號:V1.00(2018.09.19)
  107. ********************************************************************/
  108. void Bsp_Tim0_Init(void)                //1000微秒@11.0592MHz
  109. {
  110.         AUXR |= 0x80;                //定時器時鐘1T模式
  111.         TMOD &= 0xF0;                //設置定時器模式
  112.         TMOD |= 0X01;      
  113.         TH0 = 0xD4;                    //設置定時初值
  114.         TL0 = 0xCD;                    //設置定時初值
  115.         TR0 = 1;                    //定時器0開始計時
  116.         ET0 = 1;            //使能定時器0的中斷
  117.         EA = 1;             //打開總中斷
  118. }

  119. /*******************************************************************
  120. * 文件名:TIM0_IRQ_Handler
  121. * 描  述:中斷服務函數        
  122. * 功  能 中斷服務標號 INT0 ET0 INT1 ET1 UART1 ADC LVD TIME2
  123. * 優先級:                      0            1    2         3          4           5   6    12
  124. * 版本號:V1.00(2018.09.19)
  125. ********************************************************************/
  126. void TIM0_IRQ_Handler(void) interrupt 1
  127. {
  128.     static uint16 tmr500ms = 0;

  129.         TH0 = 0xD4;                    //設置定時初值
  130.         TL0 = 0xCD;                    //設置定時初值

  131.         tmr500ms++;
  132.         if(tmr500ms >= 500)
  133.         {
  134.                 tmr500ms = 0;

  135.                 flag500ms = !flag500ms;        //500MS閃爍
  136.         }
  137.         
  138.                
  139. }
復制代碼


因為在實際使用中,定時器和中斷都是在一起配合使用,所以這兒我們就不分開,但是要說的是,定時器是硬件,是單片機內部存在的一個模塊,而中斷僅僅是一種處理問題的機制,上面這個d代碼看著不多,但是消息量很大,我們一點一點解剖,理解了定時器的的原理,等你上手STM32的時候,定時器原理可以直接不看,直接拿來用就好了。
    先從STC89C52RC的開始說起,我們知道,STC89C52RC是標準51內核,在標準51的體系下,12個時鐘周期是一個機器周期,啥意思呢?比如你的外部晶振是11.0592MHZ,那么11059200的倒數,也就是周期了,這個倒數叫做時鐘周期,也叫震蕩周期,算一下時間,1/11059200 = 0.0904US,這就是STC89C52的時鐘周期,那么51單片機就規定,12個這樣的時鐘周期為一個機器周期,所以在乘以12,那么一個機器周期的數值是1.085US,注意這是在11.0592MHZ下,如果是在12MHZ下,那么一個機器周期就是1US,這就是定時器的時間基準。我們再來看下,如果我們用STC89C52來做一個500MS的定時器該怎么做呢?配置如下即可實現:
  1. /*******************************************************************
  2. * 文件名:void Bsp_Tim0_Init(void)
  3. * 描述:        定時器0初始化函數
  4. * 功 能
  5. * 作者:大核桃
  6. * 版本號:V1.00(2018.09.19)
  7. ********************************************************************/
  8. void Bsp_Tim0_Init(void)                //1000微秒@11.0592MHz
  9. {
  10.         TMOD &= 0xF0;                //設置定時器模式
  11.         TMOD |= 0X01;      
  12.         TH0 = 0xFC;                    //設置定時初值
  13.         TL0 = 0x66;                    //設置定時初值
  14.         TR0 = 1;                    //定時器0開始計時
  15.         ET0 = 1;            //使能定時器0的中斷
  16.         EA = 1;             //打開總中斷

  17. }

  18. /*******************************************************************
  19. * 文件名:TIM0_IRQ_Handler
  20. * 描  述:中斷服務函數        
  21. * 功  能 中斷服務標號 INT0 ET0 INT1 ET1 UART1 ADC LVD TIME2
  22. * 優先級:                      0            1    2         3          4           5   6    12
  23. * 版本號:V1.00(2018.09.19)
  24. ********************************************************************/
  25. void TIM0_IRQ_Handler(void) interrupt 1
  26. {
  27.     static uint16 tmr500ms = 0;

  28.         TH0 = 0xFC;                    //設置定時初值
  29.         TL0 = 0x66;                    //設置定時初值

  30.         tmr500ms++;
  31.         if(tmr500ms >= 500)
  32.         {
  33.                 tmr500ms = 0;

  34.                 flag500ms = !flag500ms;        //500MS閃爍
  35.         }
  36.         
  37.                
  38. }
復制代碼



還是來解釋下,首先定時器的配置步驟是這樣的:
1.先設置TMOD這個寄存器,選擇定時器0的模式寄存器,配置定時器0為16位不可重裝載模式

2.設置定時器的定時初值,高八位和低八位
3.打開定時器的運行標志位,因為TCON是一個可位尋址的寄存器,所以直接TR0 = 1;就好。
4.使能定時器0的中斷ET0
5.打開總中斷EA
OK,這樣就配置好了寄存器,定時器也可以工作了,然而我們了解定時器是怎么運行的了嗎?沒有!!!很多人不知道為啥是這個數值,而且定時器的的初值還有好幾種寫法,如果有人用了不一樣的而寫法,你一定要知道是等價的寫法。


  關于初值的計算
   我們知道定時器0是一個16位的定時器,最大計數65536(0-65535)分為高八位和低八位,TH0存儲的是高八位的數據,TL0存儲的是低八位的數據,0XFC是一個16進制數值,換算10進制是252,0X66是102,我們知道低八位最大計數到255,TH0就變成1,然后進位,清零,又開始從0計數,那么我們可以算算這個初值是多少?252*256 +102 = 64614,而64614的16進制表示形式就是0XFC66,這樣我們就搞清楚定時器的計時原理了,如下所示,初值代碼可以改寫成這樣:
  1. TH0 = (65535 - 921) / 256;                    //設置定時初值
  2.         TL0 = (65535 - 921) % 256;                    //設置定時初值
復制代碼
也就是說,我們讓單片機從64614開始計數,到65535溢出,總共計數921個,而我們又知道1個機器周期是1.085US,那么921個機器周期是多少呢?921*1.085 = 1000US,正好是1MS的定時,我們在程序中讓其溢出500次,那么不就是500MS了嗎?就是這樣來的,原理一定要搞清楚。不管什么STM32,64,128都是這樣的原理{:lol:}。關于中斷使用的時候,打開使能就好了,EA是總中斷使能位,如果這個不打開,ET0單獨打開是沒用的,這才是一把手。
   關于STC15W系列的定時器
好了,既然我們搞清楚了,STC89C52的定時器的原理了,我們來看下,STC15W的定時器配置,因為我們都是定時1MS,那么,為啥初值不一樣呢?我們來算下STC15W的這個初值對應的10進制數值是多少?是54477,好陌生的數字,怎么來的呢?65536-54477 = 11059,也就是說在STC15W的內核下,我們只要計數11059個,就可以達到1MS的定時,我們知道,STC15W是單周期的時鐘,也就是說我們不12分頻,我們直接就是一個時鐘周期就是一個機器周期,(1/11059200)*11059 = 1ms,明白了吧?所以,本節的程序代碼,也可以這樣寫,是一樣的作用的。
  1. /*******************************************************************
  2. * 文件名:void Bsp_Tim0_Init(void)
  3. * 描述:        定時器0初始化函數
  4. * 功 能
  5. * 作者:大核桃
  6. * 版本號:V1.00(2018.09.19)
  7. ********************************************************************/
  8. void Bsp_Tim0_Init(void)                //1000微秒@11.0592MHz
  9. {
  10.         AUXR |= 0x80;                //定時器時鐘1T模式
  11.         TMOD &= 0xF0;                //設置定時器模式
  12.         TMOD |= 0X01;      
  13. //        TH0 = 0xD4;                    //設置定時初值
  14. //        TL0 = 0xCD;                    //設置定時初值
  15.         TH0 = (65535 - 11059) / 256;//設置定時初值
  16.         TL0 = (65535 - 11059) % 256;//設置定時初值
  17.         TR0 = 1;                    //定時器0開始計時
  18.         ET0 = 1;            //使能定時器0的中斷
  19.         EA = 1;             //打開總中斷

  20. }
復制代碼




關于在單片機中大量存在的& |運算的詳細說明
    其實這個,不太想說,但無奈上網看到好多初學者根本不知道& |的作用,還是詳細的說明下比較好,以定時器0的配置為例。
    AUXR |= 0x80; AUXR是一個輔助寄存器,這不需要多說,|= 0x80有什么講究呢?|(或),是讓某一位置1的意思,讓那一位置一呢?很明顯,讓是1的那一位置一,0X80不就是最高位是1嗎?那就是讓最高位置一好了,有人說,這有啥用呢?本來不就是1嗎?人家還有后半句,而其他位保持不變,其他位?啥位?等于0的那些對吧?也就是低7位不變了。這樣操作有啥好處呢?我們知道ET0 = 1;TR0 = 1;之所以可以這樣操作,是因為他們可以被位尋址,可以進行單獨的位操作,而AUXR是不可以進行位尋址的,因此一次操作必須操作8個位,你想想看,AUXR這個寄存器的功能如下圖:

   你能保證直接讓AUXR = 0X80,不對其他位造成影響嗎?現在大家的編程還比較簡單,只有一個定時器,要是用到3個,4個定時器呢?這樣不就互相干擾了嗎?扯淡么?所以 & |的重要性也就凸現出來了。
   再來看后面這2句,很明顯TMOD是不可以位尋址的,按照我們剛才的分析,|是讓某一位置一,那么&,自然就是讓某一位清零了,來看下0XF0,二進制是1111_0000,也就是低4位置0,高4位不要管,因為&是乘法運算啊,只要都是1,那么就是1,很明顯讓低4位清零,下一句是0000_0001,讓最低為置一啊,對吧,要注意,這里的2句是連續操作的,不是單獨的的操作,什么意思?前者的運算結果,又給了后者,所以我們總體來看這2句代碼,先讓低四位清零,高四位不變,然后將這個結果進行或運算,讓最低位置一,而高7位都不變,因為任何數|還是任何數啊,對吧,這就達到了一個互不干擾的目的,這樣的代碼在STM32上好多好多的,都是起到一個互不干擾的作用。這樣的做法可以確保定時器0和定時器1是獨立的,如果我們不這樣做,你看看是工作在啥模式?除了定時器配置在16位不可重裝模式在,定時器1被配置在了16位自動重裝定時器,我們沒有使用定時器1,萬一出錯怎么辦?這就不好了。
  

關于自動重裝載和不可自動重裝模式
  其實,沒啥太大的區別,如果是自動重裝,那么在中斷服務函數中,TH0 TL0就不需要去再去重新賦值了,直接刪掉就好,如果不是自動重裝,則必須要加。還差點忘了一個事,你怎么確定你的定時是500MS呢?答案不能靠眼睛看把,看看示波器觀察的結果,嗯,是對的。如下圖,1S 1HZ的方波信號

好了,今天就到這里吧,代碼上傳 004 定時器的使用.rar (30.68 KB, 下載次數: 92)






評分

參與人數 2黑幣 +11 收起 理由
新鄉家電維修 + 5 很給力!
jstele + 6

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏35 分享淘帖 頂13 踩
回復

使用道具 舉報

沙發
ID:371529 發表于 2018-10-14 14:51 | 只看該作者
我不明白為啥這么好的分享瀏覽量這么低呢,樓主加油
回復

使用道具 舉報

板凳
ID:74187 發表于 2018-10-14 15:28 | 只看該作者
哈哈我哈哈 發表于 2018-10-14 14:51
我不明白為啥這么好的分享瀏覽量這么低呢,樓主加油

謝謝支持
回復

使用道具 舉報

地板
ID:410928 發表于 2018-10-26 09:53 | 只看該作者
樓主厲害
回復

使用道具 舉報

5#
ID:388099 發表于 2018-10-27 16:29 | 只看該作者
感謝分享,正在學習單片機,
回復

使用道具 舉報

6#
ID:406748 發表于 2018-10-27 22:41 | 只看該作者
感謝分享
回復

使用道具 舉報

7#
ID:85743 發表于 2018-10-29 14:15 | 只看該作者

感謝分享,正在學習單片機,
回復

使用道具 舉報

8#
ID:417624 發表于 2018-10-29 22:45 | 只看該作者
真的好實用,正好解決了我的疑惑,力贊!!!!!
回復

使用道具 舉報

9#
ID:400074 發表于 2018-11-2 06:55 | 只看該作者
挺不錯的資料
回復

使用道具 舉報

10#
ID:218360 發表于 2018-11-15 18:25 | 只看該作者
咋沒有專門寫匯編語言的內容?
回復

使用道具 舉報

11#
ID:156220 發表于 2018-11-20 08:49 | 只看該作者
謝謝樓主的分享,很詳細的講解
回復

使用道具 舉報

12#
ID:244544 發表于 2018-11-20 11:33 | 只看該作者
好東東,下載學習下!!1
回復

使用道具 舉報

13#
ID:400349 發表于 2018-11-21 01:22 來自手機 | 只看該作者
樓主,我有個地方不懂,從第二次溢出開始,進入中斷后tmr500ms不是都會重新賦值為零嗎,這樣子不是不會大于或等于500嗎,那怎么執行if函數
回復

使用道具 舉報

14#
ID:74187 發表于 2018-11-21 15:40 | 只看該作者
陳臣塵 發表于 2018-11-21 01:22
樓主,我有個地方不懂,從第二次溢出開始,進入中斷后tmr500ms不是都會重新賦值為零嗎,這樣子不是不會大于 ...

void TIM0_IRQ_Handler(void) interrupt 1
{
    static uint16 tmr500ms = 0;

        TH0 = 0xFC;                    //設置定時初值
        TL0 = 0x66;                    //設置定時初值

        tmr500ms++;//這個你應該沒有看到
回復

使用道具 舉報

15#
ID:421232 發表于 2018-12-13 11:39 | 只看該作者
謝謝樓主分享
回復

使用道具 舉報

16#
ID:450718 發表于 2018-12-24 14:33 | 只看該作者
學習 學習
回復

使用道具 舉報

17#
ID:461889 發表于 2019-1-23 11:46 | 只看該作者
感謝分享
回復

使用道具 舉報

18#
ID:345426 發表于 2019-3-23 21:42 | 只看該作者
謝謝分享好好學習。
回復

使用道具 舉報

19#
ID:511868 發表于 2019-4-14 14:46 | 只看該作者
謝謝分享好好學習
回復

使用道具 舉報

20#
ID:505803 發表于 2019-4-14 16:34 | 只看該作者
這個文章真是太接地氣了,基本上把定時掰開了講清楚了
說的非常好,初學者都能夠看懂,
受益良多
回復

使用道具 舉報

21#
ID:278200 發表于 2019-6-15 14:24 | 只看該作者
感謝分享!!!
回復

使用道具 舉報

22#
ID:138119 發表于 2019-7-28 18:23 | 只看該作者
很適合初學者,或者這方面理解不清的朋友!
講的非常好,樓主加油~~~~~
回復

使用道具 舉報

23#
ID:546770 發表于 2019-7-28 18:37 | 只看該作者
這是真的好貼,加油!
回復

使用道具 舉報

24#
ID:600135 發表于 2019-8-15 08:31 來自手機 | 只看該作者
樓主 是怎么自學的
回復

使用道具 舉報

25#
ID:689073 發表于 2020-2-11 07:21 | 只看該作者


感謝分享,正在學習單片機,
回復

使用道具 舉報

26#
ID:781074 發表于 2020-6-16 15:12 | 只看該作者
謝謝樓主的分享,很詳細的講解
回復

使用道具 舉報

27#
ID:785551 發表于 2020-9-2 16:36 | 只看該作者
樓主,還有后續經驗分享嗎??
回復

使用道具 舉報

28#
ID:816540 發表于 2020-9-15 22:38 | 只看該作者
講解的很清楚,謝謝!
回復

使用道具 舉報

29#
ID:863412 發表于 2021-1-12 16:38 | 只看該作者
樓主高手,謝謝了!
回復

使用道具 舉報

30#
ID:878420 發表于 2021-1-23 20:14 | 只看該作者
感謝分享,正在學習單片機!
回復

使用道具 舉報

31#
ID:883622 發表于 2021-2-10 20:52 | 只看該作者
回復

使用道具 舉報

32#
ID:513213 發表于 2021-3-2 08:50 | 只看該作者
感謝分享,正在學習單片機
回復

使用道具 舉報

33#
ID:928284 發表于 2021-7-9 17:57 | 只看該作者
溫習定時器的使用,多看看有啟發。
回復

使用道具 舉報

34#
ID:497561 發表于 2022-3-7 09:43 | 只看該作者
對初學者很友發,值得多看幾次
回復

使用道具 舉報

35#
ID:1001745 發表于 2022-4-9 18:53 | 只看該作者
這樣的C教材還是第一次拜讀,比那些所謂名校的教材更加通俗易懂
回復

使用道具 舉報

36#
ID:1007896 發表于 2022-5-1 20:34 | 只看該作者
別的不服,就服樓主。&、|、TH0、TL0講得非常非常清楚!
回復

使用道具 舉報

37#
ID:962396 發表于 2022-6-22 17:28 | 只看該作者
謝謝樓主我會來學習的
回復

使用道具 舉報

38#
ID:260656 發表于 2022-10-19 10:44 | 只看該作者
就是定時器搞不懂,這文章太好了,萬分感謝!
回復

使用道具 舉報

39#
ID:1049825 發表于 2022-10-31 20:19 | 只看該作者
聽君一席話,勝讀十年書,拜謝!
回復

使用道具 舉報

40#
ID:958799 發表于 2022-12-29 16:44 | 只看該作者
說實話,這是我看過講定時器講的最清楚的了,點贊
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 91文字幕巨乱亚洲香蕉 | 亚洲高清成人 | 欧美日韩亚洲系列 | 免费一级毛片 | 日韩中文字幕免费在线观看 | 日韩免费网站 | 91精品麻豆日日躁夜夜躁 | 中文字幕成人在线 | 99热国产在线播放 | 国产成人免费在线 | 亚洲色综合 | 亚洲欧美中文日韩在线v日本 | 久久国产精品久久久久久久久久 | 欧美一区二区三区视频 | 伦理午夜电影免费观看 | 中文字幕日韩欧美 | 亚洲综合色丁香婷婷六月图片 | 成人精品一区亚洲午夜久久久 | 特级特黄特色的免费大片 | 亚洲免费精品 | 啪啪免费网站 | 国产激情视频在线 | 久久青| 国产一级毛片精品完整视频版 | 99精品欧美一区二区蜜桃免费 | 日韩视频观看 | 不卡av在线| 国产一区久久 | 日韩免费高清视频 | 操久久 | 久久99久久久久 | 视频在线一区二区 | 欧美成人激情 | 亚洲欧洲一区二区 | 亚洲成人蜜桃 | 欧美日韩精品一区二区天天拍 | 欧美一区二区三区在线看 | 日韩乱码一二三 | 欧美视频1区 | 日本超碰 | 国产精品久久久久久久久久 |