单片机原理及应用:独立式键盘控制LED与多功能按键识别

本文主要是介绍单片机原理及应用:独立式键盘控制LED与多功能按键识别,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

今天来介绍另一个外设——按键与LED的配合工作,与开关不同,按键需要注意消除抖动带来的影响,代码逻辑也会更复杂一写,下面先为大家介绍独立式键盘的相关知识。

单片机的独立式键盘指的是一种不依赖于计算机或其他外部设备的键盘输入方式,由若干按键按照一定的规则组成,每一个按键实质就是一个按钮开关。而独立式键盘的各键相互独立,每个按键各接一条I/O口线,通过检测I/O输入线的电平状态,很容易地判断哪个按键被按下。

当无键按下时,通过上拉电阻,P0的 8 个I/O口引脚被上拉为高电平“ 1 ”;如果有键按下,将使对
应该键接的I/O口引脚,通过该键接地,信息为“0 ” 。
与开关不同,机械式按键在按下或释放时,由于机械弹性作用的影响 常伴随一定时间的触点机械抖 动, 然后才能稳定下来。 若有抖动,按键按下会被错误地认为是多次操作。 所以我们要在代码中执行消抖程序。
消抖程序的原理是 在检测到有按键按下时执行一个10ms左右的延时程序;再确认该键电平是否仍保持闭合状态电平,若仍保持闭合状态电平,则确认该键处于闭合状态,从而消除抖动的影响。我现在以8位独立式键盘控制LED灯点亮作为案例,代码如下:
#include <reg52.h>     
void delay10ms(void)     //延时消抖程序,第三种delay,数量级为5~10k
{ unsigned char i,j; for(i=40;i>0;i--) for(j=250;j>0;j--); 
} 
void main()         
{unsigned char x;P1=0xff;          //led全灭x=0;while(1){while(x==0)     //无键被按下执行死循环,有键被按下才往下走{x=P0;             //第一次进入循环给x赋值,没有异常再取反恢复原值x=~x;}delay10ms();      //消抖x=P0;               //再次读键盘状态x=~x;if(x==0) continue;//如果无键按下则认为是按键抖动,重新扫描键盘 switch(x)           //根据键值点亮对应的发光二极管{case 0x01: P1=0xfe; break;    //点亮第一个发光二极管case 0x02: P1=0xfd; break;    //点亮第二个发光二极管case 0x04: P1=0xfb; break;   //点亮第三个发光二极管case 0x08: P1=0xf7; break;   //点亮第四个发光二极管case 0x10: P1=0xef; break;   //点亮第五个发光二极管case 0x20: P1=0xdf; break;    //点亮第六个发光二极管case 0x40: P1=0xbf; break;   //点亮第七个发光二极管case 0x80: P1=0x7f; break;    //点亮第八个发光二极管default: break;}}
}
#include<reg52.h> sbit S1=P1^0;        		//将S1位定义为P1.0引脚
sbit S2=P1^1;        		//将S2位定义为P1.1引脚
sbit S3=P1^2;        		//将S3位定义为P1.2引脚
sbit S4=P1^3;        		//将S4位定义为P1.3引脚unsigned char keyval;  		//定义键值储存变量单元void led_delay(void);//第一种延时函数,流水灯延时
void delay10ms(void);//按键消抖
void key_scan(void)	;//键盘扫描
void ledstate();	 //switch封装,也可以写在主函数中
//void key(void);		 
//灯的四种变化
void forward(void);	//从上至下
void backward(void);//从下至上
void Alter(void);	//高四位与低四位互闪
void blink (void);	//全闪void main(void)  	
{keyval=0;       //键值初始化为0while(1)
{		//key();key_scan();  			//调用键盘扫描函数ledstate();				//调用灯光执行程序}
}
void key_scan(void)			//函数功能:键盘扫描
{P1=0xff;if((P1&0x0f)!=0x0f)   		//检测到有键按下{delay10ms();  		//延时10ms再去检测if(S1==0) keyval=1;    		//按键k1被按下if(S2==0) keyval=2;     		//按键k2被按下if(S3==0) keyval=3;     		//按键k3被按下if(S4==0) keyval=4;     		//按键k4被按下	}}
void forward(void)	//函数功能:正向流水点亮LED
{P3=0xfe; led_delay();        		//LED0亮P3=0xfd; led_delay();         		//LED1亮P3=0xfb; led_delay();         		//LED2亮P3=0xf7; led_delay();         		//LED3亮P3=0xef; led_delay();         		//LED4亮P3=0xdf; led_delay();         		//LED5亮P3=0xbf; led_delay();         		//LED6亮P3=0x7f; led_delay(); 				//LED7亮} 
void backward(void)		//函数:反向流水点亮LED
{P3=0x7f; led_delay();        		//LED7亮P3=0xbf; led_delay();        		//LED6亮P3=0xdf; led_delay();         		//LED5亮P3=0xef; led_delay();          		//LED4亮P3=0xf7; led_delay();         		//LED3亮P3=0xfb; led_delay();          		//LED2亮P3=0xfd; led_delay();        		//LED1亮P3=0xfe; led_delay();       		//LED0亮
}
void Alter(void)		//函数:交替点亮高4位与低4位LED
{P3=0x0f;led_delay();P3=0xf0;led_delay();
}
void blink (void)		//函数:闪烁点亮LED
{P3=0xff;led_delay();P3=0x00;led_delay();
} 
void led_delay(void)			//函数:延时
{unsigned char i,j;for(i=0;i<220;i++)for(j=0;j<220;j++);
}
void delay10ms(void)	//函数:软件消抖延时10ms
{unsigned char i,j;for(i=0;i<100;i++)for(j=0;j<100;j++);
}
void ledstate()
{switch(keyval){case 1:forward();	//键值为1,调用正向流水点亮函数break;case 2:backward();	//键值为2,调用反向流水点亮函数break;case 3:Alter();	//键值为3,调用高、低4位交替点亮函数break;case 4:blink ();	//键值为4,调用闪烁点亮函数break;}
} 
//键盘扫描和灯光操作可以合并为一个函数,还能省下sbit命名
/*void key(void)
{
P1=0xff;
if((P1&0x0f)!=0x0f)
{delay10ms();
switch(~(P1&0x0f)){case 0xf1:forward();	//键值为1,调用正向流水点亮函数break;case 0xf2:backward();	//键值为2,调用反向流水点亮函数break;case 0xf4:Alter();	//键值为3,调用高、低4位交替点亮函数break;case 0xf8:blink ();	//键值为4,调用闪烁点亮函数break; }}} */

 这里给大家展示了两个程序,第一个实例就是先检测按键的状态,然后用switch语句判断哪个键被按下,之后执行相应的点亮程序。第二个实例是把之前学过的LED点亮状态都封装成函数,然后在主程序里根据键盘的值执行相应的操作。

实例仿真1

实例仿真2

有两点需要注意

  1. delay10ms是到目前为止我们学习的第三个延时函数,作用是消抖,数量级为5~10k。 
  2. 为了节省空间,按键个数一般少于8个,需要用按位与“&”屏蔽不需要的引脚来防止异常电位

按键控制LED点亮

下面是多功能按键控制LED的案例,与前文不同,该案例是通过记录按键按下的次数来改变LED状态的。,在这种情况下,就需要考虑按住按键不松手的情况,以免一直进行灯光切换。

#include <reg52.h>
sbit key=P3^0; 
unsigned char ID; 
void delay10ms(void) 
{ unsigned char i,j; for(i=20;i>0;i--) for(j=248;j>0;j--); 
} 
void keyonoff()
{if(key==0) 		  //检测按键被按下{delay10ms();  //去抖if(key==0) { ID++;while(key==0); 	//防止按住不松手,等待按键释放  if(ID==4) { ID=0; } } }
}
void displayled()
{switch(ID) {case 0: P1=0x0e;break; 	//点亮D1,熄灭其它LEDcase 1: P1=0x0d;break; 	//点亮D2,熄灭其它LEDcase 2: P1=0x0b;break; 	//点亮D3,熄灭其它LEDcase 3: P1=0x07;break; 	//点亮D4,熄灭其它LED}  	//end switch
}
void main(void) 
{ 	P1=0x0f;while(1) { //按键识别程序keyonoff();//根据按键结果,输出程序displayled();}    	
}      		

这个模式在没有按键被按下的情况下点亮第一个LED作为标志,大家也可以自行更改case的值设置双击或全灭等操作,或者把前文封装的函数放在switch里执行更多的功能。

多功能按键控制LED点亮

 以上就是按键控制LED灯点亮的过程,之后会介绍按键控制数码管显示的案例。谢谢大家。

这篇关于单片机原理及应用:独立式键盘控制LED与多功能按键识别的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/562872

相关文章

PostgreSQL的扩展dict_int应用案例解析

《PostgreSQL的扩展dict_int应用案例解析》dict_int扩展为PostgreSQL提供了专业的整数文本处理能力,特别适合需要精确处理数字内容的搜索场景,本文给大家介绍PostgreS... 目录PostgreSQL的扩展dict_int一、扩展概述二、核心功能三、安装与启用四、字典配置方法

从原理到实战深入理解Java 断言assert

《从原理到实战深入理解Java断言assert》本文深入解析Java断言机制,涵盖语法、工作原理、启用方式及与异常的区别,推荐用于开发阶段的条件检查与状态验证,并强调生产环境应使用参数验证工具类替代... 目录深入理解 Java 断言(assert):从原理到实战引言:为什么需要断言?一、断言基础1.1 语

Python中re模块结合正则表达式的实际应用案例

《Python中re模块结合正则表达式的实际应用案例》Python中的re模块是用于处理正则表达式的强大工具,正则表达式是一种用来匹配字符串的模式,它可以在文本中搜索和匹配特定的字符串模式,这篇文章主... 目录前言re模块常用函数一、查看文本中是否包含 A 或 B 字符串二、替换多个关键词为统一格式三、提

Java MQTT实战应用

《JavaMQTT实战应用》本文详解MQTT协议,涵盖其发布/订阅机制、低功耗高效特性、三种服务质量等级(QoS0/1/2),以及客户端、代理、主题的核心概念,最后提供Linux部署教程、Sprin... 目录一、MQTT协议二、MQTT优点三、三种服务质量等级四、客户端、代理、主题1. 客户端(Clien

MySQL中的表连接原理分析

《MySQL中的表连接原理分析》:本文主要介绍MySQL中的表连接原理分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、环境3、表连接原理【1】驱动表和被驱动表【2】内连接【3】外连接【4编程】嵌套循环连接【5】join buffer4、总结1、背景

深度解析Spring AOP @Aspect 原理、实战与最佳实践教程

《深度解析SpringAOP@Aspect原理、实战与最佳实践教程》文章系统讲解了SpringAOP核心概念、实现方式及原理,涵盖横切关注点分离、代理机制(JDK/CGLIB)、切入点类型、性能... 目录1. @ASPect 核心概念1.1 AOP 编程范式1.2 @Aspect 关键特性2. 完整代码实

Java Stream的distinct去重原理分析

《JavaStream的distinct去重原理分析》Javastream中的distinct方法用于去除流中的重复元素,它返回一个包含过滤后唯一元素的新流,该方法会根据元素的hashcode和eq... 目录一、distinct 的基础用法与核心特性二、distinct 的底层实现原理1. 顺序流中的去重

Spring如何使用注解@DependsOn控制Bean加载顺序

《Spring如何使用注解@DependsOn控制Bean加载顺序》:本文主要介绍Spring如何使用注解@DependsOn控制Bean加载顺序,具有很好的参考价值,希望对大家有所帮助,如有错误... 目录1.javascript 前言2. 代码实现总结1. 前言默认情况下,Spring加载Bean的顺

Spring @Scheduled注解及工作原理

《Spring@Scheduled注解及工作原理》Spring的@Scheduled注解用于标记定时任务,无需额外库,需配置@EnableScheduling,设置fixedRate、fixedDe... 目录1.@Scheduled注解定义2.配置 @Scheduled2.1 开启定时任务支持2.2 创建

Spring Boot 实现 IP 限流的原理、实践与利弊解析

《SpringBoot实现IP限流的原理、实践与利弊解析》在SpringBoot中实现IP限流是一种简单而有效的方式来保障系统的稳定性和可用性,本文给大家介绍SpringBoot实现IP限... 目录一、引言二、IP 限流原理2.1 令牌桶算法2.2 漏桶算法三、使用场景3.1 防止恶意攻击3.2 控制资源