单片机Day06---独立按键实验

发布于:2025-04-14 ⋅ 阅读:(14) ⋅ 点赞:(0)

目录

一、原理图: 

二、思路梳理:

三、一些说明:

1.定义独立按键控制脚:

2.使用宏定义独立按键按下的键值:#define KEY1_PRESS    1#define KEY2_PRESS    2#define KEY3_PRESS    3#define KEY4_PRESS    4#define KEY_UNPRESS    0

3.key_scan 函数:

4.按键状态: 

5.按键扫描模式:

6.消抖:

7.key为0:

8.返回值问题:

9.调用key_scan 函数:

四、程序实现:


 

一、原理图: 

二、思路梳理:

1.独立按键控制角

2.LED灯控制角

3.独立按键键值

4.延时函数

5.独立按键扫描函数

6.主函数

三、一些说明:

1.定义独立按键控制脚:

 sbit KEY1=P3^1;
 sbit KEY2=P3^0;
 sbit KEY3=P3^3;
 sbit KEY4=P3^4;

2.使用宏定义独立按键按下的键值:
#define KEY1_PRESS    1
#define KEY2_PRESS    2
#define KEY3_PRESS    3
#define KEY4_PRESS    4
#define KEY_UNPRESS    0

#define KEY1_PRESS 1 :将 KEY1_PRESS 定义为 1 ,表示按键 K1 按下时,程序中用 KEY1_PRESS 这个标识符代表其键值 。当程序检测到 K1 按键被按下,key_scan 函数会返回 KEY1_PRESS ,即返回 1 。

下面会有key_scan 函数。

3.key_scan 函数:

u8 key_scan(u8 mode)
  • mode 是函数的参数,用于控制按键扫描的模式:
    • 当 mode 为 0 时,表示单次扫描按键,即按键按下一次,函数只返回一次键值,直到按键释放后才能再次触发。
    • 当 mode 为 1 时,表示连续扫描按键,即只要按键一直按下,函数会不断返回对应的键值。

 

4.按键状态: 

key 用于记录按键的状态,初始值为 1,表示按键处于未按下状态。一定要分清,key为1就是未按下,所以一开始要设置key=1.

KEY1 == 0 || KEY2 == 0 || KEY3 == 0 || KEY4 == 0 表示检测是否有任意一个按键被按下。在硬件电路中,按键按下时对应的引脚电平通常为低电平(0)。

将 key 置为 0,表示按键已经被按下。

key 是在 key_scan 函数中定义的静态变量(static u8 key = 1;),它的作用是标记当前按键检测的状态。key 的值只有 1 和 0 两种情况:

  • 当 key 为 1 时,意味着当前按键处于未被按下或者已经释放的状态,程序可以开始检测是否有新的按键按下事件。
  • 当 key 为 0 时,表明按键已经被按下,并且还未释放,在这种状态下,程序不会再次对按键按下事件进行检测,以此避免重复触发按键响应。

不论key还是单个按键,都是为0的时候是被按下。key标记当前按键检测的状态,key为1表示可以检测按键状态。

5.按键扫描模式:

连续扫描模式:当 mode 参数为非零值(一般设为 1)时,if(mode) 条件满足,会执行 key = 1;。这意味着不管当前按键状态如何,都会把 key 置为 1,即允许函数再次检测按键按下事件。在这种模式下,只要按键一直被按着,key_scan 函数每次被调用时都会去检查按键状态,一旦检测到按键按下,就会返回相应键值,达成连续扫描的效果。

单次扫描模式:当 mode 参数为 0 时,if(mode) 条件不成立,key 的值不会被强制置为 1。这就保证了只有在按键释放(key 变为 1)之后,再次按下按键才会被检测到。在这种模式下,按键按下一次,函数仅返回一次键值,适用于只需要响应一次按键按下事件的场景,比如开关控制。

笨人理解:

在连续扫描模式下,可以进行长按,得到的结果就是长按想要的。

在单次扫描模式下,进行长按时,只会算一次结果,并不能达到长按的想要的状态。

6.消抖:

在检测到有按键按下后,程序先调用 delay_10us(1000); 进行延时消抖,然后再次检测按键状态,若按键仍然处于按下状态,就判定为有效按键按下事件,并返回对应的键值。

7.key为0:

当检测到有按键按下,并且经过消抖处理确认是有效按下事件之后,将 key 置为 0。在按键释放之前,由于 key 已经是 0if (key == 1 && ...) 这个条件就不会成立,函数不会再次判定按键按下,这样就避免了在按键持续按下的过程中对同一事件进行重复检测。

8.返回值问题:

将 return KEY_UNPRESS; 放在 else if 语句块外面,是为了确保函数在没有检测到有效按键按下事件时,能够有一个明确的默认返回值。

9.调用key_scan 函数:

调用 key_scan 函数进行按键扫描,0 作为参数传递给 key_scan 函数,表示使用单次扫描模式。在单次扫描模式下,按键按下一次,函数只返回一次键值,直到按键释放后才能再次触发。

四、程序实现:

#include <REGX51.H>
 typedef unsigned int u16;
 typedef unsigned char u8;
 sbit KEY1=P3^1;
 sbit KEY2=P3^0;
 sbit KEY3=P3^3;
 sbit KEY4=P3^4;
 sbit LED=P2^0;
 #define KEY1_PRESS 1
#define KEY2_PRESS 2
#define KEY3_PRESS 3
#define KEY4_PRESS 4
#define KEY_UNPRESS 0
void delay_10us(u16 t)
{
while(t--);
}
u8 key_scan(u8 mode)
{
static u8 key=1;
if(mode)key=1;
if (key==1&(KEY1==0||KEY2==0||KEY3==0||KEY4==0)    )
{
delay_10us(1000);
key=0;
if(KEY1==0)
return KEY1_PRESS;
else if(KEY2==0)
return KEY2_PRESS;
else if(KEY3==0)
return KEY3_PRESS;
else if(KEY4==0)
return KEY4_PRESS;
}
else if(KEY1==1&&KEY2==1&&KEY3==1&&KEY4==1)
{
key=1;
}
return KEY_UNPRESS;
}
void main( )
{
u8 key=0;
while(1)
{
  key=key_scan(0);
  if (key==KEY1_PRESS)
  {
  LED=!LED;
  }
  }
  }