找回密码
 立即注册

QQ登录

只需一步,快速开始

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

51单片机如何实现 按下按键执行某函数或语句,松开后停止执行这个函数或语句

[复制链接]
跳转到指定楼层
楼主
ID:879924 发表于 2021-11-16 12:14 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 macboa 于 2021-11-16 12:25 编辑

在做一个51小车,用定时器扫描按键状态。来控制加速和减速。
想实现的功能是,按住加速按键,执行加速函数,同时LED亮,松开就不再加速,灯灭,跳出。
  1. LED1=P1^0;
  2. LED2=P1^1;
  3. void main(void)
  4. {
  5.   unsigned char Key_Value=0;
  6.   Timer0_Init();
  7.   while(1)
  8.   {
  9.     Key_Value=getKey_Value();
  10.     switch(Key_Value)
  11.     {
  12.       case 1:LED1=1;Speed_UP();break;
  13.       case 2:LED2=1;Speed_Down();break;
  14.     }
  15.   }
复制代码

我把case:改成
  1. case 1:
  2. {
  3.       while(Key_Value==1)
  4.       {
  5.           Speed_UP();
  6.           LED1=1;
复制代码

可是还是一直在执行。应该如何修改呢?
下面是中断函数:
  1. void Timer0_ISR(void) interrupt 1
  2. {
  3.     static unsigned int Timer0_Count=0;
  4.     TL0=0x18;
  5.     TH0=0xFC;                                
  6.     Timer0_Count++;
  7.     if(Timer0_Count>=20)
  8.     {
  9.         Timer0_Count=0;
  10.         Key_Scan_Loop();
  11.     }
  12. }
复制代码

这里是Key.c里的
  1. unsigned char getKey_State(void)
  2. {
  3.     unsigned char Key_Num=0;
  4.    
  5.     if(Key_OpenHeadLights==0){Key_Num=1;}
  6.     if(Key_BrakeMotor==0){Key_Num=2;}
  7.     if(Key_SpeedUpMotor==0){Key_Num=3;}
  8.     if(Key_BackMotor==0){Key_Num=4;}
  9.    
  10.     return Key_Num;
  11. }
  12. void Key_Scan_Loop(void)
  13. {
  14.     static unsigned char Key_NowState=0;    //按键现在状态
  15.     static unsigned char Key_LastState=0;        //按键上次状态
  16.    
  17.     Key_LastState=Key_NowState;
  18.     Key_NowState=getKey_State();
  19.    
  20.     if(Key_LastState==0&&Key_NowState==1)
  21.     {
  22.         Key_Number=1;
  23.     }
  24.     if(Key_LastState==0&&Key_NowState==2)
  25.     {
  26.         Key_Number=2;
  27.     }
  28.     if(Key_LastState==0&&Key_NowState==3)
  29.     {
  30.         Key_Number=3;
  31.     }
  32.     if(Key_LastState==0&&Key_NowState==4)
  33.     {
  34.         Key_Number=4;
  35.     }
  36. }
  37. unsigned char getKey_Value(void)
  38. {
  39.     unsigned char Key_Temp=0;
  40.    
  41.     Key_Temp=Key_Number;
  42.     Key_Number=0;
  43.    
  44.     return Key_Temp;
  45. }
复制代码



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

使用道具 举报

沙发
ID:584814 发表于 2021-11-16 14:46 | 只看该作者
void Key_Scan_Loop(void)
{
    static unsigned char Key_NowState=0;    //按键现在状态
    static unsigned char Key_LastState=0;        //按键上次状态
......
每进一次 Key_Scan_Loop 都将按键现在的状态和上次的状态清零 ?
回复

使用道具 举报

板凳
ID:554500 发表于 2021-11-16 15:29 | 只看该作者

sbit Key=P1^0;

void Key_scan()
{
    static u8 i=0;

    if(Key==0)
    {
        if(i==0)
       {
            if(Key==0)
            {
                 i=1;
                //执行按下函数
            }
        }
    }
  else
  {
      if(i==1)
     {
         //执行释放函数
     }
      i=0;
   }
}
回复

使用道具 举报

地板
ID:879924 发表于 2021-11-16 18:10 | 只看该作者
man1234567 发表于 2021-11-16 14:46
void Key_Scan_Loop(void)
{
    static unsigned char Key_NowState=0;    //按键现在状态

不是static了么?
回复

使用道具 举报

5#
ID:879924 发表于 2021-11-16 18:28 | 只看该作者
18701931930 发表于 2021-11-16 15:29
sbit Key=P1^0;

void Key_scan()

试过不行,按下按键无反应- -
回复

使用道具 举报

6#
ID:95407 发表于 2021-11-16 20:15 | 只看该作者
while(Key_value==1)这里改成
回复

使用道具 举报

7#
ID:95407 发表于 2021-11-16 20:17 | 只看该作者
while(Key_Value==1)改成 while(getKey_Value()==1)试下
回复

使用道具 举报

8#
ID:213173 发表于 2021-11-16 20:41 | 只看该作者
这个示例程序适合楼主要求,要按实际电路重新定义端口。
  1. #include<reg51.h>        

  2. sbit key1=P3^2;
  3. sbit key2=P3^3;
  4. sbit OUT1=P1^0;
  5. sbit OUT2=P1^1;

  6. unsigned char state=0;//按键操作状态

  7. void key_scan()//按键扫描函数
  8. {
  9.         static bit sign1=0,sign2=0;
  10.         static unsigned int count1=0,count2=0;
  11.        
  12.         if(!key1)
  13.         {
  14.                 if(++count1>=500 && sign1==0)//count1/count2消抖依主循环周期取值,估测10~20ms即可
  15.                 {
  16.                         sign1=1;
  17.                         state=1;
  18.                 }
  19.         }
  20.         else
  21.         {
  22.                 if(sign1==1)
  23.                 {
  24.                         sign1=0;
  25.                         state=2;
  26.                 }
  27.                 count1=0;
  28.         }

  29.         if(!key2)
  30.         {
  31.                 if(++count2>=500 && sign2==0)
  32.                 {
  33.                         sign2=1;
  34.                         state=3;
  35.                 }
  36.         }
  37.         else
  38.         {
  39.                 if(sign2)
  40.                 {
  41.                         sign2=0;
  42.                         state=4;
  43.                 }
  44.                 count2=0;
  45.         }
  46. }                       

  47. void key_service()//按键服务程序
  48. {
  49.         switch(state)
  50.         {
  51.                 case 1: OUT1=0; state=0; break;//任务完成state清0
  52.                 case 2: OUT1=1; state=0; break;
  53.                 case 3: OUT2=0; state=0; break;
  54.                 case 4: OUT2=1; state=0; break;
  55.         }
  56. }
  57. void main()
  58. {
  59.         while(1)
  60.         {
  61.                 key_scan();
  62.                 key_service();
  63.         }
  64. }
复制代码

评分

参与人数 1黑币 +30 收起 理由
macboa + 30 很给力!

查看全部评分

回复

使用道具 举报

9#
ID:879924 发表于 2021-11-17 22:48 来自触屏版 | 只看该作者
zxian163 发表于 2021-11-16 20:15
while(Key_value==1)这里改成

试过 不行
回复

使用道具 举报

10#
ID:624769 发表于 2021-11-17 23:25 | 只看该作者
按照: 按下按键执行某函数或语句,松开后停止执行这个函数或语句
这个要求的话,不需要中断,不需要其他任何,只需要:
sbit Key = P3.2;    //假定你的按键是这个

void main()
{
    其他代码
while(1)
{
     其他代码
if(Key)
{
       松开后停止执行这个函数或语句
}
else
{
        按下按键执行某函数或语句,
}
         其他代码
}
}

按这个格式就可以了
回复

使用道具 举报

11#
ID:624769 发表于 2021-11-17 23:27 | 只看该作者
188610329 发表于 2021-11-17 23:25
按照: 按下按键执行某函数或语句,松开后停止执行这个函数或语句
这个要求的话,不需要中断,不需要其他 ...

写错了  不是: sbit Key = P3.2
是  sbit Key = P3^2;  不过,反正是假定,应该没有影响
回复

使用道具 举报

12#
ID:879924 发表于 2021-11-18 00:44 | 只看该作者
188610329 发表于 2021-11-17 23:27
写错了  不是: sbit Key = P3.2
是  sbit Key = P3^2;  不过,反正是假定,应该没有影响

谢谢哈,不过还是不行。要么就的按下去不亮,要么你就是一直亮
回复

使用道具 举报

13#
ID:879924 发表于 2021-11-18 00:48 | 只看该作者
本帖最后由 macboa 于 2021-11-18 01:00 编辑
wulin 发表于 2021-11-16 20:41
这个示例程序适合楼主要求,要按实际电路重新定义端口。

老哥,你这个是相当牛皮了。。。
感谢您!

但是还有一个不解之处。。。
就是我自己写的
  1. main()
  2. {
  3.     if(Key_Value==1)
  4.     {
  5.         LED=0;
  6.     }
  7.     LED=1;
  8. }
复制代码

按道理无论按下没按下,LED=1这一步都会执行啊。为啥这样写,按下之后再抬起,LED还是=0呢?也就是LED=1这一步根本没有执行,新手非常不解。。。还请大神明示!!!

最后一个不解的地方就是,为何我把扫描函数放到定时器中断里,按键就失效了呢?
回复

使用道具 举报

14#
ID:213173 发表于 2021-11-18 06:37 | 只看该作者
macboa 发表于 2021-11-18 00:48
老哥,你这个是相当牛皮了。。。
感谢您!
  1. main()
  2. {
  3.     if(Key_Value==1)
  4.     {
  5.         LED=0;
  6.     }
  7.     LED=1;//此语句结束后跑飞
  8. }


  9. void main()
  10. {
  11.         while(1)
  12.         {//永远约束在{}内
  13.                 if(Key_Value==1)
  14.                 {
  15.                         LED=0;
  16.                 }
  17.                 else LED=1;
  18.         }
  19. }
复制代码


扫描函数放到定时器中断里一样用,count1/count2消抖依中断周期取值,10~20ms即可。
回复

使用道具 举报

15#
ID:123289 发表于 2021-11-18 14:47 | 只看该作者
不要管按键,你能不能写出一个加速的程序。
回复

使用道具 举报

16#
ID:879924 发表于 2021-11-19 11:01 | 只看该作者
wulin 发表于 2021-11-18 06:37
扫描函数放到定时器中断里一样用,count1/count2消抖依中断周期取值,10~20ms即可。

谢谢,已经做到定时器里了。。。可以运行。。。那个LED=1,不执行的,还是不明白。。。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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