找回密码
 立即注册

QQ登录

只需一步,快速开始

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

关于单片机独立按键程序调试

[复制链接]
跳转到指定楼层
楼主
而我改的就很多问题,按一下可能亮可能灭。
   明明也加了,消抖,如果加while(!KEY1)  的话,就没什么问题了,这个的思路就是按键没有释放,就一直等,释放后再做一个消抖即可。

   问题是普中的程序也没有等待按键弹起的动作呀,而且弹起来后面的消抖也没有处理,但是但是但是他们的程序就是特别好用。

单片机源程序如下:
  1. /**************************************************************************************
  2. 实验名称:独立按键实验
  3. 接线说明:        
  4. 实验现象:下载程序后,按下“独立按键”模块中K1键,控制D1指示灯亮灭
  5. 注意事项:                                                                                                                                                                  
  6. ***************************************************************************************/
  7. #include "reg52.h"

  8. typedef unsigned int u16;        //对系统默认数据类型进行重定义
  9. typedef unsigned char u8;

  10. //定义独立按键控制脚
  11. sbit KEY1=P3^1;
  12. sbit KEY2=P3^0;
  13. sbit KEY3=P3^2;
  14. sbit KEY4=P3^3;

  15. //定义LED1控制脚
  16. sbit LED1=P2^0;
  17. sbit LED2=P2^1;
  18. sbit LED3=P2^2;
  19. sbit LED4=P2^3;

  20. //使用宏定义独立按键按下的键值
  21. #define KEY1_PRESS        1
  22. #define KEY2_PRESS        2
  23. #define KEY3_PRESS        3
  24. #define KEY4_PRESS        4
  25. #define KEY_UNPRESS        0        

  26. /*******************************************************************************
  27. * 函 数 名       : delay_10us
  28. * 函数功能                 : 延时函数,ten_us=1时,大约延时10us
  29. * 输    入       : ten_us
  30. * 输    出             : 无
  31. *******************************************************************************/
  32. void delay_10us(u16 ten_us)
  33. {
  34.         while(ten_us--);        
  35. }

  36. /*******************************************************************************
  37. * 函 数 名       : key_scan
  38. * 函数功能                 : 检测独立按键是否按下,按下则返回对应键值
  39. * 输    入       : mode=0:单次扫描按键
  40.                                            mode=1:连续扫描按键
  41. * 输    出             : KEY1_PRESS:K1按下
  42.                                    KEY2_PRESS:K2按下
  43.                                    KEY3_PRESS:K3按下
  44.                                    KEY4_PRESS:K4按下
  45.                                    KEY_UNPRESS:未有按键按下
  46. 假设我们传的参是1,然后我的手按着按键不松开,
  47. 然后程序一直重复进这个函数,是不是每次都进if的判断,
  48. 是不是每次进都会返回那个键值**********
  49. 假设我们传的参是0,然后我的手按着按键不松开,
  50. 但是程序即使重复进这个函数,是不是每次都进不去if的判断,
  51. 是不是就只会返回一次键值*************************
  52. *******************************************************************************/
  53. u8 key_scan(u8 mode)

  54. {
  55.         static u8 key=1;

  56.         if(mode)key=1;//连续扫描按键
  57.         if(key==1&&(KEY1==0||KEY2==0||KEY3==0||KEY4==0))//任意按键按下
  58.         {
  59.                 delay_10us(1000);//消抖
  60.                 key=0;  //
  61.                 if(KEY1==0)
  62.                         return KEY1_PRESS;
  63.                 else if(KEY2==0)
  64.                         return KEY2_PRESS;
  65.                 else if(KEY3==0)
  66.                         return KEY3_PRESS;
  67.                 else if(KEY4==0)
  68.                         return KEY4_PRESS;        
  69.         }
  70.         else if(KEY1==1&&KEY2==1&&KEY3==1&&KEY4==1)        //无按键按下
  71.         {
  72.                 key=1;                        
  73.         }
  74.         return KEY_UNPRESS;               
  75. }
  76. /*******************************************************************************
  77. * 函 数 名       : main
  78. * 函数功能                 : 主函数
  79. * 输    入       : 无
  80. * 输    出             : 无
  81. *******************************************************************************/
  82. void main()
  83. {        
  84.         u8 key=0;

  85.         while(1)
  86.         {
  87.                    key=key_scan(0);
  88.                 if(key==KEY1_PRESS)//检测按键K1是否按下
  89.                         LED1=!LED1;//LED1状态翻转        
  90.                 if(key==KEY2_PRESS)
  91.                         LED2=!LED2;
  92.                 if(key==KEY3_PRESS)
  93.                         LED3=!LED3;
  94.                 if(key==KEY4_PRESS)
  95.                         LED4=!LED4;
  96.         }               
  97. }
复制代码
为什么这个程序就可以呢?

  1. /**************************************************************************************

  2. 实验名称:独立按键实验
  3. 接线说明:        
  4. 实验现象:下载程序后,按下“独立按键”模块中K1键,控制D1指示灯亮灭
  5. 注意事项:                                                                                                                                                                  
  6. ***************************************************************************************/
  7. #include "reg52.h"

  8. typedef unsigned int u16;        //对系统默认数据类型进行重定义
  9. typedef unsigned char u8;

  10. //定义独立按键控制脚
  11. sbit KEY1=P3^1;
  12. sbit KEY2=P3^0;
  13. sbit KEY3=P3^2;
  14. sbit KEY4=P3^3;

  15. //定义LED1控制脚
  16. sbit LED1=P2^0;

  17. //使用宏定义独立按键按下的键值
  18. #define KEY1_PRESS        1
  19. #define KEY2_PRESS        2
  20. #define KEY3_PRESS        3
  21. #define KEY4_PRESS        4
  22. #define KEY_UNPRESS        0        

  23. /*******************************************************************************
  24. * 函 数 名       : delay_10us
  25. * 函数功能                 : 延时函数,ten_us=1时,大约延时10us
  26. * 输    入       : ten_us
  27. * 输    出             : 无
  28. *******************************************************************************/
  29. void delay_10us(u16 ten_us)
  30. {
  31.         while(ten_us--);        
  32. }

  33. /*******************************************************************************
  34. * 函 数 名       : key_scan
  35. * 函数功能                 : 检测独立按键是否按下,按下则返回对应键值
  36. * 输    入       : mode=0:单次扫描按键
  37.                                            mode=1:连续扫描按键
  38. * 输    出             : KEY1_PRESS:K1按下
  39.                                    KEY2_PRESS:K2按下
  40.                                    KEY3_PRESS:K3按下
  41.                                    KEY4_PRESS:K4按下
  42.                                    KEY_UNPRESS:未有按键按下
  43. *******************************************************************************/
  44. u8 key_scan(void)

  45. {

  46.         if(KEY1==0||KEY2==0||KEY3==0||KEY4==0)//任意按键按下
  47.         {
  48.                 delay_10us(1000);//消抖
  49.                 if(KEY1==0)
  50.                         return KEY1_PRESS;
  51.                 else if(KEY2==0)
  52.                         return KEY2_PRESS;
  53.                 else if(KEY3==0)
  54.                         return KEY3_PRESS;
  55.                 else if(KEY4==0)
  56.                         return KEY4_PRESS;        
  57. //                else
  58. //                        return KEY_UNPRESS;
  59.         }
  60. //        else
  61.           return KEY_UNPRESS;               
  62. }
  63. /*******************************************************************************
  64. * 函 数 名       : main
  65. * 函数功能                 : 主函数
  66. * 输    入       : 无
  67. * 输    出             : 无
  68. *******************************************************************************/
  69. void main()
  70. {        
  71.         u8 key=0;

  72.         while(1)
  73.         {
  74.                 if(KEY1==0||KEY2==0||KEY3==0||KEY4==0)//任意按键按下
  75.                 {
  76.                         key=key_scan();
  77.                   if(key==KEY1_PRESS)//检测按键K1是否按下
  78.                         LED1=!LED1;//LED1状态翻转
  79.                         delay_10us(1000);//消抖
  80.     }                        
  81.         }               
  82. }
复制代码
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:275826 发表于 2023-12-20 17:47 | 只看该作者
关键的东西被你改没了呀
回复

使用道具 举报

板凳
ID:161164 发表于 2023-12-20 22:57 | 只看该作者
重点

回复

使用道具 举报

地板
ID:1064915 发表于 2023-12-21 08:48 | 只看该作者

具体说明一下,错误原因
回复

使用道具 举报

5#
ID:161164 发表于 2023-12-21 09:02 | 只看该作者
joyb 发表于 2023-12-21 08:48
具体说明一下,错误原因

例程用了一个变量来记录按键情况
并用来判断
按过一次就不再进入
直到没键按下
回复

使用道具 举报

6#
ID:1064915 发表于 2023-12-21 10:27 | 只看该作者
lkc8210 发表于 2023-12-21 09:02
例程用了一个变量来记录按键情况
并用来判断
按过一次就不再进入

暂时没有理解
这两个程序用普中学习板试验了,都能用,没有出问题
回复

使用道具 举报

7#
ID:1091094 发表于 2023-12-21 10:54 | 只看该作者
tyrl800 发表于 2023-12-20 17:47
关键的东西被你改没了呀

是的  后来我又仔细看了  原来ELSE if部分起到的作用,还有等待按键弹起来的作用,按键不弹起就不会进入else if ,就不会再次执行key=1。
回复

使用道具 举报

8#
ID:1091094 发表于 2023-12-21 11:01 | 只看该作者
lkc8210 发表于 2023-12-21 09:02
例程用了一个变量来记录按键情况
并用来判断
按过一次就不再进入

是的  理解得透彻,我理解了,但是没有你这么透彻
回复

使用道具 举报

9#
ID:1091094 发表于 2023-12-21 11:04 | 只看该作者
joyb 发表于 2023-12-21 10:27
暂时没有理解
这两个程序用普中学习板试验了,都能用,没有出问题

怎么可能,那你按久一点试一下,一直按着肯定会功能错乱的,他会不停地进入按键扫描程序,导致LED的状态会不断翻转的
回复

使用道具 举报

10#
ID:1091094 发表于 2023-12-21 11:09 | 只看该作者
tyrl800 发表于 2023-12-20 17:47
关键的东西被你改没了呀

是的  理解得不透彻的缘故
回复

使用道具 举报

11#
ID:517951 发表于 2023-12-23 07:54 | 只看该作者
delay_10us(1000);//消抖 这种延时消抖方法要改进, 这个延时过程中单片机可以跑几千几万条指令了.
回复

使用道具 举报

12#
ID:1101997 发表于 2023-12-23 14:01 | 只看该作者
一般来说,这种按键处理程序是学生做的,在系统中,像楼上说的那样不能死等,毕竟系统中不仅仅就一个任务,第二要做到按键扫描和按键读取分离,一个夸张一点的例子,今天扫描到的按键,明天去使用也不应该有丢失或者重复的问题,也就是要做到不同模块之间解耦合。
有的人其实没学过几天系统,也没写过几行程序,就能断言别人的程序如何如何,远离他们。
多看看高手程序,读读数据结构和软件工程。
回复

使用道具 举报

13#
ID:1091094 发表于 2023-12-23 17:19 | 只看该作者
rayin 发表于 2023-12-23 07:54
delay_10us(1000);//消抖 这种延时消抖方法要改进, 这个延时过程中单片机可以跑几千几万条指令了.

这还算好了,我的是
  1. if(key==0)
  2. {
  3.   delay_10us(1000);
  4.   if(key==0)
  5.     {
  6.        //执行需要的操作
  7.      }

  8. 真正的一直在死等。

  9. 如果改进的话,思路是什么,可以说说吗?
  10.    while(key==0)
  11.       ;
  12.    delay_10us(1000);
  13. }
复制代码
回复

使用道具 举报

14#
ID:1091094 发表于 2023-12-23 17:25 | 只看该作者
nearsea 发表于 2023-12-23 14:01
一般来说,这种按键处理程序是学生做的,在系统中,像楼上说的那样不能死等,毕竟系统中不仅仅就一个任务, ...

你说的应该是系统的思维,现在还没接触过系统(RTOS 什么实时系统之类的),
   但是我感觉:如果在按键扫描程序后面还有一些程序,如果程序的时间过长的话,那么你按键的时候,单片机没有在执行这个按键扫描程序的话,那么你这个按键就无效了,相当于BUG了吧
回复

使用道具 举报

15#
ID:1107339 发表于 2023-12-31 21:35 | 只看该作者
编程时应多考虑任务之间的协同。
回复

使用道具 举报

16#
ID:1107339 发表于 2024-1-1 15:53 | 只看该作者
key按下后,直接等待x毫秒,然后再读是否有数据即可,等待时间要通过测试来进行确定,一般150ms可以。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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