天天看點

中斷系統知識點

目錄

一、中斷基礎知識介紹

1、中斷基礎

2、寄存器

3、中斷口的設定

二、外部中斷的使用 

1、中斷使用流程

2、中斷代碼 

三、内部中斷的使用 

1、相關知識介紹

2、中斷使用流程

3、相關代碼 

中斷其實并不是那麼吓人哦,一定要搞清楚各寄存器、中斷口、中斷源等示意圖,後來你會發現其實就是根據你一開始的選擇不斷設定而已!

一、中斷基礎知識介紹

你知道中斷是什麼嗎?它有哪些類型呢?

1、中斷基礎

中斷系統:計算機執行某程式時,發生了緊急事件或有特殊請求,處理完畢後再重新執行程式的過程
中斷類型: 中斷分為外部中斷及内部中斷,外部中斷可以由低電平或下降沿兩種方式實作,而       内部中斷則分為計數器模式和定時器模式。
中斷流程:    中斷請求->中斷響應->中斷處理->中斷傳回

**中斷源示意圖**:

中斷系統知識點

小tip:後面中斷相關代碼都要根據該圖設定,不是随意設定的,該圖的掌握對中斷而言至關重要哦!

2、寄存器

寄存器的使用與設定,是中斷不可缺少的重要環節,它可用于控制中斷開關、設定中斷方式等等。

(1)IE寄存器

中斷系統知識點

(2)TCON寄存器

中斷系統知識點
小知識穿插(有關資料的輸入/輸出傳送方式):
  • 無條件傳送方式 : 一方對另一方總是準備好的
  • 查詢傳送方式 :   傳送前一方先查詢另一方狀态,若已準備好就傳送,否則就繼續查詢/等待
  • 中斷傳送方式: 一方通過申請中斷的方式與另一方進行資料傳送

3、中斷口的設定

中斷系統知識點

一定要根據自己選擇的中斷方式與觸發方式(或工作模式)結合圖示選擇中斷入口,不可以自己随意設定! 

二、外部中斷的使用 

不管是内部中斷還是外部中斷,上述内容中的寄存器與中斷源示意圖都需要熟練掌握哦,後面的程式均要結合其進行代碼編寫!

1、中斷使用流程

  1. 允許中斷(IE寄存器)    打開IE中斷總開關   打開相應的中斷開關(外部中斷0或1)
  2. 配置中斷方式(TCON寄存器) 選擇中斷方式為低電平還是下降沿
  3. 編寫中斷服務函數(寫對應的中斷入口)和主函數 

2、中斷代碼 

     下降沿觸發相關代碼

#include <reg52.h>

#define  uchar unsigned char
#define  uint  unsigned int

sbit flag = P3^3;  //對應P3^3的第二功能(外部中斷1輸入)
sbit key = P3^1;  //中斷1必須要使用P3^3,中斷2必須使用P3^2

void delay(uint z)
{
    uint x,y;
    for(x=z;x>0;x--)
        for(y=114;y>0;y--);
}

void int1init()
{
    EA=1;  //打開EA總開關
    EX1=1; //允許外部中斷1中斷
    ET1=1;  //外部中斷1下降沿觸發
}

void int1() interrupt 2
{
    //該單片機中斷口有問題,進了中斷不會出來,隻能加上該循環,正常情況可以不用
    while(!key)
    {
        P2=~P2;  //P2的狀态按位取反
    }
}

void main() 
{
    int1init();  //調用初始化函數進行初始化
    while(1)
    {
        if(key==0)
        {
             delay(20);
             if(key==0)
             {
                  flag=1;
                  flag=0;
                  while(!key);  //松手檢測
             }

        }


    }


}
           

三、内部中斷的使用 

1、相關知識介紹

       51單片機有兩個16位定時器/計數器:  定時器0(T0 引腳為P3^4)   定時器1(T1引腳為P3^5)

       是以,定時器/計數器可以工作在如下不同模式:

  **當定時器工作在定時器模式時**   每經過一個機器周期内部的16位計數寄存值加1,當這個寄存器裝滿時溢出

  **當定時器工作在計數器模式**   T0(P3^4)  T1(P3^5) 每來一個脈沖寄存器加1

工作模式寄存器(用于調配上述寄存器工作模式)

中斷系統知識點

2、中斷使用流程

       1、允許中斷(IE寄存器) 打開IE中斷總開關                                                                                     2、啟動定時/計數器(TCON控制器) TR0=1/TR1=1(T0/T1開始計數)                                               3、設定定時/計時器工作模式    調配定時/計時工作模式  調配8位/16位模                                         4、查詢定時/計數器是否溢出(讀TCON中TF位)

3、相關代碼 

定時器模式

#include "reg52.h"
sbit LA=P2^2;
sbit LB=P2^3;
sbit LC=P2^4;
sbit  key1 = P3^0;     //按鍵1
sbit  key2 = P3^1;     //按鍵2
unsigned char smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
					0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
void delay(unsigned int z)    
{
	unsigned int x,y;
	for(x=z;x>0;x--)
	   for(y=120;y>0;y--);
}

void timefrist()
{
	EA = 1;          //打開總開關
	ET0 = 1;         //中斷函數0的開關
	TR0 = 1;         //打開定時器0開關
	TMOD = 0x01;      //模式一,定時模式
	TH0 = 0xED;       //這裡改值了,到上限就5ms(改初值)
	TL0 = 0xFF;
//開關、模式、賦初值
}
unsigned char miao=0;
void DigDisplay(unsigned char h)
{
	unsigned char a=h%10;                //個位
	unsigned char b=h/10;               //十位
	static unsigned char wei=0;         //靜态變量,就是函數執行完也不會抹去這個變量的值,在次使用函數值可以用(隻有初值時才會初始的,後來不改變)
	switch(wei)                        //這裡重新布局,我們這裡不斷交換顯示,用一次函數就顯示一個,當快速多顯示就動态顯示	
	{
		case 0: LA=1;LB=1;LC=1;P0 = smgduan[b];break;      //wei值0與1不斷交換,就動态顯示
		case 1:	LA=0;LB=1;LC=1;P0 = smgduan[a];break;  
	}
	wei++;                                            //用過之後++
	if(wei==2)                                 //我們隻要1與0不斷交換,為2時就重新回0
	{
		wei = 0;
	}
}
void timer0() interrupt 1
{
	 TH0 = 0xED;         //重新定義5ms初始值
	 TL0 = 0xFF;
	 DigDisplay(miao);   //顯示,不斷5ms顯示就是動态顯示
}
void main()
{	
	timefrist();
	while(1)
	{
		if(key1==0)  //為0,按鍵被按下
		{
			delay(20);
			if(key1==0)   //按鍵消抖
			{
				miao++;    //全局miao加1,顯示就會加1了
				while(!key1);   //松手檢測
			}
		}
		if(key2==0)          //同理
		{
			delay(5);
			if(key2==0)
			{
				miao--;
				while(!key2); 
			}
		}
   }
}
           

小tips:定時器模式初值如何設定?

          例如 5ms,5ms=5000us,5000/1.085(機器周期)=4608(次),65535-4608=60926; 将其換算為二進制為11101101 11111110,則高八位為0xED(TH0),低八位為0xFE(TL0)

計時模式 

#include <reg52.h>

sbit LA=P2^2;
sbit LB=P2^3;
sbit LC=P2^4;  //區段碼位選
sbit key1=P3^0;   //按鍵1
sbit key2=P3^1;  //按鍵2

#define uchar unsigned char
#define uint unsigned int

uint data;

unsigned char code smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x7f,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

//延時函數
void delay(uchar z)
{
    uchar x,y;
    for(x=z;x>0;x--)
        for(y=114;y>0;y--);
}

void timeint1()  //定時器1中斷初始化
{
    EA = 1; //打開中斷總開關
    TR1 = 1;
    TMOD = 0x10;  //0001 0000(十六位定時器,TL1、TH1全用)		
    TH0=0xED;
    TL0=0XFE;    //設定初值為5ms
}


void display(data)
{
    uint m,n;
    m=data/10;  //該數的十位數
    n=data%10;  //該數的個位數
    static uchar wei = 0;  //靜态變量,函數執行完了之後資料不會抹去,下一次執行該函數還可以接着用
    switch(wei)
    {
         case 0: LA=1;LB=1;LC=1; P0=smgduan[m]; break;
         case 1: LA=0;LB=1;LC=1; P0=smgduan[n]; break;
    }
    wei++;  //也就是說,每過10ms才會實作一次個位與十位的顯示,但是速度極快,可以看成是動态顯示
    if(wei==2)
    {
        wei=0; 
    }

}


void timer1() interrupt 0
{
    TH0=0xED;
    TL0=0XFE;    //重新設定初值為5ms
    display(data);  //顯示數字,不斷5ms即實作動态顯示
}

void main()
{
    timeint1();
    while(1)
    {
     	if(key1==0)  //按鍵1被按下時為零
    	{
         		delay(20);
        		 if(key1==0)  //防誤觸
         		{
         			data++;  //按鍵按下,秒數加1
                		while(!key1)  //松手檢測
         		}
    	}
    	if(key2==0)  //按鍵2被按下時為0
   	 {
         		delay(20);
         		if(key2==0)  //防誤觸
        	 	{
         			data--;  //按鍵按下,秒數減1
                		while(!key2)  //松手檢測
        	 	}
   	 }
    }
}
           

繼續閱讀