關(guān)于單片機(jī)的計(jì)時(shí)器與中斷系統(tǒng)
下面進(jìn)入正題:
1、計(jì)時(shí)器
下面先看一個(gè)圖:其中可以清楚的看到,TH0和TL0是兩個(gè)8位寄存器,這兩個(gè)寄存器組合成T0加1計(jì)數(shù)器,所以計(jì)數(shù)器為16位計(jì)數(shù)器。同理,TL1和TH1組合成了T1加1計(jì)數(shù)器。
再看TMOD寄存器,它是一個(gè)8位寄存器,名字叫做工作方式寄存器,顯然它是控制工作方式的,看電路圖上看它有兩條灰色的線條延伸到T0和T1,即它可控制T0和T1的工作方式,也可以清楚的看到,其低四位控制T0的工作方式,高4位控制T1的工作方式。
那么什么叫做工作方式呢?工作方式就是指開(kāi)或者關(guān),芯片是工作在定時(shí)模式還是計(jì)數(shù)模式,和寄存器的使用情況??傮w如下:
GATE是門(mén)控位,GATE=0時(shí),TCON中TR0/TR1=1時(shí)可啟動(dòng)。
GATE=1時(shí),TCON中TR0/TR1=1,且外部中斷引腳為高電平時(shí)可啟動(dòng)。
C/T=0:定時(shí)模式。
M1M0組合使用,其值如下:
00 | 13位定時(shí)/計(jì)數(shù)器 |
01 | 16位定時(shí)/計(jì)數(shù)器 |
10 | 8位自動(dòng)重裝定時(shí)/計(jì)數(shù)器 |
11 | T0分成兩個(gè)定時(shí)/計(jì)數(shù)器,T1停止 |
再看TCON寄存器,它與TMOD一樣,叫做控制寄存器,它是用于控制外部中斷啟動(dòng)、申請(qǐng)的一系列工作的。定時(shí)器/計(jì)數(shù)器的工作要依賴(lài)于溢出中斷,在中斷處理中處理相關(guān)事件T0或者T1寄存器溢出時(shí)會(huì)申請(qǐng)中斷,然后再處理。比如所以如果想要使用T0計(jì)數(shù)100,那么就用16位寄存器的溢出值減去初始值,既是計(jì)數(shù)值,那么就是65536-100=65436(65536-65436=100),所以T0要首先置初始值65436。這里先介紹TCON的高4位。
TF1:T1溢出中斷請(qǐng)求標(biāo)志位,T1溢出時(shí)TF1為1,相應(yīng)中斷后自動(dòng)清0,也可使用軟件控制。
TR1:T1運(yùn)行控制位,TR1為1時(shí),T1工作,TR1為0時(shí),T1停止工作。
TF0:T0溢出中斷請(qǐng)求標(biāo)志位。同理TF1。
TR0:T0運(yùn)行控制位,同理TR1。
M1M0控制的四種工作方式如下:
00 | 13位計(jì)數(shù),使用了TL0的低5位和TH0的8位組成,TH0溢出置TF0中斷。 |
01 | 16位計(jì)數(shù),使用T0。同00。 |
10 | 自動(dòng)重裝初值的8位計(jì)數(shù)方式。 |
11 | T1停止,TH0和TL0分開(kāi)計(jì)數(shù)。 |
計(jì)時(shí)器使用步驟:
·對(duì)TMOD賦值,確定T1、T0的工作方式。
·計(jì)算初值,并將其寫(xiě)入T0或者T1。
·對(duì)IE(IE后面再介紹)賦值,開(kāi)放中斷。
·使TR0或者TR1置位,啟動(dòng)計(jì)數(shù)。
二、中斷
中斷估計(jì)都知道是干啥的,這些就不啰嗦了,這里先上一幅圖:看這圖估計(jì)都沒(méi)心情,下面剖開(kāi)來(lái)看:
其他的先不看,先看這點(diǎn)圖,這是一個(gè)中斷源,其中IT0是選擇中斷的方式,IT0=1時(shí)為選擇下降沿有效,IT0=0時(shí)為低電平有效(有一個(gè)非門(mén))。當(dāng)中斷觸發(fā)時(shí)就將IE0置1,此時(shí),向CPU申請(qǐng)中斷。那么,IT0和IE0是在什么地方呢?
還記得上面講的TCON嗎?現(xiàn)在把低四位也加進(jìn)去:
TF1 | TR1 | TF0 | TR0 | IE1 | IT1 | IE0 | IT0 |
參照1:INT0。
3、
TF0中斷,上面已經(jīng)介紹。
4、
TF1中斷,上面已經(jīng)介紹。
5、(RI或TI中斷)
串行口中斷請(qǐng)求標(biāo)志,當(dāng)串行口接收完一幀串行數(shù)據(jù)時(shí),置位RI或當(dāng)串行口發(fā)送完一幀串行數(shù)據(jù)時(shí)置位TI,向CPU申請(qǐng)中斷。
TCON中斷
其中,TCON中的中斷標(biāo)志有如下幾個(gè):TF1 | TR1 | TF0 | TR0 | IE1 | IT1 | IE0 | IT0 |
·IT0=0為下降沿有效
·IT0=1為負(fù)邊沿觸發(fā)
IE0:外部中斷0中斷請(qǐng)求標(biāo)志位。
IT1:外部中斷1觸發(fā)方式控制位(同IT0)。
IE1:外部中斷1中斷請(qǐng)求標(biāo)志位。
TF0:T0溢出中斷。
TF1:T1溢出中斷。
SCON中斷
SCON中的中斷如下:TI | RI |
TI:串行口發(fā)送中斷標(biāo)志位。當(dāng)CPU將一個(gè)發(fā)送數(shù)據(jù)寫(xiě)入串行口發(fā)送緩沖器時(shí),就啟動(dòng)了發(fā)送過(guò)程,每發(fā)送完一個(gè)串行幀,由硬件置位TI,CPU響應(yīng)中斷時(shí),不能自動(dòng)清除TI,TI必須由軟件清除。
下面再看上圖的下一部分:
這部分叫做中斷允許控制,當(dāng)一個(gè)中斷發(fā)生時(shí),必須由中斷允許控制來(lái)檢測(cè)是否允許,如果允許則轉(zhuǎn)入中斷處理,否則不處理。
先看右邊的EA,這個(gè)是總的中斷允許控制位,CPU想要處理中斷,必須開(kāi)此中斷允許。
再看左邊:
其中各個(gè)中斷允許控制如下:
·EX0:外部中斷0允許位
·ET0:T0中斷允許位
·EX1:外部中斷1允許位
·ET1:T1中斷允許位
·ES:串行口中斷允許位
其中,這幾個(gè)位都是由中斷允許寄存器IE控制的,IE寄存器具體如下:
EA | ES | ET1 | EX1 | ET0 | EX0 |
很明了,中斷響應(yīng)條件如下:
1、有中斷請(qǐng)求
2、中斷源中斷允許位為1
3、CPU開(kāi)中斷(EA=1)
其中,8051有兩個(gè)中斷優(yōu)先級(jí),可以實(shí)現(xiàn)二級(jí)中斷嵌套。每個(gè)中斷源的中斷優(yōu)先級(jí)都是由中斷優(yōu)先級(jí)寄存器IP中的相應(yīng)位的狀態(tài)來(lái)規(guī)定的。
IP寄存器如下:
PT2 | PS | PT1 | PX1 | PT0 | PX0 |
可以按照上圖以此類(lèi)推。
(這里,PT2是80C52的中斷,不介紹)
優(yōu)先級(jí)高的中斷可以打斷優(yōu)先級(jí)低的中斷而先執(zhí)行,實(shí)現(xiàn)中斷嵌套。那么同一優(yōu)先級(jí)之間不能打斷,如果多個(gè)同優(yōu)先級(jí)中斷同時(shí)申請(qǐng),則按照自然優(yōu)先級(jí)順序執(zhí)行中斷,自然優(yōu)先級(jí)如下:
中斷源 | 中斷標(biāo)志 | 中斷服務(wù)程序入口 | 優(yōu)先級(jí)順序 |
外部中斷0 | IE0 | 0003H | 高 |
T0 | TF0 | 000BH | ↓ |
外部中斷1 | IE1 | 0013H | ↓ |
T1 | TF1 | 001BH | ↓ |
串行口中斷 | RI或者TI | 0023H | 低 |
中斷使用方法如下所示:
函數(shù)名
例如:void
那么,這里的x代表的是何種中斷具體如下:
0:代表外部中斷0
1:定時(shí)/計(jì)數(shù)器0
2:外部中斷1
3:定時(shí)/計(jì)數(shù)器1
4:串行口中斷
這里y代表寄存器組,可取0~7,也可以不寫(xiě)。
例如,外部中斷0可以寫(xiě):
interrupt
外部中斷1可寫(xiě)
interrupt
下面看一個(gè)使用定時(shí)器和中斷的數(shù)字時(shí)鐘的例子:
#include
#define
uchar
uchar
uchar
void
int
while(a--){
for(i=0;i<148;i++);
}
}
//次函數(shù)表明使用的是定時(shí)器,定時(shí)為50ms
void
{
TMOD
//TMOD為
//且為16位定時(shí)器,GATE=0,配合下面TR0=1,則啟動(dòng)寄存器
TH0
//設(shè)定初值,即設(shè)定定時(shí)時(shí)間
TL0
//設(shè)定初值,即設(shè)定定時(shí)時(shí)間
IE
//0x82二進(jìn)制為1000
//設(shè)定允許響應(yīng)總中斷和T0中斷
TR0
//設(shè)置TCON中TR0=1,允許T0工作
}
void
{
TH0
//重新設(shè)定初值
TL0
count++;
if(count==20){
count=0;
second++;
//時(shí)間秒數(shù)加1
}
}
uchar
uchar
uchar
int
for(i=0;i<4;i++){
P1=hang[i];
temp=0x10;
for(j=0;j<4;j++){
if(!(temp&P1)){
return
}
temp<<=1;
}
}
return
}
uchar
uchar
uchar
P2=0;
P0=tab[y/10]-0x80;
Delay(1);
P2=1;
P0=tab[y];
return
}
uchar
uchar
uchar
P2=3;
P0=tab[y/10]-0x80;
Delay(1);
P2=4;
P0=tab[y];
return
}
uchar
uchar
uchar
P2=6;
P0=tab[y/10]-0x80;
Delay(1);
P2=7;
P0=tab[y];
return
}
void
{
uchar
uchar
uchar
Time0_Init();
while(1){
Delay(1);
if(mk==0){
s=show_second(second);
second%=60;
mk++;
}
else
minute+=s;
m=show_minute(minute);
minute%=60;
mk++;
}else{
hour+=m;
h=show_hour(hour);
hour%=24;
mk++;
mk=mk%3;
}
k=
if(12==k||13==k||14==k){
Delay(50);
k=
if(12==k||13==k||14==k){
if(12==k)hour++;
else
else
}
}
}
}
評(píng)論