找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 84531|回复: 153
收起左侧

状态机按键扫描,看懂了会增长你的功力。。。。

  [复制链接]
ID:69862 发表于 2014-12-14 21:19 | 显示全部楼层 |阅读模式
本帖最后由 xiao_yp2014 于 2016-1-21 14:37 编辑

大家好!我叫肖亚平,从小热爱上了电子技术,读书时阴差阳错的选择了电子这方面的专业,学习电子技术。对于我的理解来说,学校里面学到的技术不是全部实用,但是必须有用,所以一直奋斗在前线。我对学习总结出一句话“压力不是有人努力,而是比你牛X N倍的人依然在努力
说在前面:
              做单片机开发少不了的就是通过按键和单片机交流,按键是单片机交流的一个桥梁,所以状态机按键扫描犹如嵌入式一样的火爆,在网上一搜一大把,一说起按键,学了单片机的人都知道有个叫做“状态机扫描的方法”,这个方法确实比其它的按键方法要好得多,我记得在星期五的一个下午,一个网友叫我帮他调一个程序,他当时说按下按键显示就不显示了,我一想,按键肯定有问题,我打开程序一看,里面居然还有像这样的语句存在“ while(!Key); ”这明显是给自己找麻烦,给CPU挖陷阱嘛,下面分享一个状态机的按键扫描方法,据说这种方法是实时最高的,今天我也是亲自试过,确定如此。


捕获.PNG


程序如下:main.c
  1. /********************************************************************************************
  2. 名    称:状态机按键扫描
  3. 功    能:运用状态机思想,实现按下按键LED点亮,再按一下LED灯熄灭。
  4. 作    者:肖亚平
  5. 创建时间:2014年12月14日
  6. 修改时间:
  7. 备    注:
  8. **************************************************************************************************/
  9. #include<reg52.h>                 //头文件
  10. #include"Key_State.h"         //按键扫描头文件

  11. sbit Led = P0^7;                 //LED灯输出

  12. unsigned char Key_Number = 0; //按键值

  13. /********************************************************************************************
  14. 函数名称:主程序
  15. 功    能:程序执行的入口
  16. 返 回 值:无
  17. 时    间:2014-12-14        
  18. 备    注:
  19. **************************************************************************************************/
  20. void main()
  21. {
  22.    while(1)
  23.    {
  24.        Key_Number = read_key();        //调用按键扫描函数,取得按键值,10MS调用一次,这里我没有计时

  25.            if(Key_Number == 1)                //按键返回值是1
  26.            {
  27.               Led = ~Led;                        //LED灯取反
  28.            }
  29.    }
  30. }
复制代码

Key_State.c
  1. #include<reg52.h>

  2. sbit key_sr1 = P1^6;  // 按键输入口

  3. #define key_state_0        0   //按键的初始状态
  4. #define key_state_1        1   //按键按下的状态
  5. #define key_state_2        2   //按键释放的状态

  6. /********************************************************************************************
  7. 函数名称:按键扫描程序
  8. 功    能:检测按键,并返回按键值
  9. 返 回 值:key_press
  10. 时    间:2014-12-14        
  11. 备    注:
  12. **************************************************************************************************/
  13. unsigned char read_key(void)
  14. {
  15.     static char key_state = 0;     //按键的状态
  16.     unsigned char key_press;       //按键是否被按下
  17.         unsigned char key_return = 0;  //按键返回值
  18.     key_press = key_sr1;         // 读按键I/O电?
  19.    
  20.     switch (key_state)
  21.     {
  22.         case key_state_0:                 // 按键初始态
  23.                 if (!key_press)
  24.                 {
  25.                                 key_state = key_state_1;// 键被按下,状态转换到键确认态
  26.                         }
  27.                         break;
  28.                                 
  29.         case key_state_1:                   // 按键确认态
  30.             if (!key_press)
  31.             {
  32.                 key_return = 1;         // 按键仍按下,按键确认输出为“1”
  33.                 key_state = key_state_2;// 状态转换到键释放态
  34.             }
  35.             else
  36.             {
  37.                                 key_state = key_state_0; // 按键已抬起,转换到按键初始态
  38.                         }
  39.             break;
  40.                                 
  41.         case key_state_2:
  42.             if (key_press)
  43.                         {
  44.                             key_state = key_state_0;//按键已释放,转换到按键初始态
  45.             }
  46.             break;
  47.    }
  48. return key_return;                            //返回按键值
  49. }
复制代码

Key_State.h
  1. #ifndef __Key_State_H__
  2. #define __Key_State_H__

  3. unsigned char read_key(void);

  4. #endif
复制代码


Key_State.zip (34.43 KB, 下载次数: 1414)   

程序在这里下载


低调,低调才是最牛逼的炫耀。。。。。。
由于水平能力有限,纰漏之处,不望各位读者指出。。。。。。




评分

参与人数 4黑币 +51 收起 理由
陈润源home + 10 谢谢肖哥,师弟又学到东西了
botgs + 5 赞一个!
goty2000 + 1 多谢楼主,这次可以彻底摆脱while(KEY==0);.
暗光 + 35 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:149642 发表于 2024-7-2 08:00 | 显示全部楼层
这个程序大了后就容易按键失灵。
回复

使用道具 举报

ID:713651 发表于 2024-7-1 08:21 | 显示全部楼层
最简单的按键状态机
回复

使用道具 举报

ID:1079930 发表于 2024-6-28 13:34 | 显示全部楼层
大佬真牛哇,学习了
回复

使用道具 举报

ID:1108581 发表于 2024-3-2 20:32 | 显示全部楼层
正好最近一直为这个问题烦忧,多谢分享。回去慢慢研究研究
回复

使用道具 举报

ID:409251 发表于 2024-2-29 15:57 | 显示全部楼层
按键是如何消抖的?
回复

使用道具 举报

ID:195666 发表于 2023-11-6 16:18 | 显示全部楼层
怎么加防抖呢
回复

使用道具 举报

ID:59300 发表于 2023-9-11 09:33 | 显示全部楼层
对我正在学习状态机非常有帮助,谢谢分享
回复

使用道具 举报

ID:137736 发表于 2022-7-24 20:41 | 显示全部楼层
很好,做成头文件了么?
回复

使用道具 举报

ID:336367 发表于 2022-7-1 20:15 | 显示全部楼层
你这个状态机用的,只能说理想状态吧。按键防抖呢,你打算怎么设计?而且状态机要有时序约束的。
回复

使用道具 举报

ID:228701 发表于 2022-6-29 10:28 | 显示全部楼层
e792b16db5dc14d6dc5a7191700a8710.png 哈哈,说的就是我,感谢分享
回复

使用道具 举报

ID:814956 发表于 2022-5-30 09:55 | 显示全部楼层
细细研究一下,妙呀
回复

使用道具 举报

ID:624685 发表于 2022-5-26 21:18 | 显示全部楼层
学习51编程,思路很重要,谢谢
回复

使用道具 举报

ID:398219 发表于 2022-5-26 20:46 | 显示全部楼层
谢谢楼主分享,对于初学者来说一直都用的while
回复

使用道具 举报

ID:1029395 发表于 2022-5-25 02:25 | 显示全部楼层
正在找状态按键写法,是我急需的,感谢楼主的经验分享。我已经卡在这里5天了
回复

使用道具 举报

ID:489048 发表于 2022-2-17 19:10 | 显示全部楼层
小白有个问题:
1. 假设默认是高电平,第一次进入函数,key_press为1. 在按键按下变成0的时候切换到状态1.
2. 然后第二次进入函数,首先读IO口的值,此时key_press成为0了,如果想检测按键是否还是按下,为何要用(!key_press)呢?感觉应该是(key_press)。
3. 同理,状态2的时候应该是(!key_press)...
回复

使用道具 举报

ID:449522 发表于 2021-4-5 09:38 | 显示全部楼层
在学习状态机键盘,谢谢
回复

使用道具 举报

ID:106422 发表于 2021-1-13 11:35 | 显示全部楼层
小白表示有点懵,先下载学习,谢谢!
回复

使用道具 举报

ID:276761 发表于 2021-1-9 23:53 | 显示全部楼层
又学到了知识,谢谢
回复

使用道具 举报

ID:69115 发表于 2021-1-8 19:13 | 显示全部楼层
在定时中断里完成按键检测,才是实用的按键程序.
回复

使用道具 举报

ID:694424 发表于 2021-1-6 21:17 | 显示全部楼层
来学习了,谢谢楼主小哥
回复

使用道具 举报

ID:857685 发表于 2020-12-28 19:27 | 显示全部楼层
大佬就是大佬,学到了
回复

使用道具 举报

ID:702127 发表于 2020-12-28 15:52 | 显示全部楼层
不错,学习了,今天刚刚知道有状态机的概念,楼主的代码能够对按键未按、按下和抬起进行独立的操作!
回复

使用道具 举报

ID:594086 发表于 2020-12-21 14:12 | 显示全部楼层
本帖最后由 jiaojunh 于 2020-12-21 14:15 编辑

对于我来是都是牛x的,自学快两年了,在各论坛搬砖,谢谢大神的每一次分享,学到了不少东西,偶然一次发现自己写延时去抖的按键程序用在一个比较大的程序里边时,不堪入目啊,不稳定。
回复

使用道具 举报

ID:690363 发表于 2020-5-20 14:42 | 显示全部楼层
一看是版主,想必很实用,谢谢,下来研究研究
回复

使用道具 举报

ID:501195 发表于 2020-5-19 09:05 | 显示全部楼层
不错,很好的资料
回复

使用道具 举报

ID:465279 发表于 2020-3-19 10:22 | 显示全部楼层
学习学习一下,谢谢楼主
回复

使用道具 举报

ID:46228 发表于 2020-2-14 10:01 来自触屏版 | 显示全部楼层
真的真佩服这样的又清晰又有中文注释
回复

使用道具 举报

ID:600789 发表于 2019-9-3 11:21 | 显示全部楼层
Strongest丶星空 发表于 2019-5-17 18:46
学到了不同按键扫描的方法,我是单片机的初学者,我自创了一种按键方式楼主可以看看,(PS:这不是装逼,只 ...

兄弟,你这个连消抖都没,而且一旦有键按下,CPU就一直被while(1)这条语句占用,别的语句都执行不了了。还是多学多练吧
回复

使用道具 举报

ID:594633 发表于 2019-8-6 10:01 来自触屏版 | 显示全部楼层
感谢楼主分享,学习了
回复

使用道具 举报

ID:419500 发表于 2019-8-5 11:29 | 显示全部楼层
下载学习
回复

使用道具 举报

ID:56665 发表于 2019-6-16 10:51 | 显示全部楼层
没有看到消抖动作,是不是要放在定时中断中去完成的。
回复

使用道具 举报

ID:552614 发表于 2019-6-16 07:29 | 显示全部楼层
刚学单片机,还不知道状态机有什么用,学习一下,谢谢楼主分享
回复

使用道具 举报

ID:495036 发表于 2019-6-14 21:19 | 显示全部楼层
没黑币了,好想收藏
回复

使用道具 举报

ID:561683 发表于 2019-6-13 12:21 | 显示全部楼层
新手,学习了
回复

使用道具 举报

ID:540753 发表于 2019-5-23 16:05 | 显示全部楼层
学习学习,多谢LZ
回复

使用道具 举报

ID:502682 发表于 2019-5-17 18:46 | 显示全部楼层
学到了不同按键扫描的方法,我是单片机的初学者,我自创了一种按键方式楼主可以看看,(PS:这不是装逼,只是让楼主看看有多大局限)if(key==0)
                {
                        while(1)
                        {
                                if(key==1)
                                {
                                                return  k;
                                }
                        }
                }
回复

使用道具 举报

ID:502682 发表于 2019-5-17 18:41 | 显示全部楼层
学到了不同的按键扫描我自创了一种按键扫描不过感觉局限可大楼主可以看看
回复

使用道具 举报

ID:540753 发表于 2019-5-17 15:40 | 显示全部楼层
下来学习学习,先顶一个
回复

使用道具 举报

ID:520563 发表于 2019-4-25 09:16 | 显示全部楼层
听说过状态机按键很好,一直还没学会,谢谢楼主讲解
回复

使用道具 举报

ID:20672 发表于 2019-4-2 09:25 | 显示全部楼层
谢谢分享,再次看了,还是有收获
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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