STC51微控制器中斷與定時器配置參考
*外中斷INT0--------void intsvr0(void) interrupt 0 using 1
*定時/計數器T0-----void timer0(void) interrupt 1 using 1
*外中斷INT1--------void intsvr0(void) interrupt 2 using 1
*定時/計數器T1-----void timer0(void) interrupt 3 using 1
*串列埠中斷----------void serial0 interrupt 4 using 1
P3口的代替功能 暫存器地址B0H,位定址B7H~B0H。 1、IE:中斷允許控制暫存器 暫存器地址A8H,可按位定址,位定址AFH~A8H。復位IE全部清零 位地址AFAEADACABAAA9A8位符號EA/ET2ESET1EX1ET0EX0位序號D7D6 D5D4D3D2D1D0EA:中斷允許總控制位 當EA=0時,中斷總禁止。 當EA=1時,中斷總允許後中斷的禁止與允許由各中斷源的中斷允許控制位進行設定。 EX0(EX1):外部中斷允許控制位 當EX0(EX1)=0禁止外中斷 當EX0(EX1)=1允許外中斷 ET0(EX1):定時/計數中斷允許控制位 當ET0(ET1)=0 禁止定時(或計數)中斷 當ET0(ET1)=1 允許定時(或計數)中斷 ET2:定時器2中斷允許控制位 ES:序列中斷允許控制位 當ES=0 禁止序列中斷 當ES=1 允許序列中斷 2、IP:中斷優先順序控制暫存器 暫存器地址B8H,位定址BFH~B8H。 位序號D7D6 D5D4D3D2D1D0位地址BFHBEHBDHBCHBBHBAHB9HB8H位符號//PT2PSPT1PX1PT0PX0PX0——外部中斷0優先順序設定位,1為高優先順序中斷,0為低優先順序中斷 PT0——定時中斷0優先順序設定位 PX1——外部中斷1優先順序設定位 PT1——定時中斷1優先順序設定位 PS——串列埠中斷優先順序設定位 PT2——定時器2優先順序設定位 3、TCON:定時器控制暫存器 暫存器地址88H,位定址8FH~88H。 位地址8FH8EH8DH8CH8BH8AH89H88H位符號TF1TR1TF0TR0IE1IT1IE0IT0TR0(TR1)——定時器執行控制位 當TR0(TR1)=0 停止定時器/計數器工作 當TR0(TR1)=1 啟動定時器/計數器工作 IE0(IE1)——外中斷請求標誌位 當CPU取樣到P3.2(P3.3)[INT0或INT1]出現有效中斷請求時,此位由硬體置1。在中斷響應完成後轉向中斷服務時,再由硬體自動清0。 IT0(IT1)——外中斷請求訊號方式控制位 當IT0(IT1)=1脈衝方式(後沿負跳有效)下降沿觸發有效 當IT0(IT1)=0電平方式(低電平有效)此位由軟體置1或清0。 TF0(TF1)——計數溢位標誌位 當計數器產生計數溢位時,此位由硬體置1。當轉向中斷服務時,再有硬體自動清0。計數溢位的標誌位的使用有兩種情況:採用中斷方式時,作中斷請求標誌位來使用;採用查詢方式時,作查詢狀態位來使用。 |
4、TMOD:工作方式控制暫存器
暫存器地址89H,不可位定址。
位序 |
B7 |
B6 |
B5 |
B4 |
B3 |
B2 |
B1 |
B0 |
位符號 |
GATE |
C/T |
M1 |
M0 |
GATE |
C/T |
M1 |
M0 |
GATE——門控位
當=0時,以執行TR0(或TR1)啟動或禁止定時器、計數器
當=1時,以TR0*/INT0(或TR1*/INT1)啟動或禁止定時器、計數器
GATE=0 以TCON暫存器中的TR0(TR1)啟動定時器/計數器
GATE=1 TCON暫存器中的TR0(TR1)和外部中斷引腳INT0(INT1)啟動定時器,高電位有效
C/T=1由外引腳T0或T1做計數脈衝,C/T=0由TH和TL做定時數。 M1M0——工作方式選擇位
M1,M0:用來選擇計時計數器工作模式
M1 |
M0 |
工作模式 |
說明 |
0 |
0 |
0 |
13位計時計數器 (8192) |
0 |
1 |
1 |
16位計時計數器 (65536) |
1 |
0 |
2 |
8位計時計數器,可自動重新載入計數值 (256) |
1 |
1 |
3 |
當成兩組獨立的8位計時器(256,T0和T1不能同時用) |
5、T2MOD:工作方式控制暫存器
暫存器地址0C9H,不可位定址,用來設定定時器2自動重灌模式遞增或遞減模式
- |
- |
- |
- |
- |
- |
T2OE |
DCEN |
T2OE:定時器2輸出允許位,當=1時,P1.0/T2引腳輸出連續脈衝訊號
DCEN:當=1時,T2配置成向上向下計數器
6、T2CON:定時器控制暫存器,可進行位定址
暫存器地址0C8H,位定址0C8H~0CFH。
位地址 |
CF |
CE |
CD |
CC |
CB |
CA |
C9 |
C8 |
位符號 |
TF2 |
EXF2 |
RCLK |
TCLK |
EXEN2 |
TR2 |
C/T2 |
CP/RL2 |
TF2:T2溢位標記;方式2,3置TF2,方式3不置。
當T2溢位時TF2=1,TD2只能用軟體清0
當RCLK=1或TCLK=1時,TF2將不置位
EXF2:T2外部標記
當EXEN2=1時,T2EX/P1.1引腳上的負跳變引起T2的捕捉/重灌操作,此時EXF2=1。在T2中斷允許時,EXF2=1將引起中斷,EXF2只能用軟體清除。在T2的遞增、遞減計數模式下(DCEN=1)EXF2的置位將不引起中斷。
RCLK:接收時鐘允許
當RCLK=1時,T2的溢位脈衝可用作序列口的接收時鐘訊號,適於序列口模式1、3當RCLK=0時,T1的溢位脈衝用作序列口接收時鐘訊號
TCLK:傳送時鐘允許
當RCLK=1時,T2的溢位脈衝可用作序列口的接收時鐘訊號,適於序列口模式1、3當RCLK=0時,T1的溢位脈衝用作序列口傳送時鐘訊號
EXEN2:T2外部事件(引起捕捉/重灌的外部訊號)允許,即外部使能標誌
當EXEN2=1時,如果T2沒有作序列時鐘輸出(即RCLK+TCLK=0),則在T2EX/P1.1引腳跳變將引起T2的捕捉/重灌操作;
當EXEN2=0時,在T2EX引腳的負跳變將不起作用
TR2:T2計數控制位;TR2=1時允許計數/定時。
C/T2:外部計數器/定時器選擇位;C/T2=1時為計數器,計數脈衝來自T2(P1.0);下降沿觸發
C/T2=0時為內部定時器,以震盪脈衝的十二分頻訊號為計數訊號。
CP/RL2:捕捉/重灌選擇
當CP/RL2=1且EXEN2=1時,T2EX/P1.1引腳的負跳變將引起捕捉操作
當CP/RL2=0且EXEN2=1時,T2EX/P1.1引腳的負跳變將引起重灌操作
當CP/RL2=0且EXEN2=0時,T2的溢位將引起T2的自動重灌操作
當RCLK+TCLK=1時,CP/RL2控制位不起作用,T2被強制工作於重灌方式。重灌方式發生於T2溢位時,常用來作波特率發生器。
7、SCON:序列口控制暫存器
暫存器地址98H,位定址9FH~98H。
位地址 |
9F |
9E |
9D |
9C |
9B |
9A |
99 |
98 |
位符號 |
SM0 |
SM1 |
SM2 |
REN |
TB8 |
RB8 |
TI |
RI |
SM0、SM1:序列口工作方式選擇位
SM2:多機通訊控制位
對於方式0:SM2=0。
對於方式1:SM2=1,只有接到有效的停止位才啟用RI。
對於方式2和3為多機通訊控制位;SM2=1,則接收的第9位資料為0時不啟用RI
REN:允許/禁止序列口接收的控制位,REN=1允許接收資料
TB8:在方式2和方式3中,是被髮送的第9位資料,可根據需要由軟體置1或清零,也可以作為奇偶校驗位,在方式1中是停止位。
RB8:在方式2和方式3中,是被接收的第9位資料(來自第TB8位);在方式1中,RB8收到的是停止位,在方式0中不用。
TI:序列口傳送中斷請求標誌位
當傳送完一幀序列資料後,由硬體置1;在轉向中斷服務程式後,用軟體清0。
RI:序列口接收中斷請求標誌位
當接收完一幀序列資料後,由硬體置1;在轉向中斷服務程式後,用軟體清0。
8、PSW:程式狀態字
暫存器地址D0H,位定址D7H~D0H。
位地址 |
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
位符號 |
CY |
AC |
F0 |
RS1 |
RS0 |
OV |
- |
P |
CY——進位標記。CY=1表示運算時有進位產生。
AC——半進位標記。補助進位位;AC=1表示運算時較低4位有進位產生。
F0——使用者設定標記
RS1 、RS0——4個工作暫存器區的選擇位。
RS1 |
RS0 |
選擇的暫存器組 |
0 |
0 |
暫存器組0 |
0 |
1 |
暫存器組1 |
1 |
0 |
暫存器組2 |
1 |
1 |
暫存器組3 |
OV——溢位標記. OV=1表示運算時有益出產生
P——奇偶校驗標記. 奇偶位;P=0表示A中1的個數是偶數,P=1表示A中1的個數是奇數。
9、PCON:電源控制器及波特率選擇暫存器
位元組地址=87H,不可位定址
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D |
D0 |
SMOD |
(SMOD0) |
(LVDF) |
(POF) |
GF1 |
GF0 |
PD |
IDL |
SMOD——波特率倍增位
SMOD=1:串列埠方式1,2,3時,波特率正常
SMOD=0:串列埠方式1,2,3時,波特率加倍
(SMOD0) |
(LVDF) |
(POF) |
是STC微控制器特有的功能
GF1、GF0——使用者通用標記,使用者課自由使用
PD——掉電模式控制位,PD=1時進入掉電模式,在硬體復位或外中斷低電平觸發或由下降沿觸發恢復。進入掉電模式,外部晶振,cpu,定時器,序列口全部停止工作,只有外部中斷工作
IDL——空閒模式控制位,IDL=1時進入空閒模式,除cpu外,其餘繼續工作。
在AT89S51中PCON.4是電源斷電標記位POF,上電是為1
進入空閒模式:PCON=0x01; 之前執行AUXR=0xFF;定義空閒模式下看門狗WDT不計數。
定時器
1)對TMOD賦值,以確定T0和T1的工作方式
2)計算初值,並將初值寫入TH0,TL0或TH1,TL1
3)中斷方式時,對IE賦值,開放中斷
4)使TR0或TR1置位,啟動定時器計數器定時或計數
能在主程式完成的功能就不在中斷函式中些,否則一定要高效簡潔
方式0和方式3很少用,方式1 用作16位的計數器,方式2用在串列埠波特率發生器
1、發光二極體以一秒亮滅,11.0592M晶振
l定時器0工作方式1
#include <reg52.h> //52系列微控制器標頭檔案
#define uchar unsigned char
#define uint unsigned int
sbit led1=P1^0;
uchar num;
void main()
{
TMOD=0x01; //設定定時器0為工作方式1(M1M0為01)
TH0=(65536-45872)/256; //裝初值11.0592M晶振定時50ms為45872
TL0=(65536-45872)%256;
EA=1; //開總中斷
ET0=1; //開定時器0中斷
TR0=1; //啟動定時器0
while(1) //程式停止在這裡等待中斷髮生
{
if(num==200) //如果到了200次,說明1秒時間到
{
num=0; //然後把num清0重新再計200次
led1=~led1; //讓發光管狀態取反
}
}
}
void T0_time() interrupt 1
{
TH0=(65536-45872)/256; //重灌初值
TL0=(65536-45872)%256;
num++;
}
l定時器0工作方式0
1、定時器方式0為13位計數器,最多能裝載的數2^=8192個,所以最多經過8192個機器週期該計數器就會溢位一次,向cpu申請中斷
2、計算機器週期T,晶振為11.0592MHz,那麼機器週期為12*(1/11059200)=1.0851微s,若t=5ms,則N=5000/1.0851=4607
3、TH0=(8192-4607)/32;中,對32求模是因為定時器方式0為13位計數器,計數支使用了TL0的低5位,這5位最多裝載32個數,再加1進位。16位計數器裝載256個數
void main()
{
TMOD=0x00;//設定定時器0為工作方式0(0000 0000)
TH0=(8192-4607)/32; //裝初值
TL0=(8192-4607)%32;
EA=1; //開總中斷
ET0=1; //開定時器0中斷
TR0=1; //啟動定時器0
l定時器T0的定時方式2
1、定時器2被稱為8位初值自動裝載的8位定時器/計數器,THX被作為常數緩衝器,TLX計數溢位時,在溢位標誌TFX置1的同時,還自動將THX中的常數重新裝入TLX中,使TLX從初值開始重新計數,提高定時的精度。
2、定時器2特別適合做較精確的脈衝訊號發生器,此時晶振頻率一定要是12 的整數倍。
方式2為8位計數器,最多裝2^8=256個,即使用12MHz晶振,最多隻有256微秒
3、機器週期為12*(1/11059200)=1.0851微s,計時1s,當計250個數,需1.0851*250=271.275微秒。需要溢位1000000/271.275=3686,若為12MHz晶振,則溢位4000次
4、主要應用在串列埠波特率發生器。
#include <reg52.h> //52系列微控制器標頭檔案
#define uchar unsigned char
#define uint unsigned int
sbit led1=P1^0;
uint num; //3686遠遠超過了uchar的範圍
void main()
{
TMOD=0x02; //設定定時器0為工作方式2(0000 0010)
TH0=6; //裝初值
TL0=6;
EA=1; //開總中斷
ET0=1; //開定時器0中斷
TR0=1; //啟動定時器0
while(1) //程式停止在這裡等待中斷髮生
{
if(num==3686) //如果到了3686次,說明1秒時間到
{
num=0; //然後把num清0重新再計3686次
led1=~led1; //讓發光管狀態取反
}
}
}
l定時方式3
1、方式3只適用於定時器/計數器T0,當設定定時器T1為方式3,定時器T1不計數,T0分成兩個獨立的8位計數器TL0和TH0。
2、其中TL0為正常8位計數器,計數溢位後置位TF0,並向CPU申請中斷,之後重新裝初值。TH0將佔用定時器T1的。
3、在工作方式3時,T1一定不要用在有中斷的場合,不過可以用來當做序列口的波特率發生器。
TL0計數器對應的8位定時器
#include <reg52.h> //52系列微控制器標頭檔案
#define uchar unsigned char
#define uint unsigned int
sbit led1=P1^0;
sbit led2=P1^1;
uint num1,num2;
void main()
{
TMOD=0x03; //設定定時器0為工作方式3(0000 0011)
TH0=6; //裝初值
TL0=6;
EA=1; //開總中斷
ET0=1; //開定時器0中斷
ET1=1; //開定時器1中斷
TR0=1; //啟動定時器0
TR1=1; //啟動定時器0的高8位計數器
while(1) //程式停止在這裡等待中斷髮生
{
if(num1>=3686) //如果到了3686次,說明1秒時間到
{
num1=0; //然後把num1清0重新再計3686次
led1=~led1; //讓發光管狀態取反
}
if(num2>=1843) //如果到了1843次,說明半秒時間到
{
num2=0; //然後把num2清0重新再計1843次
led2=~led2; //讓發光管狀態取反
}
}
}
void TL0_time() interrupt 1
{
TL0=6; //重灌初值
num1++;
}void TH0_time() interrupt 3
{
TH0=6; //重灌初值
num2++;
}
1、定時器0的方式1實現第一個發光二極體以200ms間隔閃爍,定時器1的方式1實現數碼管前兩位59s迴圈計時
#include <reg52.h> //52系列微控制器標頭檔案
#define uchar unsigned char
#define uint unsigned int
sbit led1=P1^0;
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
void delayms(uint);
void display(uchar,uchar) ;
uchar num, num1,num2,shi,ge;
void main()
{
TMOD=0x01; //設定定時器0為工作方式1(M1M001)
TH0=(65536-45872)/256; //裝初值11.0592M晶振定時50ms為45872
TL0=(65536-45872)%256;
TH1=(65536-45872)/256; //裝初值11.0592M晶振定時50ms為45872
TL1=(65536-45872)%256;
EA=1; //開總中斷
ET0=1; //開定時器0中斷
ET1=1; //開定時器1中斷
TR0=1; //啟動定時器0
TR1=1; //啟動定時器1
while(1) //程式在這裡不停地對數碼管動態掃描同時等待中斷
{
display(shi,ge);
}
}
void display(uchar shi,uchar ge) //顯示子函式
{
P0=table[shi]; //送十位段選資料
P0=0xfe; //送位選資料
delayms(5); //延時
P0=table[ge]; //送個位段選資料
P0=0xfd;
delayms(5);
}
void delayms(uint xms)
{
uint i,j;
for(i=xms;i>0;i--) //i=xms即延時約xms毫秒
for(j=110;j>0;j--);
}
void T0_time() interrupt 1
{
TH0=(65536-45872)/256; //重灌初值
TL0=(65536-45872)%256;
num1++;
if(num1==4) //如果到了4次,說明200ms時間到了
{
num1=0; //清零,重新再計
led1=~led1;
}
}
void T1_time() interrupt 3
{
TH1=(65536-45872)/256; //重灌初值
TL1=(65536-45872)%256;
num++;
if(num2==20) //說明一秒到
{
num2=0;
num++;
if(num==60) //這個數送數碼管顯示,到60歸零
num=0;
shi=num/10;
ge=num%10; //把一個2位數分離後分別送數碼管顯示各位和十位
}
}
2、不按鍵時,P1口的led呈流水燈顯示,按下K1(P3.2),P1口左右4個LED交替閃爍,按下K2(P3.3),P1口LED閃亮,外中斷優先順序相同。
#include <reg52.h> //52系列微控制器標頭檔案
#define uchar unsigned char
#define uint unsigned int
void delayms(uint xms)
{
uint i,j;
for(i=xms;i>0;i--) //i=xms即延時約xms毫秒
for(j=110;j>0;j--);
}
void main()
{
uchar design[9]={0xFF,0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F};
uchar a;
for(;;)
{
for(a=0;a<9;a++)
{
delayms(500);
P1=design[a];
}
EA=1; //開放總開關
EX0=1; //允許外部中斷0中斷
EX1=1; //允許外部中斷1中斷
IT0=1; //設定外部中斷0為邊沿中斷方式
IT1=1; //設定外部中斷1為邊沿中斷方式
IP=0; //設定中斷優先順序
}
}
void intsvr0(void) interrupt 0
{
for(;;)
{
P1=0x0F; //左4個燈亮
delayms(500);
P1=0xF0; //右4個燈亮
delayms(500);
}
}
void intsvr1(void) interrupt 2
{
for(;;)
{
P1=0xFF; //全滅
delayms(500);
P1=0; //全亮
delayms(500);
}
}