在上一篇文章已經介紹定時器的用法,而且簡單介紹工作方式1。工作方式1使用場景較豐富,在大部分用到定是的場景皆可使用。其余剩下的3種工作方式也有很多使用場景,,下面來一一介紹。下文以定時器0為準,晶振以11.0592為準。這里貼一張圖,來再回顧定時器的4種工作方式。
4種工作方式
工作方式0
工作方式0,13位定時器/計數器。下面以定時器0為例講解。
定時器方式0邏輯結構
上圖可以知道定時器工作方式0的邏輯結構,與工作方式1相差不遠,只是方式1是兩個8位計數器,而方式0是一個8位,一個低5位組成的13位計數器。編程控制兩個非常像。方式0的計數器最大值為2的13次方=8192,計數一次時間最大值為8192*1.09=8929us(以晶振為11.0592MHZ為例)。下面示范講解使用,比如說設置一個10ms的間距,哎哦,最大間距為9ms,設置不了,那就以5ms為例
示例
N=5*1000/1.09=4587,
TL0(低五位計數器)最大值為2的5次方=32,所以TH0(高八位)=4587/32=143,十六進制為0X8F。
TL0=4587%32=11,十六進制為0X0B。
所以 TH0=0X8F; //注意高低位,H=high, 高?
TL0=0X0B; //L=low, 低
下面寫一個簡單的完整程序:`
#include??//頭文件
sbit?led=P1^1;???????//位定義
unsigned?char?count;????//定義一個無符號型變量count,記錄中斷次數
main?()???????//主函數
{
????TMOD=0X00;???//定時器0,工作方式0
????TH0=0X8F;????//賦初值,定時5ms
????TL0=0X0B;
????EA=1;???????//打開總中斷
????ET0=1;??????//打開定時器0中斷
????TR0=1;??????//?啟動定時器0
}
void?timer_T0()?interrupt?1?????//中斷函數,1表示中斷源為定時器0
{
????TMOD=0X00;??//重新賦值
????TH0=0X8F;
????count++;??????//中斷一次加1
????if(count==20)????//count==20時表示100ms到
????{
????????count=0;??????//清0
????????led=~led;?????//狀態取反
????}???
}
方式0的使用至此已經講解完畢,方式0與方式1的使用差不多,可以對照來看,兩者使用場景也差不多,能使用方式1的地方也可以使用方式0.
工作方式2
工作方式2,8位初值自動重載的8位定時器/計數器
定時器方式2邏輯結構
在這里說明一下,定時器是比簡單的延時函數實用,精確。但定時器也是有誤差的,在賦值時,采用的是約等數。人工重載時時間上也會造成誤差。種種原因,時間一久,誤差累積就會很大,在一些要求精確度功能時,比方說串口通信設置波特率,就會出錯。所以就出現了方式2,計數器自動重載。
來看一下方式2的邏輯圖,右邊部分的圖不用說了,重點來看左邊。TH0被作為常數緩沖器,當TL0計數溢出,在溢出標志TF0置1的同時,自動將TH0的常數重新裝入TL0中,時TL0從初值開始重新計數。
方式2,8位計數器,最大值為2的8次方=256,計數時間最大值為2561.09=279us,以100ms為間距時, N=1001000/279=358 .同樣來個范例:
范例
#include??//頭文件
sbit?led=P1^1;???????//位定義
unsigned?int?count;????//定義一個無符號型變量count,記錄中斷次數
main?()???????//主函數
{
????TMOD=0X02;???//定時器0,工作方式2
????TH0=0X00;????//賦初值,定時279us
????TL0=0X00;
????EA=1;???????//打開總中斷
????ET0=1;??????//打開定時器0中斷
????TR0=1;??????//?啟動定時器0
}
void?timer_T0()?interrupt?1?????//中斷函數,1表示中斷源為定時器0
{
???????????????????//不用賦初值,計數器自動重載
????count++;??????//中斷一次加1
????if(count==358)???//count==358時表示100ms到
????{
????????count=0;??????//清0
????????led=~led;?????//狀態取反
????}???
}
方式2的講解告一段落,方式2特別適合用于做較精確的脈沖信號發射器。
工作方式3
工作方式3,僅使用于T0,分成兩個8位計數器,T1停止計數。
工作方式3邏輯結構
上圖結構簡單,就不多講解。就是定時器0的計數器分成兩個,TH0作用于TF1,TR1.
TL0作用于TF0,TR0.那就是說使用工作方式3時,不使用T1定時器,或使用時不使用中斷,這個情況就是定時器1使用工作方式2,不然會出錯,因為TF1,TR1已經讓定時器0占用。計算已經大同小異,把式子就算了。TH0定時5ms,TL0定時10ms。
N=51000/(2561.09)=18 //TH0
N=101000/(2561.09)= 36 //THL0
示例
#include??//頭文件
sbit?led_1=P1^1;???????//位定義
sbit?led_2=P1^2;
unsigned?char?count;????//定義一個無符號型變量count,記錄TH0中斷次數
unsigned?char?num;????????//定義一個無符號型變量num,記錄TL0中斷次數
main?()???????//主函數
{
????TMOD=0X03;???//定時器0,工作方式2
????TH0=0X00;????//賦初值,定時279us
????TL0=0X00;????//賦初值,定時279us
????EA=1;???????//打開總中斷
????ET0=1;??????//打開定時器0中斷
????ET1=1;??????//打開定時器1中斷
????TR0=1;??????//?啟動定時器0的低八位計數器
????TR1=1;??????//?啟動定時器0的高八位計數器
}
void?timer_TH0()?interrupt?1?????//中斷函數,1表示中斷源為定時器0
{
????TH0=0X00;???????//重新賦值
????count++;??????//中斷一次加1
????if(count==18)????//count==18時表示5ms到
????{
????????count=0;??????//清0
????????led_1=~led_1;?????//狀態取反
????}???
}
void?timer_THL0()?interrupt?1?????//中斷函數,1表示中斷源為定時器0
{
????TH0=0X00;????//重新賦值???????
????num++;????//中斷一次加1
????if(num==36)??//num==36時表示10ms到
????{
????????num=0;????//清0
????????led_2=~led_2;?????//狀態取反
????}???
}
方式3的使用也講完了。下面介紹兩個定時器嵌套使用。
定時器綜合
兩個定時器一起使用也沒有什么困難,很簡單的,只要一個的會用,兩個也不成問題,小小意思。這和方式3有點像。看看下面例程就回了。
#include??//頭文件
sbit?led_1=P1^1;???????//位定義
sbit?led_2=P1^2;
unsigned?char?count;????//定義一個無符號型變量count,記錄TH0中斷次數
unsigned?char?num;????????//定義一個無符號型變量num,記錄TL0中斷次數
main?()???????//主函數
{
????TMOD=0X11;???//?0001?0001?定時器0,工作方式1?定時器1,?工作方式1????
????TH0=(65535-50000)/256;???//賦初值,定時50ms
????TL0=(65535-50000)%256;???
????TH1=(65535-10000)/256;???//賦初值,定時10ms
????TL1=(65535-10000)%256;
????EA=1;???????//打開總中斷
????ET0=1;??????//打開定時器0中斷
????ET1=1;??????//打開定時器1中斷
????TR0=1;??????//?啟動定時器0
????TR1=1;??????//?啟動定時器1
}
void?timer_T0()?interrupt?1?????//中斷函數,1表示中斷源為定時器0
{
????TH0=(65535-50000)/256;???//重新賦值
????TL0=(65535-50000)%256;??????
????count++;??????//中斷一次加1
????if(count==20)????//count==20時表示1s到
????{
????????count=0;??????//清0
????????led_1=~led_1;?????//狀態取反
????}???
}
void?timer_T1()?interrupt?3?????//中斷函數,3表示中斷源為定時器1
{
????TH1=(65535-10000)/256;???//重新賦值
????TL1=(65535-10000)%256;????????????
????num++;????//中斷一次加1
????if(num==10)??//num==10時表示100ms到
????{
????????num=0;????//清0
????????led_2=~led_2;?????//狀態取反
????}???
}
結束語
定時器的講解已經結束,大家對定時器的認知肯定也提升不少。定時器非常重要,在大部分的程序中都會運用到,這個要求會用。上面的講解已經非常直白了,不懂的多看幾遍,每次都會有新的體悟。定時器就一計數器,到點了就中斷,卡準中斷時間,不就可知道時間,定時器就這樣子,不難。
評論