IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 由一个按键程序引发的思考(上) -> 正文阅读

[嵌入式]由一个按键程序引发的思考(上)

??说起按键程序,只要会单片机的肯定都很熟悉。一般开始学习单片机的时候,入门程序基本都是LED灯和按键。那么这个按键程序有什么特别的吗,还需要专门去思考吗?如果我刚开始学单片机的时候也会这么想,但是随着项目的积累,经验的增加,越来越觉得复杂的事情简单做,简单的事情复杂做,这句话很有哲理,越是看起来简单的事情,真正做好却很不容易。下面就抽丝剥茧的来慢慢分析下这个按键程序有什么特别之处。

??首先来看一下按键的硬件原理图。
在这里插入图片描述

??这是一个很常见的按键硬件连接图,电源接一个上拉电阻,在接按键,按键的另一端接地,电阻和按键的连接点接到单片机的IO口。按键未按下的时候输出高电平,当按键按下的时候输出低电平。由于按键是机械开关,所以在按下的一瞬间可能会产生毛刺。按键的实际波形如下:
在这里插入图片描述
??由于按键在按下或者弹起的瞬间会产生毛刺,所以在写程序判断的时候,需要加上10ms的延时。如果10ms后按键依然是低电平就认为按键有效,否则就认为出现了干扰,按键无效。

在这里插入图片描述

u8 key_scan(void)
{
	if(key==0)
	{
		delay_ms(10);
		if(key==0)
			return 1;
		else
			return 0;
	}
}

??这种是很常见的方法,使用起来也最简单。看起来也没什么问题,现在将问题复杂化一下。假设按键被用户按下了一次,那么会有以下这些情况。

在这里插入图片描述
??第一种情况是正常按键按下时间大概0.2秒左右,第二种情况是按键的时间非常短只有0.02秒,第三种情况是持续按下2秒。那么这三种情况都会被程序正常识别到。但是程序运行的结果可能会出现不同的效果。

??假如现在的程序实现的功能是,在主程序中循环检测按键,如果发现按键按下,就让LED灯的状态翻转一下。也就是按一下按键LED灯亮,再按一下按键LED灯灭。程序执行流程如下。

在这里插入图片描述

void main(void)
{
	char value = 0;
	while(1)
	{
		value = key_scan();
		if(value)
			LED = !LED;
	}
}

??在主函数中一直循环检测按键,如果有按键按下,那么就翻转LED灯的状态。在实际测试过程中会发现按键有时候好像不怎么灵敏,当LED灯亮的时候,按一下按键,LED灯还是亮的。如果用示波器观察LED灯的波形,会发现按键按下一次时,LED的状态会翻转很多次。

在这里插入图片描述
??按键按下的时候越长,LED翻转的次数越多。LED最后是亮还是灭就得靠运气了,通过按键很难控制一下灭,一下亮。那么为什么会出现这种情况。下面就根据波形分析一下程序执行的流程。
在这里插入图片描述
??由于主程序干的事情很少,所以代码消耗的时间,主要是在按键检测的10ms中,也就是主程序基本10ms就能执行完一圈。假如按键按下的时间比较长,当按键程序检测完成之后,LED灯的状态也翻转了,此时按键依然没有弹起,那么程序会再次进入按键检测函数中。此时会再次检测到按键按下。这样LED灯在按键按下的这段时间中就会一直翻转。所以LED灯基本10ms翻转一次,由于人的视觉暂留时间时是20ms,翻转的时间小于20ms所以人眼看不到LED灯的闪烁。如果将按键的10ms延时改为100ms,那么在按键按下的时候,就会看到LED灯一直在闪烁。单次按键功能变成了连续按键的功能。

??那么如果想要这个程序实现正常的功能要怎么办呢?第一种方法是在主程序中加入延时,让程序执行一圈花费的时间更多一点。第二种方法是按键检测的延时时间加长一点。第三种方法是当发现按键按下时直接进入死循环中,直到按键弹起,才退出按键检测程序。

??前两种方法看着能解决问题,但是实际中不同的人按键的时间长短很难把握,有的人轻轻按一下,有的人使劲按半天。这样延时时间太长,感觉按键比较迟钝,延时时间太短,又会导致按一次按键,灯闪好几次的情况出现。这样同一个产品在不同客户的手里就有不同的客户体验,就会导致有的客户感觉产品的功能和设计的不符。那么最有效的解决方法只能是第三种,当按键按下后,等待按键弹起,然后在执行LED状态翻转的功能。

??那么按键检测的流程改为下面这种:
在这里插入图片描述

u8 key_scan(void)
{
	if(key==0)
	{
		delay_ms(10);
		if(key==0)
		{
			while(key==0);
			return 1;
		}
		else
			return 0;
	}
}

??这样当按键按下的时候,就一直在while循环中等待按键释放。LED灯的状态在按键弹起的时候才会翻转。

在这里插入图片描述
??不论按键按的快还是慢,LED的状态在按键的时候每次只会改变一次。这样就比较符合设计的期望。

??但是这样又会引入一个新的问题,就是在按键按下的时候,程序就会一直停留在那里,其他的事情就不能干了。如果此时还有数码管动态显示函数,那么在按键按下的时候就数码管就会闪烁一下,如果按键按下时间很长,那么数码管就会熄灭。这样产品使用的时候体验就很不好。
在这里插入图片描述

??那按键既不能在按下的时候让LED状态翻转,又不能在弹起的时候让LED翻转,难道就无解了吗?那这个LED灯如如何控制呢?要知按键如何判断?且听下回分解。

由一个按键程序引发的思考(中)

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-10-31 12:14:20  更:2022-10-31 12:15:47 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 20:15:51-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码