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

news2024/9/24 23:33:34

今天来介绍另一个外设——按键与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;       //键值初始化为0
 	while(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,熄灭其它LED
      		case 1: P1=0x0d;break; 	//点亮D2,熄灭其它LED
      		case 2: P1=0x0b;break; 	//点亮D3,熄灭其它LED
      		case 3: P1=0x07;break; 	//点亮D4,熄灭其它LED
    	}  	//end switch
}
void main(void) 
{ 	P1=0x0f;
	while(1) 
  	{ 
		//按键识别程序
 		keyonoff();
		//根据按键结果,输出程序
		displayled();
  	}    	
}      		

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

多功能按键控制LED点亮

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1352982.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据结构:堆的三部曲(二)top K问题

堆的应用&#xff08;一&#xff09;top K问题 一.top k问题的应用本质解析二.top K问题使用案例——从100亿整型的文件中找出前5个最大值1.建堆1.1过程分析1.2过程图模拟1.3向上调整算法代码1.4建堆代码 2.处理文件中剩余剩余元素2.1过程分析2.2过程图示例2.3向下调整算法代码…

百度百科词条创建多久可以通过?

一个优质的百度百科词条&#xff0c;能提升个人或企业的品牌形象。因此&#xff0c;越来越多的人希望创建自己的百度百科词条&#xff0c;那么&#xff0c;创建一个百度百科词条到底需要多久才能通过审核呢&#xff1f;接下来伯乐网络传媒就来给大家分享一下。 一、百度百科词条…

AI计算,为什么要用GPU?

今天这篇文章&#xff0c;我们继续来聊聊芯片。 在之前的文章里&#xff0c;小枣君说过&#xff0c;行业里通常会把半导体芯片分为数字芯片和模拟芯片。其中&#xff0c;数字芯片的市场规模占比较大&#xff0c;达到70%左右。 数字芯片&#xff0c;还可以进一步细分&#xff0…

灰度发布及声明式资源管理(yaml文件)

一、三种常见的项目发布方式 1&#xff09;蓝绿发布 2&#xff09;灰度发布【常用】 3&#xff09;滚动发布 应用程序升级&#xff0c;面临最大的问题是新旧业务之间的切换 立项-定稿-需求发布-开发-测试-发布&#xff0c;测试上线后&#xff0c;再完美也会有问题&#xff0c;为…

【Mybatis】深入学习MyBatis:高级特性与Spring整合

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a; Mybatis ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 高级特性 1 一级缓存和二级缓存 一级缓存 二级缓存 2 延迟加载 5 整合Spring 1 MyBatis-Spring模块 2 事务管理 结…

C#基础:字段的初始化、继承

一、字段的初始化 class Test {static int Main(string[] args){var list new List<Calculate>();//1.Calculate中加入abvar calculate new Calculate { a 2, b 3 };//2.Calculate中加入Value列表calculate.Values.Add(new Value { id 1, value 6 });calculate.Va…

计算机组成原理-期末复习

目录 第一章——计算机系统概述 一、数字计算机的主要组成结构 二、指令的形式 三、控制器的基本任务 四、指令流和数据流 五、适配器与输入/输出设备 七、计算机的系统软件 八、C 语言的转换层次图 九、计算机系统的层次结构图 第二章——运算方法和运算器 一、 数据格式…

MySQL之表的记录操作

前言 存数据不是目的&#xff0c;目的是能够将存起来的数据取出来或者查出来&#xff0c;并且能够对数据进行增删改查操作&#xff0c;本文将详细介绍表中记录的增删改查操作。对记录的操作属于DML数据库操作语言&#xff0c;可以通过SQL实现对数据的操作&#xff0c;包括实现向…

爬虫入门与urllibrequests

前情摘要 一、web请求全过程剖析 我们浏览器在输入完网址到我们看到网页的整体内容, 这个过程中究竟发生了些什么? 我们看一下一个浏览器请求的全过程 接下来就是一个比较重要的事情了. 所有的数据都在页面源代码里么? 非也~ 这里要介绍一个新的概念 那就是页面渲染数据的…

爬取涛声网音频

代码展现&#xff1a; 代码详情&#xff1a; import requests import re import os filename 声音// if not os.path.exists(filename): os.mkdir(filename) def down_load(page): for page in range(page): page page1 url https://www.tosound.…

如何将图像数据转换为.mat文件,mat文件内是cell封装的struct格式的数据

在我看论文&#xff1a;《 Holistically-nested Edge Detection (HED) 》的时候&#xff0c;对论文中有关边缘结果的评价指标很感兴趣&#xff0c;于是我就研究了如何计算这些指标 如果有同样感兴趣或者有需要的小伙伴可以下载这里的代码&#xff1a;GitHub - xwjabc/hed: A P…

IO进程线程 day4 文件IO与目录操作

1.使用标准IO完成两个文件拷贝 #include <head.h> int main(int argc, const char *argv[]) {//判断输入是否合法if(argc>3){printf("输入不合法\n");return -1;}//定义两个文件指针&#xff0c;用于读写FILE *fp1NULL;FILE *fp2NULL;if((fp1fopen(argv[1]…

扩展:键盘录入笔记(next()、nextLine()、nextInt()、nextDouble())

文章目录 一&#xff0c;键盘录入涉及到的方法如下&#xff1a;1&#xff09;next&#xff08;&#xff09;、nextLine&#xff08;&#xff09;&#xff1a;代码示例&#xff1a;代码示例&#xff1a; 2&#xff09;nextInt&#xff08;&#xff09;&#xff1a;代码示例&…

面试题:Linux命令大全

序号命令对应英文作用1ls [目录名]list查看当前目录下的内容2pwdprint work directory查看当前所在目录3cd [目录名]change directory切换目录4touch [文件名]touch如果文件不存在,创建文件5mkdir [目录名]make directory创建目录6rm [文件名]remove删除指定文件 ls 查看当前目…

hAdmin漂亮的后台html模板免费下载

hAdmin漂亮的后台html模板免费下载-遇见你与你分享

Qt6.5类库详解:QFontComboBox

哈喽大家好&#xff0c;欢迎关注公众号(20YC编程)&#xff0c;有免费视频课程哦&#xff01; -今日内容- 1 QFontComboBox介绍 QFontComboBox是Qt框架中的一个字体选择类&#xff0c;它提供了一个下拉列表框&#xff0c;用于选择字体。 QFontComboBox的主要功能和特点&#x…

Java基础-----集合类(四)

文章目录 1. Iterator和ListIterator1.1 简介1.2 常用方法 2. remove方法2.1 比较foreach方式和迭代器方式删除元素2.2 找原因 -- 迭代器删除操作源码 1. Iterator和ListIterator 1.1 简介 1.Iterator 可以遍历List集合&#xff0c;也可以遍历Set集合&#xff1b; ListIterat…

Unity SVN更新提交小工具

Unity SVN更新提交小工具 前言使用说明必要前提源码参数说明 感谢 前言 Unity开发时每次都要到文件夹中操作SVN&#xff0c;做了一个小工具能够在Editor中直接操作。 使用说明 必要前提 前提是要安装好SVN&#xff0c;在文件夹右键能够看到安装的SVN 源码 using System…

音效出众设计时尚,内置AI功能,sanag塞那Z50上手

现在蓝牙耳机已经成为人们生活中不可或缺的一部分了&#xff0c;像是在上班、坐车的时候&#xff0c;既可以享受自己的音乐空间&#xff0c;又不会吵到别人&#xff0c;看书、做题还是运动的时候&#xff0c;也可以保证长时间使用耳朵卫生、舒适度。正因为庞大的市场需求&#…

软件测试作业‖pytest+po+csv+html报告+cookie+selenium

软件测试作业‖pytestpocsvhtml报告cookieselenium 先用本地部署的系统试了下 或者UFT自动化测试里诺图书管理系统软件测试 # &#xff0c;#测试报告# #性能测试#&#xff0c;#测试用例#&#xff0c; #自动化测试# Selenium 的 Web自动化测试基本要求和注意事项 1.请使用ch…