找回密码
 立即注册

QQ登录

只需一步,快速开始

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

判断按钮单、双、三击,开关相应的led,编译通过,逻辑却没反应,诚心请教指点,谢谢

[复制链接]
跳转到指定楼层
楼主
ID:52701 发表于 2013-9-4 09:08 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#include<reg51.h>     //使用的是stc12c4052ad
sbit led1  = P1^7;     // LED1接P1.7脚
sbit led2  = P1^6;     // LED2接P1.6脚
sbit led3  = P1^5;     // LED3接P1.5脚
sbit led4  = P1^4;     // LED4接P1.4脚
sbit button = P1^0;     // 按钮接P1.0脚
void s(unsigned int a) 、// 延时函数
{
unsigned char i,j;
for(i=0;i<a;i++)
  for(j=0;j<600;j++);
}
void main(void)
{
unsigned  char key=0;        //按钮状态判断变量
led1=led2=led3=led4=1;          //led初始均为关闭
button=1;          //按钮初始化为按下
while(1){
    if(button==0){      
     key+=1;        //单击key值为1
      s(20);
   if(button==0){
      key+=1;       //双击key值为2
       s(20);
    if(button==0){
       key+=1;         //三击key值为3
        s(20);
     if(button==0){
        key+=1;     //四击key值为4
         s(20);
      if(button==0){
       key+=1;    //长按key值为5
       s(100);
        while(button==0);
      }
     }
    }
  
   }
  }
  switch(key){         //根据key值开关相应引脚的led灯
   case 1:
    led1=~led1;
    break;
   case 2:
    led2=~led2;
    break;
   case 3:
    led3=~led3;
    break;
   case 4:
    led4=~led4;
    break;
   default:
    break;
  }

}
}

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

使用道具 举报

沙发
ID:1 发表于 2013-9-4 12:25 | 只看该作者
你应该要做一下消抖处理
回复

使用道具 举报

板凳
ID:153199 发表于 2017-1-8 16:09 | 只看该作者
消抖处理一下
回复

使用道具 举报

地板
ID:140489 发表于 2017-1-11 11:15 | 只看该作者
这样写可以做到按一次亮一个灯,按第5次,灯全灭
#include<reg52.h>   
sbit led1  = P1^7;     // LED1接P1.7脚
sbit led2  = P1^6;     // LED2接P1.6脚
sbit led3  = P1^5;     // LED3接P1.5脚
sbit led4  = P1^4;     // LED4接P1.4脚
sbit button = P1^0;     // 按钮接P1.0脚
void delay(unsigned char ms)// 延时函数
{
unsigned char i,j;
for(i=ms;i>0;i--)
  for(j=110;j>0;j--);
}  


void main(void)
{
unsigned  char key=0;        //按钮状态判断变量

//led1=led2=led3=led4=1;          //led初始均为关闭

button=1;          //按钮初始化为按下
while(1){
   
        if(button==0)
        {
          delay(30);
          
          if(button==0)
          {   
        key++;
          while(button==0);
          }
  }
  switch(key){         //根据key值开关相应引脚的led灯
   case 1:
    led1=0;
    break;
   case 2:
    led2=0;
    break;
   case 3:
    led3=0;
    break;
   case 4:
    led4=0;
    break;
        case 5:
    led1=led2=led3=led4=1;
    break;
   default:
    break;
  }

}
}
回复

使用道具 举报

5#
ID:140489 发表于 2017-1-11 11:24 | 只看该作者
//按1次亮1个灯,按4次4个灯全亮,按第5次,灯全灭,如此循环;仿真通过

#include<reg52.h>   
sbit led1  = P1^7;     // LED1接P1.7脚
sbit led2  = P1^6;     // LED2接P1.6脚
sbit led3  = P1^5;     // LED3接P1.5脚
sbit led4  = P1^4;     // LED4接P1.4脚
sbit button = P1^0;     // 按钮接P1.0脚
void delay(unsigned char ms)// 延时函数
{
unsigned char i,j;
for(i=ms;i>0;i--)
  for(j=110;j>0;j--);
}  


void main(void)
{
unsigned  char key=0;        //按钮状态判断变量

//led1=led2=led3=led4=1;          //led初始均为关闭

button=1;          //按钮初始化为按下
while(1){
   
        if(button==0)
        {
          delay(30);
          
          if(button==0)
          {   
        key++;
          while(button==0);
          if(key==6)
          {key=0;}
          }
  }
  switch(key){         //根据key值开关相应引脚的led灯
   case 1:
    led1=0;
    break;
   case 2:
    led2=0;
    break;
   case 3:
    led3=0;
    break;
   case 4:
    led4=0;
    break;
        case 5:
    led1=led2=led3=led4=1;
    break;
   default:
    break;
  }

}
}
回复

使用道具 举报

6#
ID:140489 发表于 2017-1-11 14:03 | 只看该作者
//按1次亮1个灯,按4次4个灯全亮,按第5次,灯全灭,如此循环

#include<reg52.h>   
sbit led1  = P1^7;     // LED1接P1.7脚
sbit led2  = P1^6;     // LED2接P1.6脚
sbit led3  = P1^5;     // LED3接P1.5脚
sbit led4  = P1^4;     // LED4接P1.4脚
sbit button = P1^0;     // 按钮接P1.0脚
void delay(unsigned char ms)// 延时函数
{
unsigned char i,j;
for(i=ms;i>0;i--)
  for(j=110;j>0;j--);
}  


void main(void)
{
unsigned  char key=0;        //按钮状态判断变量

//led1=led2=led3=led4=1;          //led初始均为关闭

button=1;          //按钮初始化为按下
while(1){
   
        if(button==0)
        {
          delay(30);
          
          if(button==0)
          {   
        key+=1;
          while(button==0);
          if(key==6)
          key=0;
          }
  }
  switch(key){         //根据key值开关相应引脚的led灯
   case 1:
    led1=0;
    break;
   case 2:
    led2=0;
    break;
   case 3:
    led3=0;
    break;
   case 4:
    led4=0;
    break;
        case 5:
    led1=led2=led3=led4=1;
    break;
   default:
    break;
  }

}
}
回复

使用道具 举报

7#
ID:129918 发表于 2017-1-11 20:57 | 只看该作者
顶ing一个
回复

使用道具 举报

8#
ID:161477 发表于 2017-1-12 15:54 | 只看该作者
单击,双击,长按
/***********************************************************************************************************

程序的功能:一个按键的单击,双击,长按。三种按键方式,然后做不同的处理。这里就以P1口LED灯变化作为测试。

单击:点亮P1口上第一个LED灯。(低电平点亮)

双击:点亮P1口上第二个LED灯。(低电平点亮)

长按:长按:点亮P1口上的8个LED灯。(低电平点亮)

使用方法:

硬件的连接:P2.0作为按键的输入,P1口作为LED显示,连接好后,直接复制粘贴生成HEX文件,烧写进C51就能用。

************************************************************************************************************/

#include<reg51.h>

#define N_key 0 //无键

#define S_key 1 //单键

#define D_key 2 //双键

#define L_key 3 //长键

#define key_state_0 0

#define key_state_1 1

#define key_state_2 2

#define key_state_3 3

sbit key_input = P2^0; // 按键输入口

unsigned char time_10ms_ok = 0;

unsigned char key = 0;

unsigned char key_driver(void)

{

static unsigned char key_state = key_state_0, key_time = 0;

unsigned char key_return = N_key;

bit key_press;

key_press = key_input; // 读按键I/O电平

switch (key_state)

{

case key_state_0: // 按键初始态

if (!key_press) key_state = key_state_1; // 键被按下,状态转换到按键消抖和确认状态

break;

case key_state_1: // 按键消抖与确认态

if (!key_press)

{

key_time = 0; //

key_state = key_state_2; // 按键仍然处于按下,消抖完成,状态转换到按下键时间的计时状态,但返回的还是无键事件

}

else

key_state = key_state_0; // 按键已抬起,转换到按键初始态。此处完成和实现软件消抖,其实按键的按下和释放都在此消抖的。

break;

case key_state_2:

if(key_press)

{

key_return = S_key; // 此时按键释放,说明是产生一次短操作,回送S_key

key_state = key_state_0; // 转换到按键初始态

}

else if (++key_time >= 100) // 继续按下,计时加10ms(10ms为本函数循环执行间隔)

{

key_return = L_key; // 按下时间>1000ms,此按键为长按操作,返回长键事件

key_state = key_state_3; // 转换到等待按键释放状态

}

break;

case key_state_3: // 等待按键释放状态,此状态只返回无按键事件

if (key_press) key_state = key_state_0; //按键已释放,转换到按键初始态

break;

}

return key_return;

}

/*=============

中间层按键处理函数,调用低层函数一次,处理双击事件的判断,返回上层正确的无键、单键、双键、长键4个按键事件。

本函数由上层循环调用,间隔10ms

===============*/

unsigned char key_read(void)

{

static unsigned char key_m = key_state_0, key_time_1 = 0;

unsigned char key_return = N_key,key_temp;

key_temp = key_driver();

switch(key_m)

{

case key_state_0:

if (key_temp == S_key )

{

key_time_1 = 0; // 第1次单击,不返回,到下个状态判断后面是否出现双击

key_m = key_state_1;

}

else

key_return = key_temp; // 对于无键、长键,返回原事件

break;

case key_state_1:

if (key_temp == S_key) // 又一次单击(间隔肯定<500ms)

{

key_return = D_key; // 返回双击键事件,回初始状态

key_m = key_state_0;

}

else

{ // 这里500ms内肯定读到的都是无键事件,因为长键>1000ms,在1s前低层返回的都是无键

if(++key_time_1 >= 50)

{

key_return = S_key; // 500ms内没有再次出现单键事件,返回上一次的单键事件

key_m = key_state_0; // 返回初始状态

}

}

break;

}

return key_return;

}

void main()

{

P1 = 0xff;        //IO口初始化

P2 = 0xff;

//定时器的初始化

TMOD = 0x01;        //选择定时器的工作模式:定时器0,方式1

TH0 = (65535 - 10000)/256; //定时器的初值

TL0 = (65535 - 10000)%256;

EA = 1;        //开打总中断使能

ET0 = 1;        //打开定时器0 的使能

TR0 = 1;        //打开定时器0 ,开始工作

while(1)

{

if(time_10ms_ok) //time_10ms_ok = 1,表示计时到了10MS。(10MS扫描一次按键)

{

time_10ms_ok = 0; //清除计时10MS标志

key = key_read(); //调用扫描按键程序,返回一个键值

if (key == L_key) //长按:点亮P1口上的8个LED灯。(低电平点亮)

{

P1 = 0x00;

}

else if(key == D_key)//双击:点亮P1口上第二个LED灯。(低电平点亮)

{

P1 = 0xfd;

}

else if(key == S_key)//单击:点亮P1口上第一个LED灯。(低电平点亮)

{

P1 = 0xfe;

}

}

}

}
void timer0(void) interrupt 1        //用的是定时器0, 这个“interrupt 1”中的“1”代表1号中断即是定时器0中断。如果是“0”就是外部中断0;“2“=外部中断1;”3“定时器1中断;”4“=串行口中断
{

TH0 = (65535 - 10000)/256;

TL0 = (65535 - 10000)%256; //定时器0的方式1,得在中断程序中重复初值。

time_10ms_ok = 1; //定时10MS 的标志

}
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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