目錄
一,定時器介紹
定時器介紹:
51單片機的定時器屬於單片機的內部資源,其電路的連接和運轉均在單片機內部完成
定時器作用:
(1)用於計時系統,可實現軟件計時,或者使程序每隔一固定時間完成一項操作
為什么有Delay函數了還要用什么定時器呢?
(2)Delay函數在使用時,CPU是被占用的,不能進行別的操作。而定時器是和主程序同時進行的,可以替代長時間的Delay,提高CPU的運行效率和處理速度
二,STC89C52定時器資源
定時器個數:
3個(T0、T1、T2),T0和T1與傳統的51單片機兼容,T2是此型號單片機增加的資源
注意:定時器的資源和單片機的型號是關聯在一起的,不同的型號可能會有不同的定時器個數和操作方式,但一般來說,T0和T1的操作方式是所有51單片機所共有的
三,定時器框圖
看明白這個流程圖哦
四,定時器工作模式
這里涉及到或門和與門的相關知識:
以與門為例介紹一下簡單的邏輯電路:
2個引腳都置為高電平的時候:
二極管與電阻沒有壓降,所以輸出是5V。為高電平
如果2個引腳一個為高電平,一個為低電平的時候:
這個電路里面有電流流過,二極管與電阻有壓降,所以輸出的電壓為0.7V,為低電平。
定時器的工作模式:
這里注意SYSclk的分頻我們選擇的是12分頻,然后6分頻是要在燒寫軟件里面手動確認,這是因為51單片機沒有AUXR(輔助寄存器),所以沒法設置分頻。,如下圖所示:
還有關於定時器誤差的計算:
這里的誤差主要產生於系統頻率與分頻數的聯系不大(倍數關系之類的),而且定時長度比較小,所以,這里計數1,相當於在12MHz計數:1x(12/fosc) ,fosc=11.0592MHz,所以得實際計時時間是:1.08506s,誤差計算:(1.08506-1)/ 1=0.0851
五,中斷系統及其流程
實際上單片機的優先級配置比較復雜這里我們只說兩種優先級,方便理解(一般有四種優先級可以配置)
六,STC89C52中斷資源
中斷源個數:8個(外部中斷0、定時器0中斷、外部中斷1、定時器1中斷、串口中斷、定時器2中斷、外部中斷2、外部中斷3)
中斷優先級個數:4個
中斷號:
七,定時器與中斷系統
定時器已經在之前的工作原理里面介紹了,下面主要是要介紹一下Interrupt是個什么東東?
傳統的STC89C52的中斷系統有4個優先級配置起來就比較復雜(主要是我們就配置了一個定時器中斷,不是他優先還是誰優先,嘿嘿,所以我們不必搞得那么復雜)
這我們這我們之前在中斷系統里面也聊過,但是還是給大家上圖片看看:
這是傳統的STC89C52的中斷系統結構圖
為了方便講解,這里使用的中斷系統圖是傳統51單片機的中斷系統結構圖,都是一樣的哈,只不過說傳統51單片機只有2個優先級,看着比較明白,方便理解:
在這里我們配置的是定時器1,看T0哪一行就好了
八,相關寄存器的認識與配置
配置一句兩句說不清楚,而且不是很權威,所以我引用手冊上面的介紹
首先是定時器模式的配置(TMOD)
這里對幾種工作模式進行簡單的介紹:
一,13位定時/計數器方式
計數值為N和初值X關系: X=8192-N /(12/fosc)
上次計數完,計數器值為0,要重復計數需重置初值。
(即在中斷函數中將TH0,TL0,TH1,TL1置初值)
二,16位定時/計數器方式
計數值為N和初值X關系: X=65536-N/(12/fosc) { X=65536-N*(fosc/12) }
上次計數完,計數器值為0,要重復計數需重置初值。
如果上面的公式fosc與12不知道誰在分子誰在分母,那么其實可以假設fosc為11.0592Mhz,它比12Mhz計數慢(每個周期更大)可以以12Mhz為基准的話,在以11.0592Mhz為系統時鍾的時候,相同的時間,11.0592Mhz計數少。所以就需要乘以一個小於1的數,即(fosc/12)
三,8位自動重置定時/計數器
四,8位定時/計數器(只有配置T0才能使用)
計數值為N和初值X關系: X=256-N /(12/fosc)
上次計數完,計數器自動重置初值。不需用戶重置。
在一,二,三,四中fosc為晶振頻率,51單片機一般為12MHz或者11.0592MHz
我們在使用定時器的時候一般使用的是模式二,16位定時/計數器方式
這里來詳細講講12分頻的過程,12MHz的系統時鍾經過12分頻以后,其頻率變為1MHz,自然知道他的周期為1us,即在一個周期內計數為1。 所以自然:X=65536-N。而如果系統時鍾是11.0592MHz那么,12分頻后的的頻率為(11.0592/12.0000)MHz,周期為(12.0000/11.0592)us,所以有等比式:(12.0000/11.0592)us /(xus)=(1)/(?),其中x為想要定時的時長(單位us),(?)則是需要計數的值。
其次是中斷系統的配置:
這里的IT1與IT0的配置中,對於低電平觸發與低電平觸發可能會有些疑問:
低電平觸發:
低電平觸發中斷顧名思義,就是檢測到引腳為低電平就觸發,從而進入中斷函數中處理這個中斷,並且在高或低電平保持的時間內持續觸發,假設是低電平觸發,只要引腳為低電平時間內中斷一直有效,那么就會一直進入中斷,直到電平變化為高電平
低電平觸發:
數字電路中,數字電平從高電平(數字“1”)變為低電平(數字“0”)的那一瞬間叫作下降沿。 下降沿觸發是當信號有下降沿時的開關動作,當電位由高變低而觸發輸出變化的就叫下降沿觸發。也就是當測到的信號電位是從高到低也就是下降時就觸發,叫做下降沿觸發。
那么我們可以很好的理解兩種觸發:
上升沿觸發 就是當電壓從低變高時觸發中斷
下降沿觸發 就是當電壓從高變低時觸發中斷
當然,上升沿與下降沿檢測的是電平變化的一瞬間,就會產生中斷,這個時間是us級別的,但是如果中斷引腳檢測到一直保持低/高電平,則無法產生下次中斷,也就是中斷只會觸發一次,只有在下次電平發生變化時才會重新觸發中斷
對照着中斷圖一起看思路會比較清晰
如果實在看不明白,全部置1也是沒有問題的(下面的代碼優先級PT0置的是0表示默認優先級,我們置1也是沒有問題的)
九,定時器時鍾代碼演示
下面的是定時器的寄存器的相關配置:
系統時鍾為12MHz的情況,即fosc=12.00MHz,計數值為N和初值X關系: X=65536-N/(12/fosc)公式就變成了X=65536-N
下面是中斷函數的內容,包括:
1,重新設置定時器的TH0與TL0的初值,
2,一個計次計時的模塊
3,最后是中斷函數的主體部分也就是時,分,秒的進制關系(一般根據需求替換這一部分)
源代碼如下:
#include <REGX52.H>
/**
* @brief 定時器0初始化,1毫秒@12.000MHz
* @param 無
* @retval 無
*/
void Timer0Init(void)
{
TMOD &= 0xF0; //設置定時器模式
TMOD |= 0x01; //設置定時器模式
TL0 = 0x18; //設置定時初值
TH0 = 0xFC; //設置定時初值
TF0 = 0; //清除TF0標志
TR0 = 1; //定時器0開始計時
ET0=1;
EA=1;
PT0=0;
}
/*定時器中斷函數模板
void Timer0_Routine() interrupt 1
{
static unsigned int T0Count;
TL0 = 0x18; //設置定時初值
TH0 = 0xFC; //設置定時初值
T0Count++;
if(T0Count>=1000)//在中斷函數中重新進行計次,這里是每1s進行一次相關操作,注意寫中斷函數時一定要和定時器配套寫(即定時器的聲明/初始化)
{
T0Count=0;
}
}
*/
void Timer0_Routine() interrupt 1
//中斷函數中不可以加LCD這樣的耗時過長的語句,顯示的工作交由main(),否則會有L15報錯
{
static unsigned int T0Count;
TL0 = 0x18; //設置定時初值
TH0 = 0xFC; //設置定時初值
T0Count++;
if(T0Count>=1000)//每1s進行一次相關操作
{
T0Count=0;
miao++;
if(miao>=60){
miao=0,fen++;
}
if(fen>=60){
shi++;fen=0;miao=0;
if(shi>=24)shi=0;
}
}
}
最后,小白一個,有什么不足的地方還請各位大佬指出,謝謝大家。