找回密码
 注册

QQ登录

只需一步,快速开始

搜索

51单片机实用按键模块 没有延时 while语句,可以直接使用

[复制链接]
eng 发表于 2021-6-8 01:15:03 | 显示全部楼层 |阅读模式
单片机实用按键模块,没有延时语句、while()语句,资源占用小。可以直接复制使用与其他程序不冲突。
使用时只需要直接引用全局变量key1和key2就可以。举例:
1、k1按键按下LED1亮,再次按下LED1灭,
if(key1==1)        //k1按键按下
{
   key1=0;//必须软件清零!!!
   LED1=~LED1;
}

2、k2按键按下LED1亮,K2长按LED1灭,
if(key1==2) //k2按键按下
{
   key1=0;//必须软件清零!!!
   LED1=0; //0开1关
}
if(key1==20) //k按键长按
{
   key1=0;//必须软件清零!!!
   LED1=1; //0开1关
}

3、k3按键按下LED1亮,K4按下LED1灭,
if(key1==3) //k3按键按下
{
   key1=0;//必须软件清零!!!
   LED1=0; //0开1关
}
if(key1==4) //k4按键按下
{
   key1=0;//必须软件清零!!!
   LED1=1; //0开1关
}

4、K3按下一次,数据m 增加1,长按k3两秒以上每隔500ms数据m 增加10;K4按下一次,数据m 减少1,长按k4两秒以上每隔500ms数据m 减少10;
if(key1==3) //k3按键按下
{
   key1=0;//必须软件复位
   m++; //数据m 增加1
}
if(key2==3) //k3按键按下两秒以上,注意key2不需要清零,key1必须清零!!!
{
   if(ms1>2000&&ms1%500==0) m=m+10; //长按k3两秒以上每隔500ms数据m 增加10,ms1是毫秒变量,需要放在定时器1ms中断中自加,ms1++;
}
else ms1=0;        //复位

if(key1==4) //k4按键按下
{
   key1=0;//必须软件复位
   m--; //数据m -1
}
if(key2==4) //k4按键按下两秒以上 ,注意key2不需要清零,key1必须清零!!!
{
   if(ms2>2000&&ms2%500==0)  m=m-10; //长按k4两秒以上每隔500ms,ms2是毫秒变量,需要放在定时器1ms中断中自加,ms2++;
}
else ms2=0;//复位

//下面是完整程序代码:
#include "stc8.h"
#include "intrins.h"
#define u8  unsigned char
#define u16 unsigned int
sbit k1=P0^0;//按键1,四个按键可以是任意I/O口。按键按下时k1=0,按键释放k1=1
sbit k2=P0^1;//按键2
sbit k1=P0^2;//按键3
sbit k1=P0^3;//按键4
sbit LED1=P1^0;//LED1

//u8 key1[4];//按键变量数组,4个按键互不影响,如果用key1,一次只能够按一个按键,不允许同时按键。
u8 key1;//按键变量1,输出按键单击,长按。每单击或长按一次只输出一次,由调用函数清零。//key1=1/2/3/4是对应的按键单击,key1=10、20、30、40是对应的按键长按。key1=0表示没有按键按下。
//key1主要用途是:判断某一个按键是单击还是长按.注意调用函数需要将key1清零!!!
//u8 key2[4];//按键变量数组,4个按键互不影响,如果用key2,一次只能够按一个按键,不允许同时按键。
u8 key2;//按键变量2,输出按键单击,每10ms输出一次,key1=1/2/3/4是对应的按键单击。
//key2主要用途是:长按按键时快速增加或减少数值。
u16 ms1,ms2;//毫秒计时
u16 m;//
void key() //按键处理模块,需要放在10ms中断中运行!!!
/* 说明:1、按键单击,指按下100-1000ms内释放,加入时间限制是为了防止干扰。
             2、按键长按,指按下3-10s内释放,加入时间限制是为了防止干扰。
              3、函数运行后,按键值保存在key1、key2。用户直接调用key1、key2即可。

*/
{
  //静态变量,必须要static
  u16 static kgr[4];    //必须要static,抗干扰时间数组
  u8  static kanggr[4]; //中间变量1
  u8  static anjtem[4]; //按键释放中间变量。
  u8 i;
  u8 L_anj[4];
  L_anj[0]=k1;
  L_anj[1]=k2;
  L_anj[2]=k3;
  L_anj[3]=k4;
  for(i=0;i<3;i++)  //4个按键处理,key1,
   {
         if(L_anj[ i]==0)        //按键按下                                       
          { if(kanggr[ i]==0)        //中间变量1,与下面互锁
             { kgr[ i]=0;                //抗干扰时间清零,每次按键只写1次。
               kanggr[ i]=1;         //中间变量1
               anjtem[ i]=1;         //按键释放中间变量。与下面互锁
            }

           if(anjtem[ i]==1)
           {
                  kgr[ i]++;//10毫秒计时。
                  if(kgr[ i]>1000) //按键按下大于10秒,强制复位,防止误按。
                   { anjtem[ i]=0; //按键释放中间变量。与上面互锁
                     kgr[ i]=0;
                     key1=0;
//                  key1[ i]=0;//数组,4个按键独立
                   }
           }
         }

     else    //按键释放
     { kanggr[ i]=0;           //中间变量1,与上面互锁
           if(kgr[ i]>9&&kgr[ i]<99) //按键间隔100--1000毫秒才有效,防止电磁干扰。时间可以修改
                 key1=i+1;   //单击,按键间隔100--1000毫秒,每次释放只写1次。一次只能够按一个按键,不允许同时按键。
           //key1[ i]=i+1;//数组,4个按键独立
           else if(kgr[ i]>300&&kgr[ i]<1000) //按键间隔3000--10000毫秒才有效,防止电磁干扰。时间可以修改
                 key1=(i+1)*10;//长按,按键间隔3--10秒,每次释放只写1次。
           //key1[ i]=(i+1)*10;//数组,4个按键独立
           else key1=0;    //清零。  
     }
  }

//下面是处理:key2是有按键按下就输出键值。        
    for(i=0;i<3;i++)
         { if(L_anj[ i]==0)
           key2=i+1;//一次只能够按一个按键,不允许同时按键。
         //key2[ i]=i+1;//数组,4个按键独立.
         }
}


void timer0() interrupt 1                 //计时器T0中断1ms。
{
  //静态变量,必须要static
  u8  static time=0;   //毫秒变量。
  time++;//毫秒计时。
  if(time>9) //10ms运行一次按键处理函数,不需要防抖程序。
  {
       time=0;
        key();//按键处理模块,需要放在10ms中断中运行!!!
  }
//下面的语句不是按键模块需要的,可以删除。
    ms1++;ms2++;//毫秒计时
}

void main()
{
//1毫秒@12.000MHz,下面是STC单片机定时器0代码,如果是别的单片机请根据手册修改
        AUXR |= 0x80;                //定时器时钟1T模式
        TMOD &= 0xF0;                //设置定时器模式
        TL0 = 0x20;                //设置定时初值,1毫秒@12.000MHz
        TH0 = 0xD1;                //设置定时初值,1毫秒@12.000MHz
        TF0 = 0;                //清除TF0标志        
        ET0 = 1;        //使能定时器中断
       EA = 1;                    //打开总中断
        TR0 = 1;                //定时器0开始计时
while(1)
  {
//1、k1按键按下LED1亮,再次按下LED1灭,
    if(key1==1)        //k1按键按下
     {
       key1=0;//必须软件清零!!!
       LED1=~LED1;
     }

//2、k2按键按下LED1亮,K2长按LED1灭,
    if(key1==2) //k2按键按下
     {
       key1=0;//必须软件清零!!!
       LED1=0; //0开1关
     }
   if(key1==20) //k按键长按
     {
       key1=0;//必须软件清零!!!
       LED1=1; //0开1关
     }

//3、k3按键按下LED1亮,K4按下LED1灭,
   if(key1==3) //k3按键按下
    {
      key1=0;//必须软件清零!!!
      LED1=0; //0开1关
    }
   if(key1==4) //k4按键按下
    {
      key1=0;//必须软件清零!!!
      LED1=1; //0开1关
    }

//4、K3按下一次,数据m 增加1,长按k3两秒以上每隔500ms数据m 增加10;K4按下一次,数据m 减少1,长按k4两秒以上每隔500ms数据m 减少10;
//m的范围:0-60000
   if(key1==3) //k3按键按下
    {
      key1=0;//必须软件清零!!!
      if(m<60000) m++; //数据m 增加1
    }
   if(key2==3) //k3按键按下两秒以上,注意key2不需要清零,key1必须清零!!!
    {
      if(ms1>2000&&ms1%500==0)
           {if(m<=59990) m=m+10;} //长按k3两秒以上每隔500ms数据m 增加10,ms1是毫秒变量,需要放在定时器1ms中断中自加,ms1++;
    }
   else ms1=0;        //复位

   if(key1==4) //k4按键按下
    {
      key1=0;//必须软件复位
      if(m>0) m--; //数据m -1
    }
   if(key2==4) //k4按键按下两秒以上 ,注意key2不需要清零,key1必须清零!!!
    {
      if(ms2>2000&&ms2%500==0)
          {if(m>9)  m=m-10;} //长按k4两秒以上每隔500ms,ms2是毫秒变量,需要放在定时器1ms中断中自加,ms2++;
    }
   else ms2=0;//复位
}
}
这是按键检测模块函数:要认真看才能够理解。
void key() //按键处理模块,需要放在10ms中断中运行!!!
/* 说明:1、按键单击,指按下100-1000ms内释放,加入时间限制是为了防止干扰。
             2、按键长按,指按下3-10s内释放,加入时间限制是为了防止干扰。
             3、函数运行后,按键值保存在key1、key2。用户直接调用key1、key2即可。
*/
{
  u16 static kgr[4];    //必须要static,抗干扰时间数组
  u8  static kanggr[4]; //中间变量1
  u8  static anjtem[4]; //按键释放中间变量。
  u8 i;
  u8 L_anj[4];
  L_anj[0]=k1;
  L_anj[1]=k2;
  L_anj[2]=k3;
  L_anj[3]=k4;
  for(i=0;i<3;i++)  //4个按键处理,key1,
   {
         if(L_anj[ i]==0)        //按键按下                                       
          { if(kanggr[ i]==0)        //中间变量1,与下面互锁
             { kgr[ i]=0;                //抗干扰时间清零,每次按键只写1次。
               kanggr[ i]=1;         //中间变量1
               anjtem[ i]=1;         //按键释放中间变量。与下面互锁
            }

           if(anjtem[ i]==1)
           {
                  kgr[ i]++;//10毫秒计时。
                  if(kgr[ i]>1000) //按键按下大于10秒,强制复位,防止误按。
                   { anjtem[ i]=0; //按键释放中间变量。与上面互锁
                     kgr[ i]=0;
                     key1=0;
                   }
           }
         }

     else    //按键释放
     { kanggr[ i]=0;           //中间变量1,与上面互锁
           if(kgr[ i]>9 && kgr[ i]<99) //按键间隔100--1000毫秒才有效,防止电磁干扰。时间可以修改
                 key1=i+1;   //单击,按键间隔100--1000毫秒,每次释放只写1次。一次只能够按一个按键,不允许同时按键。
           else if(kgr[ i]>300 && kgr[ i]<1000) //按键间隔3000--10000毫秒才有效,防止电磁干扰。时间可以修改
                 key1=(i+1)*10;//长按,按键间隔3--10秒,每次释放只写1次。
           else key1=0;    //清零。  
     }
  }

//下面是处理:key2是有按键按下就输出键值。        
    for(i=0;i<3;i++)
         { if(L_anj[ i]==0)
           key2=i+1;//一次只能够按一个按键,不允许同时按键。
         }
}


您需要登录后才可以回帖 登录 | 注册

本版积分规则

QQ|手机版|小黑屋|ELEOK |网站地图

GMT+8, 2024-4-25 19:28

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表