找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 9507|回復(fù): 5
打印 上一主題 下一主題
收起左側(cè)

C51單片機(jī)定時(shí)器介紹

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:492319 發(fā)表于 2019-4-4 17:43 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式


簡(jiǎn)介

C51中的定時(shí)器和計(jì)數(shù)器是同一個(gè)硬件電路支持的,通過寄存器配置不同,就可以將他當(dāng)做定時(shí)器或者計(jì)數(shù)器使用。
確切的說,定時(shí)器和計(jì)數(shù)器區(qū)別是致使他們背后的計(jì)數(shù)存儲(chǔ)器加1的信號(hào)不同。當(dāng)配置為定時(shí)器使用時(shí),每經(jīng)過1個(gè)機(jī)器周期,計(jì)數(shù)存儲(chǔ)器的值就加1。而當(dāng)配置為計(jì)數(shù)器時(shí),每來一個(gè)負(fù)跳變信號(hào)(信號(hào)從P3.4 或者P3.5引腳輸入),就加1,以此達(dá)到計(jì)數(shù)的目的。

標(biāo)準(zhǔn)C51有2個(gè)定時(shí)器/計(jì)數(shù)器:T0和T1。他們的使用方法一致。C52相比C51多了一個(gè)T2。



時(shí)鐘周期與機(jī)器周期

定時(shí)器的本質(zhì)原理就是:每經(jīng)過1個(gè)機(jī)器周期,計(jì)數(shù)存儲(chǔ)器的值就加1。因此當(dāng)使用定時(shí)器時(shí),就必須掌握時(shí)鐘周期和機(jī)器周期的關(guān)系。
時(shí)鐘周期 :晶振頻率的倒數(shù)。如果使用的是11.0592M的晶振,那么就是 1 / (11.0592x10^6) 秒   
注:1MHz = 10^6Hz
機(jī)器周期 :標(biāo)準(zhǔn)51下,機(jī)器周期 =12倍的時(shí)鐘周期。即:12 / (11.0592x10^6) 秒 。有的增強(qiáng)51單片機(jī),1個(gè)機(jī)器周期等于4倍的時(shí)鐘周期,還有的更短。
計(jì)數(shù)存儲(chǔ)寄存器THx&TLx
定時(shí)器和計(jì)數(shù)器工作,都依賴于 計(jì)數(shù)。計(jì)數(shù)則是由計(jì)數(shù)存儲(chǔ)器THxTLx2個(gè)8位寄存器完成的。
對(duì)于計(jì)數(shù)器,每來一個(gè)負(fù)跳變信號(hào)(信號(hào)從P3.4 或者P3.5引腳輸入),就加1,以此達(dá)到計(jì)數(shù)的目的。
對(duì)于定時(shí)器,每隔1個(gè)機(jī)器周期 加 1,假如(只是假如)一個(gè)機(jī)器周期為 1ms , 當(dāng)加到1000次時(shí),我們就認(rèn)為經(jīng)過了1s,這就是定時(shí)器定時(shí)依據(jù)。

T0和T1都擁有一對(duì)8bit計(jì)數(shù)存儲(chǔ)寄存器。他們的復(fù)位值都是0。
T0 對(duì)應(yīng):TH0 ,TL0
T1 對(duì)應(yīng) : TH1 , TL1

sfr TL0 = 0x8A; // TL中的L是LOW的意思,代表低位,同理H代表HIGH高位。2個(gè)8位組合起來就形成了一個(gè)16位的計(jì)數(shù)器。當(dāng)然也可以配置為僅僅當(dāng)做8bit計(jì)數(shù)存儲(chǔ)器用。
sfr TL1 = 0x8B;
sfr TH0 = 0x8C;
sfr TH1 = 0x8D;

當(dāng)計(jì)數(shù)器加滿后,再加1,就溢出了,溢出后自動(dòng)歸0。且溢出時(shí),溢出標(biāo)識(shí)位TFx 就會(huì)自動(dòng)變?yōu)?(T0的溢出標(biāo)志位TF0,T1的溢出標(biāo)志位TF1)。如果啟用了對(duì)應(yīng)的中斷,單片機(jī)會(huì)調(diào)用中斷處理函數(shù)。

若TH0 和 TL0 以 16位 模式工作,那它的計(jì)數(shù)范圍為   [0 , 65535 ]  ,  也就是累加 65536次發(fā)生溢出。 每累加一次是  12 / (11.0592x10^6) 秒。
那么從 0 累加到溢出 歷時(shí)  ≈ 0.071s = 71ms 。
可以延時(shí) 10的整數(shù)倍ms,這樣就避免了誤差,以便用倍數(shù)控制更長(zhǎng)的延時(shí)時(shí)間。所以,我么要給 TH0 和  TL0賦一個(gè)初始值,使他們的溢出周期(TH0,TL0從初始值到溢出所用的時(shí)間)減少到 10ms。
就像一個(gè)瓶子,開始裝了2/3,再來就只能裝1/3就溢出了。通過比例式計(jì)算:
12 / (11.0592x10^6) s       -----     1   次
10x 10-3   s                        ------          x  次         (求出 x = 9216次 ,計(jì)數(shù)9216次后溢出)
65536 - 9216 = 56320  =  二進(jìn)制( 11011100   00000000)
也就是  TH0 = 11011100 , TL0 = 00000000
工作模式寄存器TMOD
通過TMOD來配置T0和T1的工作模式。
注意,TMOD寄存器不可位尋址(例如sbit led = P0^0 就是P0寄存器位尋址的例子),因此對(duì)它的配置需要對(duì)這個(gè)8bit寄存器整體賦值。
注:51中有些特殊功能寄存器不支持位尋址。只有寄存器的地址值能夠被8整除的(即以數(shù)字0或者8結(jié)尾的地址,如0xA8, 0xD0),才能支持位尋址。不支持位尋址的,只能整體賦值。

小技巧:在對(duì)寄存器整體賦值時(shí),要注意只修改我們想修改的位而不影響其它無關(guān)位的值,避免影響了之前對(duì)這個(gè)寄存器的配置。
TMOD |= 0x01;   //僅僅修改TMOD的最低位,其他位保持不變。

C/T:計(jì)數(shù)器,定時(shí)器功能選擇位。 1為計(jì)數(shù)器模式, 0 為定時(shí)器模式。
M0和M1:


M1

M0
模式
0

1
THx和TLx  組成一個(gè)16位計(jì)數(shù)存儲(chǔ)器
1

0
8位重裝模式。THx的值不變,負(fù)責(zé)在每次溢出后初始化TLx,僅僅由TLx計(jì)數(shù)
1

1
禁用定時(shí)器 1,定時(shí)器 0 變成 2 個(gè) 8 位定時(shí)器。很少使用。
0

0
兼容 8048 單片機(jī)的 13 位定時(shí)器,THn的 8 位和 TLn 的 5 位組
成一個(gè) 13 位定時(shí)器。很少使用。

GATE:門控位。

解釋說明:
②處 C/T = 0 表示為定時(shí)器模式,觸發(fā)信號(hào)為①處的單片機(jī)內(nèi)部時(shí)鐘信號(hào)。(若②處CT = 1,則觸發(fā)信號(hào)為Tn腳)
③處表明,信號(hào)能觸發(fā)使加法計(jì)數(shù)器加1,還得受④處控制。不然時(shí)鐘信號(hào)是不能讓加法計(jì)數(shù)器累加的。 ④處這個(gè)是與門,所以TRx(TR0和TR1)必須為1,表明我們要開啟定時(shí)器。同時(shí)當(dāng),GATE為0,通過非門后為1,再通過或門,也是1,那么就讓③處控制起來了。若GATE為1,那么,定時(shí)器的啟動(dòng)停止受 TRx和 INTx 共同控制。 INTx腳為1且TRx為1才能啟動(dòng)定時(shí)器/計(jì)數(shù)器。
于是在一般情況下使用定時(shí)器,我們需要如下配置:
TRx    為  1
GATE  為 0
INTx   任意
控制寄存器TCON
控制寄存器就是用來控制定時(shí)器/計(jì)數(shù)器 啟動(dòng)和停止的,以及溢出標(biāo)志位的查詢和修改。TFx是計(jì)數(shù)存儲(chǔ)器溢出標(biāo)志位,只要一溢出,就馬上置為1。

TF1:定時(shí)器/計(jì)數(shù)器1的溢出標(biāo)志位。1表示計(jì)數(shù)存儲(chǔ)器溢出,0表示計(jì)數(shù)存儲(chǔ)器正常計(jì)數(shù)。
        清0方式:①通過代碼修改TF1為0
                       ②當(dāng)通過中斷機(jī)制來使用定時(shí)器/計(jì)數(shù)器1時(shí),進(jìn)入中斷處理函數(shù)后自動(dòng)歸0
TR1:定時(shí)器/計(jì)數(shù)器1的啟動(dòng)和停止位。1表示啟動(dòng),0表示停止。

TF0:定時(shí)器/計(jì)數(shù)器0的溢出標(biāo)志位。1表示計(jì)數(shù)存儲(chǔ)器溢出,0表示計(jì)數(shù)存儲(chǔ)器正常計(jì)數(shù)。
        清0方式:①通過代碼修改TF0為0
                       ②當(dāng)通過中斷機(jī)制來使用定時(shí)器/計(jì)數(shù)器0時(shí),進(jìn)入中斷處理函數(shù)后自動(dòng)歸0
TR0:定時(shí)器/計(jì)數(shù)器0的啟動(dòng)和停止位。1表示啟動(dòng),0表示停止。

低4位與外部中斷INT0和INT1有關(guān),與定時(shí)器/計(jì)數(shù)器無關(guān)。這里不做介紹。
查詢法使用T0作為定時(shí)器
程序1:P0_0連接驅(qū)動(dòng)的LED小燈,用T0作為16位定時(shí)器,完成間隔為1s 的 blink程序。
#include<REGX51.H>
#include"binary.h"
#include"int51.h"
/******************************/
void timer0_init(void);
void timer0_delay(uint16_t dly);
// P0_0驅(qū)動(dòng)LED小燈
#define LEDpin P0_0
void main(void)
{
    LEDpin = 0;
    timer0_init();
    TR0 = 1;
    for(;;)
    {
       LEDpin = 1;
       timer0_delay(1000);         //延時(shí)1000ms
       LEDpin = 0;
       timer0_delay(1000);        //延時(shí)1000ms
    }
}
/*************************
T0作為定時(shí)器的初始化
**************************/
void timer0_init(void)
{
    TMOD |= B0000_0001;        //定時(shí)器0,16位存儲(chǔ)計(jì)數(shù)器模式

    TH0 = B1101_1100;       //TH0 TL0 形成數(shù)是 56320  。這樣,一次溢出代表經(jīng)過10ms     
    TL0 = B0000_0000;
}
/**********************
參數(shù):
    dly,延時(shí)的毫秒數(shù),只能是10的整數(shù)倍
***********************/
void timer0_delay(uint16_t dly)
{
     while(dly)
    {   
        if(TF0){
             TF0 = 0;
             TH0 = B1101_1100;  
             TL0 = B0000_0000;
             dly -= 10;             //溢出一次代表10ms
        }
    }
}

程序2:通過T0定時(shí)器的8位重裝模式,使得P0_0輸出PWM信號(hào),LED為呼吸燈效果。
#include<REGX51.H>
#include"binary.h"
#include"int51.h"
/******************************/
void timer0_init(void);
void timer0_delay(uint16_t dly);
void pwm_duty(uint16_t d);
// P0_0驅(qū)動(dòng)LED小燈
#define LEDpin P0_0
void main(void)
{   
    uint16_t i;
    LEDpin = 0;
    timer0_init();
    TR0 = 1;
    for(;;)
    {
       for(i=0;i<=500;++i)
           pwm_duty(i);
       for(i=500;i>0;--i)
           pwm_duty(i);
    }
}
/*************************
T0作為定時(shí)器的初始化
**************************/
void timer0_init(void)
{
    TMOD |= B0000_0010;      //定時(shí)器0,8位重裝模式
    TH0 = 250;           //一次溢出代表經(jīng)過6.51us     
    TL0 = 250;
}
/**********************
一次溢出代表經(jīng)過6.51us
參數(shù) c乘以6.51us 就是這個(gè)函數(shù)延時(shí)的時(shí)間   
***********************/
void timer0_delay(uint16_t c)
{
    while(c)
    {   
        if(TF0){
             TF0 = 0;   //因?yàn)槭亲詣?dòng)重裝,因此不用給計(jì)數(shù)存儲(chǔ)器賦值。
             --c;            
        }
    }
}
/*************
參數(shù)d 的范圍是[0,500]。d / 500 即為 pwm輸出的占空比,控制LED燈的暗亮程度
**************/
void pwm_duty(uint16_t d)
{
    LEDpin = 1;
    timer0_delay(d);
    LEDpin = 0;
    timer0_delay(500-d);
}

注:如果需要精確的延時(shí),使用8位自動(dòng)重裝模式最好,因?yàn)橛布b值(賦值給TH0)比軟件裝值快。但8位自動(dòng)重裝模式不宜做單次長(zhǎng)時(shí)間延遲。畢竟溢出周期短。長(zhǎng)時(shí)間延遲需要多個(gè)溢出周期,也挺消耗資源的。

盡量讓溢出周期 越長(zhǎng)越好。溢出周期為10ms 的優(yōu)于 1ms 的。因?yàn)椋谕瑯拥难訒r(shí)時(shí)間下,如100ms,溢出周期為10ms 的 只需要溢出10次,為TH0 和 TL0重新賦值10次,而溢出周期為1ms的要溢出100次,為TH0 和 TL0重新賦值100次。減少溢出次數(shù)和賦值次數(shù),可以減輕單片機(jī)的負(fù)擔(dān),提高定時(shí)的準(zhǔn)確性。

評(píng)分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏2 分享淘帖 頂1 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:800952 發(fā)表于 2020-9-10 16:04 來自手機(jī) | 只看該作者
初用單片機(jī),感覺定時(shí)跟書上說的差遠(yuǎn)了,12M晶振t0預(yù)置1000一次等于1ms,實(shí)際上是450差不多
回復(fù)

使用道具 舉報(bào)

板凳
ID:817950 發(fā)表于 2020-9-11 16:09 | 只看該作者
cadplus 發(fā)表于 2020-9-10 16:04
初用單片機(jī),感覺定時(shí)跟書上說的差遠(yuǎn)了,12M晶振t0預(yù)置1000一次等于1ms,實(shí)際上是450差不多

哪里弄錯(cuò)了吧,定時(shí)器很準(zhǔn)的
回復(fù)

使用道具 舉報(bào)

地板
ID:817950 發(fā)表于 2020-9-11 16:13 | 只看該作者
不是很贊成用定時(shí)器軟件生成PWM,基礎(chǔ)51外設(shè)資源少?zèng)]辦法,STC增強(qiáng)51常用外設(shè)都有。
回復(fù)

使用道具 舉報(bào)

5#
ID:800952 發(fā)表于 2020-9-11 16:59 | 只看該作者
luogu 發(fā)表于 2020-9-11 16:09
哪里弄錯(cuò)了吧,定時(shí)器很準(zhǔn)的

秒表實(shí)測(cè)啊
回復(fù)

使用道具 舉報(bào)

6#
ID:845223 發(fā)表于 2020-11-27 09:18 | 只看該作者
如果要計(jì)時(shí)器里沒到溢出,想要把計(jì)時(shí)器里頭的值和溢出的值相加算出來怎么做
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表