找回密码
 立即注册

QQ登录

只需一步,快速开始

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

图中的4个按键,只有3个IO,如何实现按键检测?

  [复制链接]
跳转到指定楼层
楼主
      看到别人的电路图,这4个按键怎么扫描检测?求大神附上代码谢谢。

bfbdc765-fd98-4fd4-89fd-a12ee5f9590a.png (32.33 KB, 下载次数: 0)

bfbdc765-fd98-4fd4-89fd-a12ee5f9590a.png
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:1133081 发表于 2025-1-11 16:53 | 只看该作者
这只是读键值的基本逻辑关系,实用代码需要补充完善。
char key_scan()
{
        B4=1;B3=1;B2=1;
        if(B2==0)return 1;
        else if(B3==0)return 2;
        B4=0;
        if(B2==0)return 3;
        else if(B3==0)return 4;
        else return 0;
}
回复

使用道具 举报

板凳
ID:1041695 发表于 2025-1-11 21:07 | 只看该作者
你这电路有问题吧?B2、B3如果不接上拉电阻,按键相当于直接短路路了。
回复

使用道具 举报

地板
ID:1109793 发表于 2025-1-12 07:34 | 只看该作者
WL0123 发表于 2025-1-11 16:53
这只是读键值的基本逻辑关系,实用代码需要补充完善。
char key_scan()
{

很明显这个不对,说下怎么完善吧
回复

使用道具 举报

5#
ID:384109 发表于 2025-1-12 09:21 | 只看该作者
xiaobendan001 发表于 2025-1-12 07:34
很明显这个不对,说下怎么完善吧

先看懂电路和代码再说吧
回复

使用道具 举报

6#
ID:1109793 发表于 2025-1-12 14:20 | 只看该作者
人中狼 发表于 2025-1-12 09:21
先看懂电路和代码再说吧

B4=1时,按S1我能理解,B4=0时,我按的仍然是S1,你试试这个代码返回的是几?
回复

使用道具 举报

7#
ID:384109 发表于 2025-1-12 16:28 | 只看该作者
xiaobendan001 发表于 2025-1-12 14:20
B4=1时,按S1我能理解,B4=0时,我按的仍然是S1,你试试这个代码返回的是几?

所以原代码提供者说明了实用代码需要补充完善啊,先理解一下电路和扫描按键如何编程吧
回复

使用道具 举报

8#
ID:1034262 发表于 2025-1-12 20:04 | 只看该作者
B4=1,检测B2、B3是否有键按下,
有则处理按键。
没有,则B4=0,检测B2、B3是否有键按下。
回复

使用道具 举报

9#
ID:1133081 发表于 2025-1-12 20:34 | 只看该作者
xiaobendan001 发表于 2025-1-12 14:20
B4=1时,按S1我能理解,B4=0时,我按的仍然是S1,你试试这个代码返回的是几?

如果你按着S1不放,if(B2==0)return 1;,程序已经返回,根本运行不到下面代码,只有S1和S2都没有按下才能运行到B4=0;,注意关键字return,这是基础知识。
回复

使用道具 举报

10#
ID:996773 发表于 2025-1-13 08:58 | 只看该作者
本人不才,问一下不按任何键,B2,B3读出来数据是1还是0?
回复

使用道具 举报

11#
ID:92781 发表于 2025-1-13 10:06 | 只看该作者
沙发的程序通过改变b4判断按键,符合电路图作者的思路,我下面还有另外一种思路,就是去掉电阻,利用改变b2和b3电平,也可以判断,而且误判可能性更小。
回复

使用道具 举报

12#
ID:92781 发表于 2025-1-13 10:17 | 只看该作者
先b2、b3、b4都置1,此时s3、s4无效,可以读取s1和s2,
再b3置0,b2、b4置1,此时s2、s3无效,可以读取s1和s4,
再b2置0、b3、b4置1,此时s1、s4无效,可以读取s3和s2
以上缺点是,同时按下两个以上按钮,会导致误判,但是只要不同时按下两个以上,就可以使用
回复

使用道具 举报

13#
ID:92781 发表于 2025-1-13 10:36 | 只看该作者
本帖最后由 jjy1039 于 2025-1-15 10:10 编辑

b2=1;b3=1;b4=1;
if(b2==0){   }//S1
if(b3==0){   }//S2

b2=1;b3=0;b4=1;
if(b2==0){   }//S1
if(b4==0){   }//S4

b2=0;b3=1;b4=1;
if(b3==0){   }//S2
if(b4==0){   }//S3
回复

使用道具 举报

14#
ID:23640 发表于 2025-1-13 14:13 | 只看该作者
IO口不够用,还不如用ADC读键值
回复

使用道具 举报

15#
ID:332444 发表于 2025-1-13 15:35 | 只看该作者
可以进一步节省1个IO口,用2个IO口就能实现4个按键检测,2个电阻接地,2个电阻接电源,都当独立按键处理.
回复

使用道具 举报

16#
ID:161164 发表于 2025-1-13 16:15 | 只看该作者
xianfajushi 发表于 2025-1-13 15:35
可以进一步节省1个IO口,用2个IO口就能实现4个按键检测,2个电阻接地,2个电阻接电源,都当独立按键处理.

请问接电源的按键如何判断?
回复

使用道具 举报

17#
ID:380037 发表于 2025-1-13 21:13 | 只看该作者
WL0123 发表于 2025-1-12 20:34
如果你按着S1不放,if(B2==0)return 1;,程序已经返回,根本运行不到下面代码,只有S1和S2都没有按下才能 ...

如果恰巧在 if(B2==0)return 1;语句之后才按下S1呢?又或者恰巧在else if(B3==0)return 2;语句后才按下S2呢?会不会出错?
回复

使用道具 举报

18#
ID:1109793 发表于 2025-1-14 13:09 | 只看该作者
wlefa 发表于 2025-1-13 21:13
如果恰巧在 if(B2==0)return 1;语句之后才按下S1呢?又或者恰巧在else if(B3==0)return 2;语句后才按下S2 ...

大概是概率低到一定程度就忽略了。
回复

使用道具 举报

19#
ID:1133081 发表于 2025-1-15 06:03 | 只看该作者
wlefa 发表于 2025-1-13 21:13
如果恰巧在 if(B2==0)return 1;语句之后才按下S1呢?又或者恰巧在else if(B3==0)return 2;语句后才按下S2 ...

你说的“恰巧”有可能存在,也就是说上述代码确有漏洞。应该加一个限制条件,有任何按键按下才开始判读,规避“恰巧”。
char key_scan()
{
        B4=0;B3=1;B2=1;//B4初始为0
        if(!B2 || !B3)//有任何按键按下条件成立
        {
                B4=1;//识别S1、S2
                if(!B2)return 1;
                if(!B3)return 2;
                B4=0;//识别S3、S4
                if(!B2)return 3;
                if(!B3)return 4;
        }
        return 0;
}
回复

使用道具 举报

20#
ID:218360 发表于 2025-2-7 13:47 | 只看该作者
按照你们写的程序,实际测试按键无效。能写一个完整的程序吗?感谢,最好是51单片机,在学习,电路是没有问题,是我们之前工程师做到一个遥控器。
回复

使用道具 举报

21#
ID:332444 发表于 2025-2-8 07:48 | 只看该作者
lkc8210 发表于 2025-1-13 16:15
请问接电源的按键如何判断?

可参看我的博文https://blog.csdn.net/xianfajushi/article/details/106518315

51hei.gif (791.92 KB, 下载次数: 0)

51hei.gif
回复

使用道具 举报

22#
ID:1133081 发表于 2025-2-8 08:33 | 只看该作者
打杂的 发表于 2025-2-7 13:47
按照你们写的程序,实际测试按键无效。能写一个完整的程序吗?感谢,最好是51单片机,在学习,电路是没有问 ...

楼主搞了快1个月还没有搞定?给你写个测试程序,肯定没有问题。如果不稳定把你电路中R5省略或改为1K
  1. #include <reg52.h>
  2. #include <intrins.h>

  3. sbit B2=P3^0;
  4. sbit B3=P3^1;
  5. sbit B4=P3^2;

  6. #define uint unsigned int
  7. #define uchar unsigned char

  8. void Delay_ms(uint t)//@12MHz
  9. {
  10.         uint i,j;
  11.         for(i=t;i>0;i--)
  12.                 for(j=120;j>0;j--);
  13. }

  14. char key_scan()
  15. {
  16.         static uint count=0;//消抖计数
  17.         static bit sign=0;  //按键状态标志
  18.         B4=0;B3=1;B2=1;//B4初始为0
  19.         if(!B2 || !B3)//有任何按键按下条件成立
  20.         {
  21.                 if(++count>=20 && sign==0)//约20ms消抖
  22.                 {
  23.                         sign=1;
  24.                         B4=1;//识别S1、S2
  25.                         _nop_();//小延时
  26.                         if(!B2)return 1;
  27.                         if(!B3)return 2;
  28.                         B4=0;//识别S3、S4
  29.                         _nop_();//小延时
  30.                         if(!B2)return 3;
  31.                         if(!B3)return 4;
  32.                 }
  33.         }
  34.         else //松手
  35.         {
  36.                 count=0;//消抖计数清0
  37.                 sign=0;//按键状态标志清0               
  38.                 return 0;//返回0
  39.         }
  40. }

  41. void key_service()
  42. {
  43.         uchar i;
  44.         i=key_scan();
  45.         switch(i)
  46.         {//用P1低4位验证键值
  47.                 case 1: P1=0xfe; i=0; break;
  48.                 case 2: P1=0xfd; i=0; break;
  49.                 case 3: P1=0xfb; i=0; break;
  50.                 case 4: P1=0xf7; i=0; break;
  51.         }
  52. }

  53. void main()
  54. {
  55.         while (1)
  56.         {
  57.                 key_service();
  58.                 Delay_ms(1);//控制主循环周期
  59.         }
  60. }
复制代码
回复

使用道具 举报

23#
ID:332444 发表于 2025-2-10 21:57 | 只看该作者
lkc8210 发表于 2025-1-13 16:15
请问接电源的按键如何判断?

除了P0外的都可用来制作1个IO检测2个按键用,特别适合闲散IO,1个按键接地1个按键接电源,检测接地按键时IO先赋值高电平再检测是否低电平按下,同样道理检测接电源按键先赋值低电平再检测是否高电平按下即可。
回复

使用道具 举报

24#
ID:654797 发表于 2025-2-11 07:03 | 只看该作者
lei848200 发表于 2025-1-11 21:07
你这电路有问题吧?B2、B3如果不接上拉电阻,按键相当于直接短路路了。

单片机的引脚又不是不能短路的,人家只检测低电平,短路没问题呀
回复

使用道具 举报

25#
ID:1137088 发表于 2025-2-11 08:31 | 只看该作者
电路图可以改一下
回复

使用道具 举报

26#
ID:60370 发表于 2025-2-11 16:19 | 只看该作者
电路没问题,就看怎么写了,I/O口需要不断变换实时检测判断,B4高低切换,配合B2、B3设置开漏(或高阻抗输入)和标准I/O口设置切换来检测判断
回复

使用道具 举报

27#
ID:161164 发表于 2025-2-12 10:06 | 只看该作者
xianfajushi 发表于 2025-2-10 21:57
除了P0外的都可用来制作1个IO检测2个按键用,特别适合闲散IO,1个按键接地1个按键接电源,检测接地按键时 ...

?
“先赋值低电平再检测是否高”
先赋值低电平不就打开了内置对地的MOS管?
如果再按接电源正的按键不就短路?
回复

使用道具 举报

28#
ID:161164 发表于 2025-2-12 10:21 | 只看该作者
wlefa 发表于 2025-1-13 21:13
如果恰巧在 if(B2==0)return 1;语句之后才按下S1呢?又或者恰巧在else if(B3==0)return 2;语句后才按下S2 ...

要加滤波消抖代码

回复

使用道具 举报

29#
ID:218360 发表于 2025-2-12 15:31 | 只看该作者
WL0123 发表于 2025-2-8 08:33
楼主搞了快1个月还没有搞定?给你写个测试程序,肯定没有问题。如果不稳定把你电路中R5省略或改为1K

使用你们的代码,编译通不过,报错not every exit path returns a value
回复

使用道具 举报

30#
ID:332444 发表于 2025-2-13 10:46 | 只看该作者
lkc8210 发表于 2025-2-12 10:06
?
“先赋值低电平再检测是否高”
先赋值低电平不就打开了内置对地的MOS管?

昨天查阅了IO内部电路,确实有些冒险,只在仿真中试用过,且仿真图有黄颜色的点,低压极短时间内仿真没报错,实际硬件没用过,请慎之。
回复

使用道具 举报

31#
ID:218360 发表于 2025-2-18 16:40 | 只看该作者
我说咋编译不过,大神故意留BUG让我找?

51hei截图_20250218163858.png (186.16 KB, 下载次数: 0)

51hei截图_20250218163858.png
回复

使用道具 举报

32#
ID:624769 发表于 2025-2-19 10:24 | 只看该作者
lkc8210 发表于 2025-1-13 16:15
请问接电源的按键如何判断?

虽然可以,但是,对单片机的要求比较高,需要有下拉电阻控制器的单片机, 比如 STC8051U 系列,STC32系列等等。
IO设置为高祖,
1) 开内部下拉,关内部上拉,如果 IO = 1, 则: 接VCC的按键被按下。
2) 关内部下拉,开内部上拉,如果 IO = 0, 则: 接GND的按键被按下。
以上皆否则没有按键被按下。

然后,还有另一种双按键方案,需要单片机IO 支持强推挽输出。
IO出来,接一个电阻,然后对地电容,然后,接两个按键,按键A直接接地,按键B接一个等值电阻后接地。
IO强推挽,先充电5us, 然后,切换高阻,检测IO, IO 为 0, 则 按键 A 按下。 否则 5us 后再检测,IO 为 0 则按键B 按下, 反之 没有按键 按下。
如 判定为 按键B 按下,需要  再 充电一次复验, 防止是 在第二次检测时,实际按键A 按下。

回复

使用道具 举报

33#
ID:218360 发表于 2025-2-20 09:26 | 只看该作者
这个是我的电路图,我实测还是不能实现按键按下指示灯闪一下。目前可以实现S1和S2,S3和S4控制不了,一直为低电平

3853AAD458D49EA1346E36FE8830A633.png (91.82 KB, 下载次数: 0)

3853AAD458D49EA1346E36FE8830A633.png
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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