TMOD:定時器/計數器模式控制寄存器TMOD是一個逐位定義的8位寄存器,但只能使用字節尋址,其字節地址為89H。
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
GATE |
C/T |
M1 |
M0 |
GATE |
C/T |
M1 |
M0 |
D0~D3為T0定時/計數器的設置,D4~D7為T1定時/計數器的設置 。
GATE :為門控位,GATE=0時,只要在編寫程序時,使TCON中的TRO或TR1為1,就可以啟動定時器/計數器工作。
GATE=1時,不僅要在編寫程序時,使TCON中的TRO或TR1為1,且需要外部引腳也為高電平,才能工作。
C/T :定時/計數模式切換,C/T=0時為定時模式,C/T=1時為計數模式。
M1,M0:用來選擇定時計/計數器的工作方式,一般使用都是采用16位的計時計數器。
M1 |
M0 |
工作模式 |
說明 |
0 |
0 |
0 |
13位計時計數器 (8192) |
0 |
1 |
1 |
16位計時計數器 (65536) |
1 |
0 |
2 |
8位計時計數器,可自動重新載入計數值 (256) |
1 |
1 |
3 |
當成兩組獨立的8位計時器(256,T0和T1不能同時用) |
TCON:控制寄存器,作用是控制定時器的啟、停,標志定時器溢出和中斷情況。
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
TF1 |
TR1 |
TF0 |
TR0 |
IE1 |
IT1 |
IE0 |
IT0 |
TF1 :TF1=1表示T1有中斷產生。(Timer Flag,定時器標志位)
TR1 :TR1=1表示T1開始運行。(單片機中T0引腳,需要高低電平的驅動)
TF0 :TF0=1表示T0有中斷產生。
TR0 :TR0=1表示T0開始運行。(單片機中T1引腳,需要高低電平的驅動)
IE1 :IE1=1表示INT1有中斷產生。
IT1 :IT1=1表示INT1為下降沿觸發,IT1=0表示INT1為低電平觸發。
IE0 :IE0=1表示INT0有中斷產生。
IT0 :IT0=1表示INT0為下降沿(負跳變)觸發,IT0=0表示INT0為低電平觸發。
中斷允許寄存器 IE (A8H)
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
EA |
— |
ET2 |
ES |
ET1 |
EX1 |
ET0 |
EX0 |
EA :整體中斷允許位;EA=1允許中斷。
ET2 :T2中斷允許位;ET2=1允許中斷(S52才有)。
ES :串行中斷允許位;ES=1允許中斷。
ET1 :T1中斷允許位;ET1=1允許中斷。
EX1 :INT1中斷允許位;EX1=1允許中斷。
ET0 :T0中斷允許位;ET0=1允許中斷。
EX0 :INT0中斷允許位;EX0=1允許中斷。
在程序中,通過設訂兩個8位寄存器中TH與TL的值,來決定定時值和計數值。TH與TL的計算過程如下:
假設定時器的時間常數為X,定時器的位數為N
定時時間T=(2的N次方-X)12/單片機晶振頻率 (例如11.0592MHZ的振盪器頻率F=1/11.0592)
N為定時器的工作方式(關於定時/計數器的4中工作方式,以下會有具體介紹):
方式0時,N=13(此為TH為8位,TL為5位)
方式1時,N=16(此為TH為8位,TL為8位)
方式2時,N=8(此為TH為8位,TL為0位)
方式3時,N=8(此為TH為8位,TL為8位,只適用於T0,且T0被分成兩個獨立的8位計數器TH與TL)
根據定時時間和工作方式,通過公式:定時時間T=(2的N次方-X)12/單片機晶振頻率,計算出時間常數X
把X轉換成二進制數,高8位送給TH1,低8位送給TL1,就可以啟動定時器開始定時了。
定時器的3種工作方式圖解:
工作方式0:
工作方式1:
工作方式2:
工作方式3:
總結定時器的操作步驟如下:
1.選擇工作方式(設置M0,M1的值)
2.選擇控制方式GATE(為0是只要軟件設定好參數即可,為1則需要軟件設定參數,且定時器/計數器的中斷引腳需要為高電平)
3.確定定時器的工作模式,是定時模式還是計數模式 C/T.
4.給定時器設初值(設置THX與TLX)
5.開啟定時器中斷(設置ET0或ET1)
6.開啟總中斷(設置EA的值)
7.定時器/計數器的選擇T0/T1(設置TR1或TR0的值)
例:設置一個LED燈每500ms的評率閃爍
#include<reg52.h> sbit led = P1^0; int i = 0; void timer1_init() { TMOD = 0x10; //定時器0選擇工作方式1 TH1 = 0x4C; //設置初始值,定時50ms TL1 = 0x00; EA = 1; //打開總中斷 ET1 = 1; //打開定時器0中斷 TR1 = 1; //啟動定時器0 } void main() { led = 1; timer1_init();//定時器1的初始化 while(1) { if(i==10) { led = ~led; i = 0; //注意i需要零 } } } void timer1() interrupt 3 { TH1 = 0x4C; //設置初始值,定時50ms TL1 = 0x00; i++; }
c51單片機中斷程序中的interrupt1,2,3是由什么決定的?
interruput X 語句 X是中斷標號 計算公式是 :(地址-3)/8=中斷標號,其中“地址”*/
指的是 中斷服務程序 的入口地址,比如:
外部中斷0,入口地址為0003H,對應的中斷標號為0
外部中斷1,入口地址為0013H(十進制為19),對應中斷標號為2
定時器0中斷,入口地址為000BH(十進制為11),對應中斷標號為1
定時器1中斷,入口地址為001BH(十進制為27),對應標號為3
串口中斷,入口地址為0023H(十進制為35),對應中斷標號4
入口地址在數據手冊里有
https://zhidao.baidu.com/question/365087067.html
由TL0的低5位(高3位未用)和TH0的8位組成。TL0的低5位溢出時向TH0進位,TH0溢出時,置位TCON中的TF0標志,向CPU發出中斷請求。由TL0的低5位(高3位未用)和TH0的8位組成。TL0的低5位出時向TH0進位,TH0溢出時,置位TCON中的TF0標志,向CPU發出中斷請求。,由TL0的低5位(高3位未用)和TH0的8位組成。TL0的低5位溢出時向TH0進位,TH0溢出時,置位TCON中的TF0
http://www.21ic.com/jichuzhishi/mcu/timer/2018-04-23/758372.html
6.STC89C52RC單片機定時器示例代碼2:
問:在中斷函數里為什么要重新賦初值呢?TH0 = XX,TL0 =XX?
因為進入中斷,其值減為0,如果不重裝初值,下次計數值就是65535,而不TH0 << 8 | TL0 ,比如上圖中的922.
https://zhidao.baidu.com/question/178452295.html
----------------------------------------------------
TH0 ,TL0怎么算:
比如計時10毫秒,10ms= 10000ms / 1.085 (機器周期)= 9216 次,意思就是當機器運行9216次 就為10ms
65535 (16位最大計數值) - 9216 = 56319 ,換成 16進制=0xDBFF ,分別賦值給TH0=0xDB, TL0 =0xFF
----------------------------------------------------
機器周期怎么算?
51單片機而言,一個機器周期等於12個晶振的周期。公式就是:12/fsoc
12/11.0592 =1.085(約等於) , 11.0592是晶振頻率
----------------------------------------------------
波特率=(2SMOD / 32) * T1溢出率
溢出速率=(計數速率)/(256-TH1初值)
溢出速率=fosc/[12*(256-TH1初值)]
11.0592M
9600=(2÷32)×((11.0592M/12)/(256-TH1))
9600 = 0.0625 * (11059200/ 12)/(256-TH1))
9600 = 57600/(256-TH1))
(256-TH1)) = 57600/9600
(256-TH1)) = 6
TH1 = 256- 6
TH1=250
----------------------------------------------------
以下轉自:https://blog.csdn.net/lile777/article/details/45719283?utm_source=blogxgwz3
當SMOD=1時,K=2,波特率加倍,公式為: 波特率=K×11059200/32×12×(256-TH1) 所以,TH1=0xfa=256-(2×11059200/384×波特率) 其中波特率為9600 這時,及時令TH1=0xff,所得波特率最大只能為57600,也就是說,這樣無法得到115200的波特率。。。 這樣就只有采用其他方法了: 1、換晶振,用22.1184M晶振,在TH1=0xff時,剛好可以產生115200波特率。 2、采用6個時鍾周期的單片機(換單片機啊。。。) 3、增強型51單片機有定時器2!(幸好偶用的是增強型。。。) 就用第三種方法啦!這時的波特率公式如下: 波特率=11059200 / { 32×[65536-(RCAP2H,RCAP2L)] } 其中的RCAP2H,RCAP2L為自動重裝值,由上式得: RCAP2H,RCAP2L=65536-11059200 / (32×波特率) 這樣得波特率為115200時,RCAP2H,RCAP2L=0xff,0xfd,初始化程序如下: void init_com( void ) { SCON=0x50; //串口工作方式1,8位UART,波特率可變 TH2=0xFF; TL2=0xFD; //波特率:115200 晶振=11.0592MHz RCAP2H=0xFF; RCAP2L=0xFD; //16位自動再裝入值 /*****************/ TCLK=1; RCLK=1; C_T2=0; EXEN2=0; //波特率發生器工作方式 /*****************/ TR2=1 ; //定時器2開始 } OK! 這樣就實現用51單片機+11.0592的晶振,產生115200的波特率了