【普中51单片机开发攻略--基于普中-2&普中-3&普中-4】-- 第 13 章 独立按键实验

(1)实验平台:普中51单片机开发板-A2&A3&A4


前几章介绍的都是 IO 口输出的使用, 这一章我们通过独立按键实验来介绍IO 口作为输入的使用。 开发板上板载 4 个独立按键。 本章所要实现的功能是:通过开发板上的独立按键 K1 控制 D1 指示灯亮灭。 学习本章可以参考前面的实验章节内容。 本章分为如下几部分内容:

[13.1 按键介绍](#13.1 按键介绍)

[13.2 硬件设计](#13.2 硬件设计)

[13.3 软件设计](#13.3 软件设计)

[13.4 实验现象](#13.4 实验现象)


13.1 按键介绍

按键是一种电子开关, 使用时轻轻按开关按钮就可使开关接通, 当松开手时,开关断开。 开发板上使用的按键及内部简易图如下图所示:

按键管脚两端距离长的表示默认是导通状态, 距离短的默认是断开状态, 如果按键按下, 初始导通状态变为断开, 初始断开状态变为导通。

通常的按键所用开关为机械弹性开关,当机械触点断开、 闭合时, 电压信号如下图所示:

由于机械点的弹性作用, 按键开关在闭合时不会马上稳定的接通, 在断开时也不会一下子断开, 因而在闭合和断开的瞬间均伴随着一连串的抖动。 抖动时间的长短由按键的机械特性决定的, 一般为 5ms 到 10ms。 按键稳定闭合时间的长短则由操作人员的按键动作决定的, 一般为零点几秒至数秒。 按键抖动会引起按键被误读多次。 为了确保 CPU 对按键的一次闭合仅作一次处理, 必须进行消抖。

按键消抖有两种方式, 一种是硬件消抖, 另一种是软件消抖。 为了使电路更加简单, 通常采用软件消抖。 我们开发板也是采用软件消抖, 一般来说一个简单的按键消抖就是先读取按键的状态, 如果得到按键按下之后, 延时 10ms, 再次读取按键的状态, 如果按键还是按下状态, 那么说明按键已经按下。 其中延时10ms 就是软件消抖处理, 至于硬件消抖, 大家可以百度了解下, 网上都有非常详细的介绍。 这里给大家列出单片机常用的软件去抖动方法:

1, 先设置 IO 口为高电平(由于开发板 IO 都有上拉电阻, 所以默认 IO 为高电平) 。

2, 读取 IO 口电平确认是否有按键按下。

3, 如有 IO 电平为低电平后, 延时几个毫秒。

4, 再读取该 IO 电平, 如果仍然为低电平, 说明按键按下。

5, 执行按键控制程序。

独立按键电路构成是由各个按键的一个管脚连接在一起接地, 按键其他引脚分别接到单片机 IO 口。

我们知道单片机的 IO 口既可作为输出也可作为输入使用, 当检测按键时用的是它的输入功能, 独立按键的一端接地, 另一端与单片机的 I/O 口相连, 开始时先给该 IO 口赋一高电平, 然后让单片机不断地检测该 I/O 口是否变为低电平, 当按键闭合时, 即相当于该 I/O 口通过按键与地相连, 变成低电平, 程序一旦检测到 I/O 口变为低电平则说明按键被按下, 然后执行相应的指令。

13.2 硬件设计

本实验使用到硬件资源如下:

(1) LED 模块中 D1 指示灯

(2) K1 按键

LED 模块电路在前面章节都介绍过, 这里就不多说, 开发板上的独立按键模块电路如下图所示:

从上图中可以看出, 4 个独立按键的控制管脚连接到 51 单片机的 P3.0-P3.3脚上。 其中 K1 连接在 P3.1 上, K2 连接在 P3.0 上, K3 连接在 P3.2 上, K4 连接在 P3.3 上。 4 个按键另一端全部连接在 GND, 当按键按下后, 对应 IO 口即为低电平。

13.3 软件设计

本章所要实现的功能是: 通过开发板上的独立按键 K1 控制 D1 指示灯亮灭。

我们打开"\4--实验程序\1--基础实验\8-独立按键实验" 工程, 控制代码全部都在 main.c 中, 代码如下:

cpp 复制代码
/**************************************************************************************
深圳市普中科技有限公司(PRECHIN 普中)
技术支持:www.prechin.net
PRECHIN
 普中

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

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

//定义独立按键控制脚
sbit KEY1=P3^1;
sbit KEY2=P3^0;
sbit KEY3=P3^2;
sbit KEY4=P3^3;

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

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

/*******************************************************************************
* 函 数 名       : delay_10us
* 函数功能		 : 延时函数,ten_us=1时,大约延时10us
* 输    入       : ten_us
* 输    出    	 : 无
*******************************************************************************/
void delay_10us(u16 ten_us)
{
	while(ten_us--);	
}

/*******************************************************************************
* 函 数 名       : key_scan
* 函数功能		 : 检测独立按键是否按下,按下则返回对应键值
* 输    入       : mode=0:单次扫描按键
				   mode=1:连续扫描按键
* 输    出    	 : KEY1_PRESS:K1按下
				   KEY2_PRESS:K2按下
				   KEY3_PRESS:K3按下
				   KEY4_PRESS:K4按下
				   KEY_UNPRESS:未有按键按下
*******************************************************************************/
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;		
}
/*******************************************************************************
* 函 数 名       : main
* 函数功能		 : 主函数
* 输    入       : 无
* 输    出    	 : 无
*******************************************************************************/
void main()
{	
	u8 key=0;

	while(1)
	{
	   	key=key_scan(0);
		if(key==KEY1_PRESS)//检测按键K1是否按下
			LED1=!LED1;//LED1状态翻转	
	}		
}

key_scan 函数带一个形参 mode, 该参数用来设定是否连续扫描按键, 如果mode 为 0, 只能操作一次按键, 只有当按键松开后才能触发下次的扫描, 这样做的好处是可以防止按下一次出现多次触发的情况。 如果 mode 为 1, 函数是支持连续扫描的, 即使按键未松开, 在函数内部有 if(mode==1)这条判断语句, 因此 key 始终是等于 1 的, 所以可以连续扫描按键, 当按下某个按键, 会一直返回这 个按键的键值, 这样做的好处是可以很方便实现连按操作。 函数内的delay_10us(1000)即为软件消抖处理, 通常延时 10ms 即可。

key_scan 函数还带有一个返回值, 如果未有按键按下, 返回值即为KEY_UNPRESS, 否则返回值即为对应按键的键值, 如 KEY1_PRESS、 KEY2_PRESS、KEY3_PRESS、 KEY4_PRESS, 这都是程序开头定义好的宏, 方便大家理解和使用。函数内定义了一个 static 变量 key, 相当于全局变量, 所以该函数不是一个可重入函数。 还有一点要注意的就是该函数按键的扫描是有优先级的, 因为函数内用了 if...else if...else 格式, 所以最先扫描处理的按键是 KEY1, 其次是KEY2, 然后是 KEY3, 最后是 KEY4。 如果需要将其优先级设置一样, 那么可以全部用 if 语句。

main 函数中主要就是调用 key_scan 函数用于检测按键, 此时传入的 mode值为 0, 表示单次扫描按键, 然后将扫描按键的值保存在变量 key 中, 最后通过if 判断语句控制 LED1 状态。

13.4 实验现象

使用 USB 线将开发板和电脑连接成功后(电脑能识别开发板上 CH340 串口) ,把编译后产生的.hex 文件烧入到芯片内, 实现现象如下: 当按下 K1 键, D1 指示灯亮, 再按下 K1 键, D1 指示灯灭, 如此循环。

相关推荐
点亮一颗LED(从入门到放弃)2 小时前
Linux驱动之中断(9)
linux·运维·单片机
小叶子来了啊2 小时前
13Arduino Flash 存储
单片机·嵌入式硬件
逐步前行2 小时前
C51_ML307C_4G
51单片机
点灯小铭3 小时前
基于单片机的温度烟雾与漏电综合火灾报警系统设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
boneStudent3 小时前
Day41:四轴飞行器控制系统 (基础)
stm32·单片机·嵌入式硬件
曾浩轩4 小时前
跟着江协科技学STM32之3-3GPIO输入
科技·stm32·嵌入式硬件
三佛科技-187366133974 小时前
FT8440AD非隔离12V350mA智能家居芯片方案(直接替代SDH8302)
单片机·嵌入式硬件·物联网
章鱼哥嵌入式开发4 小时前
【STM32F103按键外部中断检测实现】
stm32·单片机·嵌入式硬件·stm32入门教程·嵌入式开发实战·从零开始学stm32·单片机新手入门指南