单片机原理及应用:独立式键盘控制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

相关文章

SpringBoot中四种AOP实战应用场景及代码实现

《SpringBoot中四种AOP实战应用场景及代码实现》面向切面编程(AOP)是Spring框架的核心功能之一,它通过预编译和运行期动态代理实现程序功能的统一维护,在SpringBoot应用中,AO... 目录引言场景一:日志记录与性能监控业务需求实现方案使用示例扩展:MDC实现请求跟踪场景二:权限控制与

redis中使用lua脚本的原理与基本使用详解

《redis中使用lua脚本的原理与基本使用详解》在Redis中使用Lua脚本可以实现原子性操作、减少网络开销以及提高执行效率,下面小编就来和大家详细介绍一下在redis中使用lua脚本的原理... 目录Redis 执行 Lua 脚本的原理基本使用方法使用EVAL命令执行 Lua 脚本使用EVALSHA命令

Java Spring 中 @PostConstruct 注解使用原理及常见场景

《JavaSpring中@PostConstruct注解使用原理及常见场景》在JavaSpring中,@PostConstruct注解是一个非常实用的功能,它允许开发者在Spring容器完全初... 目录一、@PostConstruct 注解概述二、@PostConstruct 注解的基本使用2.1 基本代

Golang HashMap实现原理解析

《GolangHashMap实现原理解析》HashMap是一种基于哈希表实现的键值对存储结构,它通过哈希函数将键映射到数组的索引位置,支持高效的插入、查找和删除操作,:本文主要介绍GolangH... 目录HashMap是一种基于哈希表实现的键值对存储结构,它通过哈希函数将键映射到数组的索引位置,支持

C语言中位操作的实际应用举例

《C语言中位操作的实际应用举例》:本文主要介绍C语言中位操作的实际应用,总结了位操作的使用场景,并指出了需要注意的问题,如可读性、平台依赖性和溢出风险,文中通过代码介绍的非常详细,需要的朋友可以参... 目录1. 嵌入式系统与硬件寄存器操作2. 网络协议解析3. 图像处理与颜色编码4. 高效处理布尔标志集合

SpringBoot请求参数接收控制指南分享

《SpringBoot请求参数接收控制指南分享》:本文主要介绍SpringBoot请求参数接收控制指南,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Spring Boot 请求参数接收控制指南1. 概述2. 有注解时参数接收方式对比3. 无注解时接收参数默认位置

Java中的Lambda表达式及其应用小结

《Java中的Lambda表达式及其应用小结》Java中的Lambda表达式是一项极具创新性的特性,它使得Java代码更加简洁和高效,尤其是在集合操作和并行处理方面,:本文主要介绍Java中的La... 目录前言1. 什么是Lambda表达式?2. Lambda表达式的基本语法例子1:最简单的Lambda表

Spring Security+JWT如何实现前后端分离权限控制

《SpringSecurity+JWT如何实现前后端分离权限控制》本篇将手把手教你用SpringSecurity+JWT搭建一套完整的登录认证与权限控制体系,具有很好的参考价值,希望对大家... 目录Spring Security+JWT实现前后端分离权限控制实战一、为什么要用 JWT?二、JWT 基本结构

Android实现两台手机屏幕共享和远程控制功能

《Android实现两台手机屏幕共享和远程控制功能》在远程协助、在线教学、技术支持等多种场景下,实时获得另一部移动设备的屏幕画面,并对其进行操作,具有极高的应用价值,本项目旨在实现两台Android手... 目录一、项目概述二、相关知识2.1 MediaProjection API2.2 Socket 网络

Python结合PyWebView库打造跨平台桌面应用

《Python结合PyWebView库打造跨平台桌面应用》随着Web技术的发展,将HTML/CSS/JavaScript与Python结合构建桌面应用成为可能,本文将系统讲解如何使用PyWebView... 目录一、技术原理与优势分析1.1 架构原理1.2 核心优势二、开发环境搭建2.1 安装依赖2.2 验