Keil C51學習 4 按鍵 外部中斷


主板介紹:P3^2~P^5為四個按鍵;P1^0~P1^7為8個LED燈

#include "reg52.h"             //此文件中定義了單片機的一些特殊功能寄存器
typedef unsigned int uint;      //對數據類型進行聲明定義
typedef unsigned char u8;

sbit k1=P3^5;     //定義P31口是k1
sbit led=P1^0;     //定義P10口是led

/*******************************************************************************
* 函 數 名         : delay
* 函數功能           : 晶振11.0592M延時函數
*******************************************************************************/
void delay(uint z)
{
    uint i,j;
     for(j=z;j>0;j--)
     for(i=112;i>0;i--);
}

/*******************************************************************************
* 函 數 名         : keypros
* 函數功能           : 按鍵處理函數,判斷按鍵K1是否按下
*******************************************************************************/
void keypros()
{
        if(k1==0)
        {
            delay(50); 
            if(k1==0)     //再次判斷按鍵是否按下
                led=~led;      //led狀態取反
        }
        while(!k1);     //檢測按鍵是否松開
    
}

/*******************************************************************************
* 函 數 名       : main
* 函數功能         : 主函數
* 輸    入       : 無
* 輸    出         : 無
*******************************************************************************/
void main()
{    
    while(1)
    {    

        keypros();  //按鍵處理函數    
    }        
}
按鍵取反燈亮或滅

計數器(計數器0用P3^4按鈕,計數器1用P3^5按鈕,不懂)

/*-----------------------------------------------
  名稱:計數器0
  論壇:www.doflye.net
  編寫:shifang
  日期:2009.5
  修改:無
  內容:通過外部按鍵計數進入中斷執行LED取反
------------------------------------------------*/
#include<reg52.h> //包含頭文件,一般情況不需要改動,頭文件包含特殊功能寄存器的定義

sbit LED=P1^0;    //定義LED端口

/*------------------------------------------------
                    定時器初始化子程序(按鈕P3^4控制,不知為什么)
------------------------------------------------*/
void Init_Timer0(void)
{
 TMOD |= 0x01 | 0x04;      //使用模式1,16位計數器,使用"|"符號可以在使用多個定時器時不受影響             
 TH0=0xFF;          //給定初值
 TL0=245;         //從245計數到255 
 EA=1;            //總中斷打開
 ET0=1;           //定時器中斷打開
 TR0=1;           //定時器開關打開
}
/*------------------------------------------------
                    主程序
------------------------------------------------*/
main()
{
 Init_Timer0();
 while(1);
}

/*------------------------------------------------
                 定時器中斷子程序
------------------------------------------------*/
void Timer0_isr(void) interrupt 1 using 1
{
 TH0=0xFF;          //重新給定初值
 TL0=245; 

 LED=~LED;        //指示燈反相,可以看到閃爍

}
計數器0
/*-----------------------------------------------
  名稱:計數器1
  論壇:www.doflye.net
  編寫:shifang
  日期:2009.5
  修改:無
  內容:通過外部按鍵計數進入中斷執行LED取反
------------------------------------------------*/
#include<reg52.h> //包含頭文件,一般情況不需要改動,頭文件包含特殊功能寄存器的定義

sbit LED=P1^0;    //定義LED端口

/*------------------------------------------------
                    定時器初始化子程序
------------------------------------------------*/
void Init_Timer1(void)
{
 TMOD |= 0x10 | 0x40;      //使用模式1,16位計數器,使用"|"符號可以在使用多個定時器時不受影響             
 TH1=0xFF;          //給定初值
 TL1=245;         //從245計數到255 
 EA=1;            //總中斷打開
 ET1=1;           //定時器中斷打開
 TR1=1;           //定時器開關打開
}
/*------------------------------------------------
                    主程序
------------------------------------------------*/
main()
{
 Init_Timer1();
 while(1);
}

/*------------------------------------------------
                 定時器中斷子程序
------------------------------------------------*/
void Timer1_isr(void) interrupt 3 
{
 TH1=0xFF;          //重新給定初值
 TL1=245; 

 LED=~LED;        //指示燈反相,可以看到閃爍

}
計數器1

 

中斷定義:

 當機器正在執行程序的過程中,一旦遇到一些異常或者特殊請求時,停止正在 執行的程序轉入必要的處理,處理完畢后,立即返回斷點繼續執行。

 51單片機中的中斷源:

  ①外部中斷

  ②定時器/計數器中斷

  ③串口中斷三類

 

單片機與外設數據傳遞方式

1.無條件傳送: 不考慮外設狀態信息,直接傳送數據

2.查詢傳送:  不斷查詢外設狀態信息,判斷后決定是否傳送數據

3.中斷傳送:  由外設主動向控制器提出申請的數據傳送方式

4.DMA傳送:   直接存儲器存取,需要DMA控制器來完成而不需CPU干預

外部中斷源

外部中斷0  => 12號引腳(INT0/P3.2)

外部中斷1  => 13號引腳(INT1/P3.3)

1、IE – 中斷允許控制寄存器
2、TCON – 控制寄存器

EA 全局中斷允許位,當此位是1時中斷可用。(重要)
ET2 定時器/計數器2中斷允許位
ES 串口中斷允許位
ET1 定時器/計數器1中斷允許位
EX1 外部中斷1允許位
ET0 定時器/計數器0中斷允許位
EX0 外部中斷0允許位 (重要)
和定時器中斷類似,使用外部中斷需要開啟全局中斷允許位EA,以及開啟外部中斷0允許位EX0

EA = 1;     //開啟總中斷
EX0 = 1;     //開啟0號外部中斷

TCON

  TF1 定時器1溢出標志位
  TR1 定時器1運行控制位
  TF0 定時器0溢出標志位
  TR0 定時器0運行控制位

IE1和IE0為狀態位,即表示CPU對當前的中斷執行狀態,一般無需手動設置。需要設置的寄存器位是IT0,以選擇低電平信號觸發還是負跳變信號觸發。

低電平信號 :即該引腳電平信號為0時有效。
負跳變信號 :意思是電平從高跳至低時有效,即1→0的信號,而一直維持低電平則不會觸發中斷。

void initEx0() {
  //中斷允許寄存器IE
  EA = 1;     //開啟總中斷
  EX0 = 1;     //開啟0號外部中斷
  //控制寄存器TCON
  IT0 = 1;     //設置外部中斷觸發方式 
             //0 - 低電平觸發
             //1 - 負跳變觸發
}

 

#include <reg52.h> //包含頭文件,一般情況不需要改動,頭文件包含特殊功能寄存器的定義

typedef unsigned char u8;  //重新定義數據類型名
typedef unsigned int u16;//重新定義數據類型名
sbit key=P3^2;
sbit led=P1^0;        
void delay(u16 num)
{
    u16 x,y;
    for(x=num;x>0;x--)
        for(y=110;y>0;y++);
}

//外部中斷1
void  timer0() interrupt 0
{
   delay(10);
    if(key==0)
         led=~led;
     while(key);
}

void main()//主函數
{
        TCON |=0x01;
        IE=0x81;
        while(1) //主函數大循環
        {
        
        }    
}    

 

 

 

 

按鈕外部中斷0

/*-----------------------------------------------
  名稱:外部中斷0電平觸發
  內容:通過中斷接口P3.2連接的獨立按鍵測試,按一次P1口的LED燈反向,
        這里使用電平觸發,所以一直按鍵不松開和一次按鍵效果不相同,按下會看到燈全部亮
                說明中斷一直在作用,用示波器看則是高頻方波
------------------------------------------------*/
#include<reg52.h> //包含頭文件,一般情況不需要改動,頭文件包含特殊功能寄存器的定義

/*------------------------------------------------
                 外部中斷程序
------------------------------------------------*/
void ISR_Key(void) interrupt 0 using 1
{
    P1=~P1;     //進入中斷程序執行程序,
//此時可以通過 EA=0指令暫時關掉中斷   
}

typedef unsigned int uint;      //對數據類型進行聲明定義
void delay(uint i)
{
    while(i--);
}
sbit btn=P3^2;
sbit led=P1^0;
/*------------------------------------------------
                    主程序
------------------------------------------------*/
main()
{
  P1=0x55;       //P1口初始值
  EA=1;          //全局中斷開
  EX0=1;         //外部中斷0開
  IT0=0;         //電平觸發
  while(1);
}
按鈕中斷

先整理通用的代碼,有些不知所以然

#include<reg52.h> //包含頭文件,一般情況不需要改動,頭文件包含特殊功能寄存器的定義
#include <intrins.h>       //頭文件包含
typedef unsigned char u8;  //重新定義數據類型名
typedef unsigned short u16;//重新定義數據類型名
typedef unsigned long u32; //重新定義數據類型名
sbit PWM_OUT=P1^1;        
u8 idata PWM_Write_Byte[3]=0;

//****************************祁緒電子 2020年5月***
// 定時器0初始化  晶振11059200,12T,輸出50Hz的PWM,占空比0~255
// 定時器初值為:256-(11059200÷12÷50Hz÷256) = 184 = 0xB8
void PWM_Init(void)
{
        TMOD &= 0xF0; //配置定時器工作模式
        TMOD |= 0x02; //配置定時器工作模式 8位自動重裝模式
    TL0 = 0xB8;;                    //定時器初值
    TH0 = 0xB8;                     //定時器重裝初值
    TR0 = 1;                        //啟動定時器0
    ET0=1;                          //允許定時器0申請中斷
        EA=1;                       //中斷總閘閉合
}
//****************************祁緒電子 2020年5月***
//定時器0的CPU處理函數,位置任意寫都行
void PWM_Display_timer0() interrupt 1
{
        
        static u8 pwm_t=0;         //局部變量,不丟失數據
        if(pwm_t<PWM_Write_Byte[0])
        {
                PWM_OUT=1;                                 
        }
        else PWM_OUT=0;
        pwm_t++;
}

//***************************祁緒電子 2020年5月***
// PWM 數模變換數據分配
void PWM_Allot()                                          
{
        static u8 kkk=0;        
        static u8 count=0;
        count++;
        if(count>150)
        {
                count=0;
                kkk++;
                PWM_Write_Byte[0]=kkk;        //kkk為占空比自動增加
                PWM_Write_Byte[1]=10;        
                PWM_Write_Byte[2]=10;
        }
}


void main()//主函數
{
        PWM_Init();
        while(1) //主函數大循環
        {
         PWM_Allot();        
        }
}
View Code

外部中斷1電平觸發

#include<reg52.h> //包含頭文件,一般情況不需要改動,頭文件包含特殊功能寄存器的定義

sbit LED=P1^0; //定義LED端口

void DelayUs2x(unsigned char t);//us級延時函數聲明 
void DelayMs(unsigned char t); //ms級延時
/*------------------------------------------------
                    主程序
------------------------------------------------*/
main()
{
  LED=0;         //LED燈點亮
  EA=1;          //全局中斷開
  EX1=1;         //外部中斷0開
  IT1=0;         //琁T1=0表示電平觸發
  while(1)
  {
                 //在此添加其他程序
  }
}
/*------------------------------------------------
                 外部中斷程序
------------------------------------------------*/
void ISR_INT1(void) interrupt 2 
{
 
 if(!INT1)
   {
   DelayMs(10);//在此處可以添加去抖動程序,防止按鍵抖動造成錯誤
   if(!INT1)
   while(!INT1);//等待按鍵釋放
     {
     LED=!LED;   
     }
   }
}

/*------------------------------------------------
 uS延時函數,含有輸入參數 unsigned char t,無返回值
 unsigned char 是定義無符號字符變量,其值的范圍是
 0~255 這里使用晶振12M,精確延時請使用匯編,大致延時
 長度如下 T=tx2+5 uS 
------------------------------------------------*/
void DelayUs2x(unsigned char t)
{   
 while(--t);
}
/*------------------------------------------------
 mS延時函數,含有輸入參數 unsigned char t,無返回值
 unsigned char 是定義無符號字符變量,其值的范圍是
 0~255 這里使用晶振12M,精確延時請使用匯編
------------------------------------------------*/
void DelayMs(unsigned char t)
{
     
 while(t--)
 {
     //大致延時1mS
     DelayUs2x(245);
     DelayUs2x(245);
 }
}
View Code

外部中斷0下降沿觸發

/*-----------------------------------------------
  名稱:外部中斷0邊沿觸發
  論壇:www.doflye.net
  編寫:shifang
  日期:2009.5
  修改:無
  內容:通過中斷接口P3.2連接的獨立按鍵測試,按一次P1口的LED燈反向,
        這里使用邊沿觸發,所以一直按鍵不松開和一次按鍵效果相同,區
        別於電平觸發
------------------------------------------------*/
#include<reg52.h> //包含頭文件,一般情況不需要改動,頭文件包含特殊功能寄存器的定義
/*------------------------------------------------
                    主程序
------------------------------------------------*/
main()
{
  P1=0x55;       //P1口初始值
  EA=1;          //全局中斷開
  EX0=1;         //外部中斷0開
  IT0=1;         //邊沿觸發
  while(1)
  {
                 //在此添加其他程序
  }
}
/*------------------------------------------------
                 外部中斷程序
------------------------------------------------*/
void ISR_Key(void) interrupt 0 using 1
{
 P1=~P1;         //s3按下觸發一次,P1取反一次
}
外部中斷0下降沿觸發

外部中斷1下降沿觸發

/*-----------------------------------------------
  名稱:外部中斷1電下降沿平觸發
  論壇:www.doflye.net
  編寫:shifang
  日期:2009.5
  修改:無
  內容:通過中斷接口P3.3連接的獨立按鍵測試,按一次P1.0口的LED燈反向,
        作用效果和中斷0相同
------------------------------------------------*/
#include<reg52.h> //包含頭文件,一般情況不需要改動,頭文件包含特殊功能寄存器的定義

sbit LED=P1^0; //定義LED端口

void DelayUs2x(unsigned char t);//us級延時函數聲明 
void DelayMs(unsigned char t); //ms級延時
/*------------------------------------------------
                    主程序
------------------------------------------------*/
main()
{
  LED=0;         //LED燈點亮
  EA=1;          //全局中斷開
  EX1=1;         //外部中斷1開
  IT1=1;         //IT1=1表示邊沿觸發
  while(1)
  {
                 //在此添加其他程序
  }
}
/*------------------------------------------------
                 外部中斷程序
------------------------------------------------*/
void ISR_INT1(void) interrupt 2 
{
 
 if(!INT1)
   {
   DelayMs(10);//在此處可以添加去抖動程序,防止按鍵抖動造成錯誤
   if(!INT1)
   //while(!INT1);//等待按鍵釋放
     {
     LED=!LED;   
     }
   }
}

/*------------------------------------------------
 uS延時函數,含有輸入參數 unsigned char t,無返回值
 unsigned char 是定義無符號字符變量,其值的范圍是
 0~255 這里使用晶振12M,精確延時請使用匯編,大致延時
 長度如下 T=tx2+5 uS 
------------------------------------------------*/
void DelayUs2x(unsigned char t)
{   
 while(--t);
}
/*------------------------------------------------
 mS延時函數,含有輸入參數 unsigned char t,無返回值
 unsigned char 是定義無符號字符變量,其值的范圍是
 0~255 這里使用晶振12M,精確延時請使用匯編
------------------------------------------------*/
void DelayMs(unsigned char t)
{
     
 while(t--)
 {
     //大致延時1mS
     DelayUs2x(245);
     DelayUs2x(245);
 }
}
外部中斷1下降沿觸發

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM