精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

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

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

3天內不再提示

C51單片機的定時器介紹

CHANBAEK ? 來源:Zi Jin Code ? 作者: 錕醬不是醬 ? 2023-11-02 10:48 ? 次閱讀

定時器是生活中常見的一種定時裝置,常見的定時器有機械定時器和電子定時器

使用的時候我們給他設置時間,當我們指定的時間到了以后定時器會給我們提醒

其實,每天都跟我們打交道的單片機里面也有一個簡單的定時器,他一直站在單片機的角落,為機器精確的定時默默的奉獻出自己的一份力量

(1)單片機的心臟與機器周期

總所周知,單片機的心臟——晶振是一顆很重要的原件,晶振負責給單片機提供穩定的周期頻率,保證單片機的穩定運行

晶振是一顆能產生穩定脈沖頻率的電子期間,通電的時候,晶振每一秒發出脈沖頻率的次數分之一成為晶振頻率

晶振頻率 = 1秒/1秒內晶振發出脈沖的次數

我們把晶振頻率記作f,晶振周期記作T

晶振周期T= 1/晶振頻率

在單片機里面,單片機完成一次操作所用的時間叫做機器時間。這里不得不說明,在匯編里面,單片機的機器時間是12個晶振周期,但是在C語言里面,這個周期是不固定的,這也就是為什么用空循環來延遲,得不到精確的時間

void delay(unsigned int xms)  //調用時需提供參數xms的實際值。
{
  unsigned int i,j;   //定義無符號整型變量i、j
  for(i=0; i< xms; i++)  //后面沒帶";",下一條語句是循環體。參數xms延時x毫秒。
      for(j=0; j< 110; j++);  //后面帶";",表示這個for語句的循環體是空語句。
}//這個值得學習,這里的代碼是延遲代碼


//復制請注明原作者 謝謝  
//復制請注明原作者 謝謝

這也就是為什么我們不太建議用這個延遲精確時間的緣由

因為C51在匯編狀態的機器周期是12,所以可以認為單片機的機器周期值就是12

本小節講到這里就結束啦,這一節大家就要記住

·單片機的機器周期值是12,機器頻率 = 12f(晶振周期)

·f(晶振頻率) = 1/晶振1秒脈沖次數

·T(晶振周期)=1/f

(2)認識定時器的結構

單片機里面的定時器結構圖示如下(這個是我自己畫的,有點丑)

圖片

如圖所示,C51定時器原理如圖,定時器里面有一個寄存器,單片機每經過一次機器周期就會自動給這個寄存器+1,一直加,直到寄存器滿溢出,溢出后寄存器自動恢復0,并且給出一個信號告訴我們寄存器滿了.這就是定時器一次定時的工作流程

(3)定時器結構

C51中,一共有兩組定時器,記作T0,T1定時器不僅能定時,還可以當計數器使用。我們本節主要討論定時器。

定時器由三個寄存器組成

  1. 計數寄存器

C51里面的定時器有兩組(TH0,TL0)(TH0,TL1),每組由高八位和低八位組成的十六位寄存器

TH1,TL1屬于定時器1,TH0,TL0屬于定時器0

這里有個特別重要的概念!!,定時器的溢出

定時器的溢出不是滿了就算溢出,而是,滿了再加一才算溢出,拿T0舉例,現在T0的寄存器的數值是0xFFFF(65535,1111 1111 1111 1111),這時候再加一,才會溢出(也就是65535+1 = 65536才溢出),這就意味著我們計算的時候,溢出值要用65536來計算

為了方便使用定時器,我們需要給定時器的寄存器設置初始值,下面先介紹如何計算定時器初始值

假設單片機使用11.0592MHz的晶振,那么……

機器的頻率f = 1/11059200

前面我們知道,定時器會在每一次機器周期自動+1,也就是說定時器每加一一次的時間是機器周期t ,t = 12/晶振周期T

定時器計數計到65536才算溢出

假設延遲S(注意單位是秒),1000毫秒 = 1秒

計算的時候要使用Hz作為頻率單位,1MHz = 1 000 000Hz

假設定時器計數N次,溢出

那么步長N = (晶振頻率f * 要延遲的秒數S)/ 12(機器周期)

初始值X = 65536 - 步長N

/*
小練筆,假設晶振頻率是11.0592MHz
單片機周期是12
現在要延遲20ms


計算步長和初始值
20ms = 0.02s
步長N = 11059200 * 0.02/12 = 18432
初始值X=65536-N = 47104


*/

細心的朋友可能發現了,如果從0開始計時,C51定時器定時的時長最大值是0.07111

那我要如何延遲超過71ms的時間呢,這里有個方法:重復,讓定時器重復延遲多次,達到我們想要的時間,不過這就算是后話了,后面實例的時候再說吧

2.TCON寄存器

TCON寄存器在機器里的地址:0x88,可位尋址,復位值(單片機復位的時候寄存器的值) = 0x00(0000 0000)

在定時器里面,TCON寄存器主要有兩個作用,開關定時器,復位和檢測定時器是否溢出

圖片

TF

檢測定時器是否溢出,沒有溢出的時候是0,溢出的時候是1。

當定時器溢出的時候要我們手動給TF寄存器寫0復位

TR:定時器開關,寫0的時候關閉定時器自動計數定時,寫1的時候啟用定時器計數定時。

TF1,TR1屬于定時器1,TF0,TR0屬于定時器0

注意這個寄存器是可位尋址的(可以直接訪問寄存器中的某個地址),舉個栗子哈,如果我們要哦將TR1寫0,我們不用操作整個寄存器,只需要

TR1 = 0

即可

以下是TCON寄存器在定時器下的使用方法合集(這些關鍵字在reg52.h里面已經被定義,使用的時候像下面一樣用直接用)

TR0 = 0;//關閉Timer0
TR0 = 1;//打開Timer0


TR1 = 0;//關閉Timer1
TR1 = 1;//打開Timer1
//----------------------------------------
if (TF0 == 1){TF0 = 0;}//判斷Timer0是否溢出,如果溢出,重置溢出判斷位
if(TF1 ==1){TF1 = 0;}//判斷Timer1是否溢出,如果溢出,重置溢出判斷位


//特別提醒,溢出后一定要記得重置TF

特別提醒,溢出一定要記得重置TF位

3.TMOD寄存器

TMOD寄存器在機器里的地址:0x89,不可位尋址,復位值(單片機復位的時候寄存器的值) = 0x00(0000 0000)

TMOD寄存器設置寄存器的模式,我們先來看看TMOD寄存器的結構

高位對應Timer1,低位對應Timer0

圖片

名稱功能
GATE置1的時候為門控位,正常使用定時器置0
C/T切換定時,計數器。置1使用計數器,置0使用定時器
M1定時器模式設置,請看下表
M0

我們發現,定時器有兩組模式設置位,這兩組模式設置為能組合出4種模式

M1M0模式功能
00兼容8048單片機13位定時/計數器
0116位定時/計數器
10把一個定時器的寄存器拆開成兩個八位,第一個八位滿了就把這個值給到另一個8位,繼續計時
11禁用Timer1,這時候Timer0相當于兩個8位Timer

最常用的是M1 = 0,M0 = 1的16位定時器

總結,TMOD定時器的設置方法:設置一個16位定時器

功能設置值說明
GATE0不使用門控位
C/T0設置值位0的時候使用定時器
M10使用16位定時器
M01

這里必須要說明,TMOD寄存器是不可位尋址的,我們不能直接訪問這個寄存器里面的某一個地址。這就是說我們不能用GATE1 = 0;之類的方法來設置TMOD寄存器,修改的時候一次性修改整個TMOD寄存器

//按照上面的式設置寄存器
TMOD = 0x01;//TMOD寄存器修改值位0x01---》 0000 0001 16位定時器,Timer0 模式1
TMOD = 0x10;//TMOD寄存器修改值位0x01---》 0001 0000 16位定時器,Timer1 模式1

這樣就完成了最基本的16位定時器設置

定時器結構

圖片

這里大家做個簡單的了解就行

我們可以看到,OSC是晶振,/d得到機器周期,這就是給寄存器+1的信號

這個信號經過C/T(定時/計數器選擇)當C/T = 0的時候選擇定時器,當C/T = 1的時候選擇計數器

GATE是一個門控位置,GATE的信號經過一個非門取反,也就是說GATE = 0的時候非門的一端輸出1,GATE = 0的時候非門的一端輸出0GATE配合Intr(這是一個外部中斷輸入口,沒有信號的時候置0),這個電路后面經過一個或門,只要有一路或者兩路為高電平就輸出高電平,兩路都輸出低電平的時候輸出低電平

TR是使用定時/計數器的總開關,這里有個與門,只有兩路都輸入高電平的時候才會輸出高電平,輸出高電平的時候控制后面的開關,把信號輸入到計數器的寄存器

當計數器的寄存器溢出的時候就出發TF,TF = 1;

到了這,就不難理解這些寄存器怎么設置了

首先,我們把GATE設置成0,因為我們用不上Intr外部中斷輸入,Intr = 0,GATE設置成0以后機器經過或門的時候輸出1。

或門輸出1的時候,我們置TR = 1,這樣與門輸出1,信號就能通到計數寄存器上了

這時置C/T = 0,讓脈沖源來自機器周期的脈沖信號

修改M0=1,M1=0。使用16位寄存器

一個標準16位定時器設置值

GATEC/TM0M1TFTRTHTL
001001根據需要設置值

以下是定時器操作的全部代碼,我們以Timer0為例子

#include< reg52.h >
void main()
{//注意設置定時器初始值要在main函數里面設置


  TMOD = 0x01;

  /*設置定時器模式寄存器TMOD為 0000 0001
  GATE = 0
  C/T = 0
  M1 =0
  M0 = 1
  標準16位定時器
  */

  //先設置定時器初始值
  TL0 = 0x3A;//設置定時器初始值低位
  TH0 = 0x8E;//設置定時器初始值高位
 
  TR0 = 0//記得一定要設置定時器開啟

  while(1)
  {
    if (TF0 == 1)
      {//這里可以先放下你的定時器計時滿了以后要執行的代碼
      
       //溢出后你需要先給你的定時器再次設置初始值
        TL0 = 0x3A;//設置定時器初始值低位
        TH0 = 0x8E;//設置定時器初始值高位

        TF0 = 0;//設置好初始值后再復位定時器
      }
  }
}

以上就是最基本的操作方法咯,前面我們說過,如果只使用定時器,單片機最長延遲71ms,如果需要延遲更長的時間,可以利用單片機重復延遲

使用11.0592MHz的晶振,在這里,我們計算出延遲1ms的初始值是921.6

這里,如果初始值設置為921,時間會略微段短一點,設置為922,又會略微長一點,這就是為什么我們要精確定時的時候,使用11.0592MHz的晶振會不準,使用12MHz的晶振是不錯的解決辦法,可惜使用了12MHz的晶振,又無法進行正常的串口通訊(這個后面再提吧)

這里我取的數值是922,因為偏差比921小

以下是延遲函數delay()的參考代碼

#include< reg52.h >
void main()
{//注意設置定時器初始值要在main函數里面設置


  TMOD = 0x01;

  /*設置定時器模式寄存器TMOD為 0000 0001
  GATE = 0
  C/T = 0
  M1 =0
  M0 = 1
  標準16位定時器
  */

  TL0 = 0x03;//設置定時器初始值低位
  TH0 = 0x9A;//設置定時器初始值高位

  void delay(unsigned int Ms)//延遲函數,輸入的單位是毫秒
  {
    unsigned int counter = 0;
    TR0 =1;//啟用定時器
    for(counter = 0;counter< Ms;counter++)
    {
      while(TF0 !=0){}//循環一直進行,直到TF0不再是0
      TL0 = 0x03;//設置定時器初始值低位
      TH0 = 0x9A;//設置定時器初始值高位
      TF0 = 0;//復位溢出位,復位之前一定要先設置好初始值
    }
    TR0 = 0;//關閉定時器
  }
  
  while(1)
  {
   delay(1);//測試定時器
   delay(10);
   delay(100);
   delay(1000);
  }
}

這個參考代碼不算特別完整,僅供多次定時器延遲達到一個長于71ms的一種方法

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

    關注

    6032

    文章

    44525

    瀏覽量

    633247
  • 寄存器
    +關注

    關注

    31

    文章

    5325

    瀏覽量

    120052
  • 晶振
    +關注

    關注

    34

    文章

    2834

    瀏覽量

    67919
  • 定時器
    +關注

    關注

    23

    文章

    3241

    瀏覽量

    114511
  • C51單片機
    +關注

    關注

    12

    文章

    164

    瀏覽量

    34727
收藏 人收藏

    評論

    相關推薦

    C51單片機_定時器可調時鐘_程序

    C51單片機_定時器可調時鐘_程序
    發表于 08-28 10:36 ?57次下載

    基于51單片機定時器2的操作與實現

    基于51單片機定時器2的操作與實現,51單片機定時器2的使用!
    發表于 02-22 17:53 ?14次下載

    52單片機有幾個定時器?52單片機定時器1和52單片機定時器2程序對比

    52單片機有幾個定時器?STC89C52RC其實是有三個定時器單片機,STC89C52RC共有
    發表于 11-10 14:30 ?3.5w次閱讀

    C51單片機定時器介紹

    C51單片機定時器介紹 標準51架構的單片機有2個定時器
    發表于 11-24 01:32 ?3569次閱讀
    【<b class='flag-5'>C51</b>】<b class='flag-5'>單片機</b><b class='flag-5'>定時器</b><b class='flag-5'>介紹</b>

    C51單片機定時器Timer的使用及產生1ms系統Tick的詳細資料說明

    本文檔的主要內容詳細介紹的是C51單片機定時器Timer的使用及產生1ms系統Tick的詳細資料說明。
    發表于 07-09 17:40 ?1次下載
    <b class='flag-5'>C51</b><b class='flag-5'>單片機</b><b class='flag-5'>定時器</b>Timer的使用及產生1ms系統Tick的詳細資料說明

    51單片機定時器C語言程序免費下載

    本文檔的主要內容詳細介紹的是51單片機定時器C語言程序免費下載。
    發表于 09-06 16:14 ?7次下載
    <b class='flag-5'>51</b><b class='flag-5'>單片機</b>的<b class='flag-5'>定時器</b><b class='flag-5'>C</b>語言程序免費下載

    使用STC單片機實現PCA定時器C51配套例程免費下載

    本文檔的主要內容詳細介紹的是使用STC單片機實現PCA定時器C51配套例程免費下載
    發表于 03-01 17:58 ?7次下載

    基于89c51單片機的時鐘可調定時器設計

    基于89c51單片機的時鐘可調定時器設計
    發表于 08-31 10:05 ?60次下載

    51單片機——定時器

    51單片機——定時器為什么使用定時器定時器原理?定時器設置中斷配置源代碼為什么使用
    發表于 11-11 16:36 ?40次下載
    <b class='flag-5'>51</b><b class='flag-5'>單片機</b>——<b class='flag-5'>定時器</b>

    51單片機定時器中斷

    定時器介紹:51單片機定時器屬于單片機的內部資源,其電路連接和運轉均在
    發表于 11-11 19:36 ?7次下載
    <b class='flag-5'>51</b><b class='flag-5'>單片機</b><b class='flag-5'>定時器</b>中斷

    C51單片機C52單片機內部的資源區別

    C52單片機可以理解為是C51單片機的增強版? 兩個方面有差異,存儲空間和定時器計數方面有區別
    發表于 11-19 10:36 ?20次下載
    <b class='flag-5'>C51</b><b class='flag-5'>單片機</b>與<b class='flag-5'>C</b>52<b class='flag-5'>單片機</b>內部的資源區別

    51單片機定時器中斷

    定時器介紹:51單片機定時器屬于單片機的內部資源,其電路連接和運轉均在
    發表于 11-20 20:36 ?15次下載
    <b class='flag-5'>51</b><b class='flag-5'>單片機</b><b class='flag-5'>定時器</b>中斷

    基于AT89C51單片機定時器設計的門鈴仿真及代碼

    基于AT89C51單片機定時器設計的門鈴仿真及代碼
    發表于 05-04 15:33 ?2次下載

    基于89C51單片機定時器0源程序

    基于89C51單片機定時器0源程序
    發表于 05-16 09:17 ?0次下載

    基于89C51單片機定時器2源程序

    基于89C51單片機定時器2源程序
    發表于 05-16 09:17 ?0次下載