定時器中斷是由單片機中的定時器溢出而申請的中斷。
51單片機中有兩個定時器T0和T1:
TF0:定時器T0溢出中斷請求。當定時器TO產生溢出時,TO中斷請求標志TF0置1,請求中斷處理。
TF1:定時器T1溢出中斷請求。當定時器Tl產生溢出時,T1中斷請求標志TF1置1,請求中斷處理。
Stm32共有11個定時器:
1.兩個高級定時器:TIM1、TIM8-------------------------APB2
2.四個通用定時器:TIM2~TIM5-------------------------APB1
3.兩個基本定時器:TIM6、TIM7-------------------------APB1
4.兩個看門狗
5.一個系統嘀嗒定時器(SysTick)
定時/計數器
編輯
定時/計數器T0和T1分別是由兩個8位的專用寄存器組成,即定時/計數器T0由TH0和TL0組成,T1由TH1和TL1組成。此外,其內部還有2個8位的特殊功能寄存器TMOD和TCON,TMOD負責控制和確定T0和T1的功能和工作模式,TCON用來控制T0和T1啟動或停止計數,同時包含定時/計數器的狀態。 [1]
TF1:定時器1溢出標志。定時/計數器溢出時由硬件置位。中斷處理時由硬件清除。或用軟件清除。
TF0:定時器0溢出標志。定時/計數器溢出時由硬件置位。中斷處理時由硬件清除,或用軟件清除。
工作流程
編輯
定時器工作的流程可以按照這個順序(以51為例用定時器0方式一產生10毫秒的定時)
1、確定使用哪個定時器,使用哪種方式,這一步通過TMOD設置,TMOD的低四位是設置定時器0的,高四位是用來設置定時器1的,其中的M0,M1是用來設置定時器工作在哪種方式,GATE一般用不要設置,C/T是選擇計數模式還是定時模式的,如:TMOD = 0X01,就說明定時器0工作在方式1。
2、接下來就要設置定時的時間,用定時器定時50毫秒,可以用這種方式TH0 = (65535 - 10000) / 256,TL0 = (65535 - 10000) % 256;可以這樣理解:因為這是定時器的初值,也就是說計數脈沖就是在這個數的基礎上向上遞增,到達65535后就溢出產生中斷。
3、第三步打開中斷,使用IE寄存器,首先打開總中斷EA = 1,這一步是所有中斷所必須的,然后打開定時器0中斷,ET0 =1。
4、這時準備工作結束,啟動定時器,使用TCON寄存器,TR0 = 1,實現了一個10毫秒的定時。
代碼如下:(中斷時間根據情況改變)
#include <reg51.h>
#include <delay.h>
sbit key1 = P0^0;
sbit LED1 = P3^0;
#define DataPort P1 //宏定義,如果換接口,需要修改這里
sbit Seg_Latch = P2^2; //段鎖存
sbit Bit_Latch = P2^3; //位鎖存
unsigned char code Seg_Code[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //段碼
unsigned char code Bit_Code[] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //位碼
void Display(unsigned char m,unsigned char num,unsigned int n);
unsigned char i;
void main()
{
TMOD = 0x01;
EA = 1; //開中斷
ET0 = 1;
//因為只有一個中斷,所以IP不用設置
TH0 = (65536 - 400) / 256;
TL0 = (65536 - 400) % 256;
TR0 = 1; //開啟定時器0,等待中斷的到來
while(1)
{
key1 = 1;
if(!key1) //按下key1
{
DelayMs(50);
if(!key1) //判斷key1是否持續按下,進行防抖測試
{
// while(!key1) //
{
LED1 = ~LED1;
}
while(!key1);
LED1 = 1;
}
i++;
if(i > 19)
{
i = 0;
}
Display(1,2,i);
}
}
}
void Display(unsigned char m,unsigned char num,unsigned int n) //兩位共陰極數碼管顯示數字
{
unsigned char j,a[5];
a[0] = n / 10;
a[1] = n % 10;
for(j = m-1;j < num;j++)
{
DataPort = 0;
Seg_Latch = 1; //段開門
Seg_Latch = 0; //段關門
DataPort = Bit_Code[j]; //送位碼,鎖定第m位
Bit_Latch = 1; //位開門
Bit_Latch = 0; //位關門
DataPort = Seg_Code[a[j]]; //送段碼
Seg_Latch = 1; //段開門
Seg_Latch = 0; //段關門
}
}
void T0_ISR(void) interrupt 1
{
unsigned char j;
EA = 0; //如果你不想被其他中斷打斷,屏蔽中斷
TH0 = (65536 - 400) / 256; //
TL0 = (65536 - 400) % 256;
Display(1,2,i);
EA = 1;
}
|