风轻云淡愿君赏,消尽烦忧心亮敞。夏去秋来添衣裳,一声问候祝安康!

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下降沿触发

 

 

 

 

posted on 2021-01-30 16:08  荣林  阅读(3116)  评论(0编辑  收藏  举报

导航