找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 13521|回复: 8
打印 上一主题 下一主题
收起左侧

51单片机消抖处理的按键程序源代码

  [复制链接]
跳转到指定楼层
楼主
ID:318620 发表于 2018-5-24 18:07 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
单片机源程序如下:
  1. //软件消抖的独立式键盘输入实验
  2. #include<reg52.h>    //  包含51单片机寄存器定义的头文件
  3. sbit S1=P1^4;        //将S1位定义为P1.4引脚
  4. sbit LED0=P0^0;       //将LED0位定义为P0.0引脚
  5. /*************************************************
  6. 函数功能:延时约30ms
  7. **************************************************/
  8. void delay(void)
  9. {
  10.    unsigned char i,j;
  11.         for(i=0;i<100;i++)
  12.           for(j=0;j<100;j++)
  13.             ;
  14. }
  15. /*************************************************
  16. 函数功能:主函数
  17. **************************************************/
  18. void main(void)  //主函数
  19. {
  20.    LED0=0;       //P0.0引脚输出低电平
  21. while(1)
  22.    {
  23.             if(S1==0)   //P1.0引脚输出低电平,按键S1被按下
  24.          {
  25.            delay(); //延时一段时间再次检测
  26.             if(S1==0)   // 按键S1的确被按下
  27.               LED0=~LED0;  //P0.0引脚取反
  28.                 while(!S1);         
  29.           }      
  30.                   
  31.                         
  32.         }
  33. }
复制代码
按K5按键 控制
以上代码的Keil2工程文件下载:
消抖处理的按键程序.rar (8.11 KB, 下载次数: 32)


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏4 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:528469 发表于 2020-10-10 20:28 | 只看该作者
谢谢了 兄弟 解决了
回复

使用道具 举报

板凳
ID:820160 发表于 2020-11-18 18:31 | 只看该作者
还用这样的消抖方式误导人啊
回复

使用道具 举报

地板
ID:515309 发表于 2022-9-22 15:33 | 只看该作者
请问怎样算出延时是30MS时间
回复

使用道具 举报

5#
ID:1045747 发表于 2022-9-24 14:54 | 只看该作者
陆少 发表于 2022-9-22 15:33
请问怎样算出延时是30MS时间

可能是用debug设置断点看出来的
回复

使用道具 举报

6#
ID:1045747 发表于 2022-9-24 14:57 | 只看该作者
确实这个消抖的方法不好,在运行delay()这个部分的时候,单片机在这30ms的时间里什么也不能做
回复

使用道具 举报

7#
ID:1050150 发表于 2022-11-2 22:43 | 只看该作者
单片机程序是跑着等,不应该等着跑。
回复

使用道具 举报

8#
ID:496636 发表于 2022-11-5 19:12 | 只看该作者
#include<reg52.h>
#define uch unsigned char
#define uint unsigned int
#define ulong unsigned long
sbit ADDR0=P1^0;
sbit ADDR1=P1^1;
sbit ADDR2=P1^2;
sbit ADDR3=P1^3;
sbit ENLED=P1^4;
sbit KEY_IN_1=P2^4;
sbit KEY_IN_2=P2^5;
sbit KEY_IN_3=P2^6;
sbit KEY_IN_4=P2^7;
sbit key_out_1=P2^3;
sbit key_out_2=P2^2;
sbit key_out_3=P2^1;
sbit key_out_4=P2^0;

uch code ledchar[]={                                //从数字0到F的显示码。
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e
};
uch keysta[4][4]={
{1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1},
};
void main()
{

   uch i,j;//循环变量i和j
   uch backup[4][4]={
   {1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1},
   };//按键值备份。
   EA=1;//使能总中断
   ENLED=0;//选择数码管DS1进行显示。
   ADDR3=1;
   ADDR2=0;
   ADDR1=0;
   ADDR0=0;
   TMOD=0x01;//定时器0工作在模式1
   TH0=0xfc;
   TL0=0x67;//定时中断间隔1毫秒
   ET0=1;//开定时器0中断。
   TR0=1;//启动定时器0
   P0=ledchar[0]; //LED显示0
   while(1)
   {
                for (i=0;i<4;i++)//外层循环,执行四次;
                {
                         for (j=0;j<4;j++)//内层循环,执行四次
                         {
                                 if (backup[i]!=keysta[i][j])
                                 {
                                         if (backup[i][j]!=0)//如果上次保存的状态是非0,就是1,表明上次按钮按下,现在状态不同上次保存状态,那意思就是按下后已弹起
                                         {
                                           P0=ledchar[i*4+j];//将编号显示出来。i是行号,从0行开始,j是行中的第几个元素,那么变成一维数据就是行号*列宽+列号
                                         } //判断按下弹起大括号
                                        backup[i][j]=keysta[i][j];
                                 }//判断键值变化大括号
                         } //内层循环大括呈

                }//外层循环大括号
   } //while大括号

} //main函数大括号

void InterruptTimer0() interrupt 1
{
        uch i;
        static uch keyout=0;
        static uch keybuf[4][4]={
         {0xff,0xff,0xff,0xff},{0xff,0xff,0xff,0xff},{0xff,0xff,0xff,0xff},{0xff,0xff,0xff,0xff}
         };
        TH0=0xfc;//重新加载初值
         TL0=0x67;

         keybuf[keyout][0]=(keybuf[keyout][0]<<1)|KEY_IN_1;
         keybuf[keyout][1]=(keybuf[keyout][0]<<1)|KEY_IN_2;
         keybuf[keyout][2]=(keybuf[keyout][0]<<1)|KEY_IN_3;
         keybuf[keyout][3]=(keybuf[keyout][0]<<1)|KEY_IN_4;
         
         //消抖后更新按键状态
         for (i=0;i<4;i++)//每行4个按键,所以循环4次
         {
                  if ((keybuf[keyout][i]&0x0f)==0x00)
                  {           //连续4次扫描值为0,即4*4ms内都是按下状态时,可认为按键已稳定的弹起
                     keysta[keyout][i]=1;
                  }

         }//外层循环大括号
         //执行下一次的扫描输出
         keyout++;
         keyout=keyout&0x03;//索引值加到4即归零
         switch(keyout)
         {
           case 0:key_out_4=1;key_out_1=0;break;  //key_out_1低电平的时候,开始探测第一行按键。顺便把上次低电平的拉高。
           case 1:key_out_1=1;key_out_2=0;break;  //
           case 2:key_out_2=1;key_out_3=0;break;
           case 3:key_out_3=1;key_out_4=0;break;
           default:break;
         }//switch后大括号

}//中断大括号

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

9#
ID:284226 发表于 2023-3-30 22:02 | 只看该作者
你好。请问if ((keybuf[keyout][i]&0x0f)==0x00)。这一段为什么一定先要按位与了。才能进行进行比较呢。就不能这样直接比较吗?if ((keybuf[keyout][i])==0x00)
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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