zoukankan      html  css  js  c++  java
  • 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下降沿触发

     

  • 相关阅读:
    wiki iso88591字符表的解释
    [c]字符1一维数组求长度
    vim 用户配置
    PHP中向浏览器输出图片
    如何及时取消 BackgroundWorker 组件的后台工作
    python basic
    php5.1中的时区设置。
    MyBatis的深入原理分析之1架构设计以及实例分析
    hibernate缓存:一级缓存和二级缓存
    Spring 注解(Annotation)代替XML实现零配置
  • 原文地址:https://www.cnblogs.com/bymeet/p/14349352.html
Copyright © 2011-2022 走看看