ImageVerifierCode 换一换
格式:DOCX , 页数:13 ,大小:43.50KB ,
资源ID:4282575      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bingdoc.com/d-4282575.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(晨辉教你轻松学51按键篇.docx)为本站会员(b****4)主动上传,冰点文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰点文库(发送邮件至service@bingdoc.com或直接QQ联系客服),我们立即给予删除!

晨辉教你轻松学51按键篇.docx

1、晨辉教你轻松学51按键篇晨辉教你轻松学51-按键篇对于一个由单片机为核心构成的系统而言。输入通道是相当重要的。可以看到几乎每一样基于单片机的产品都有人机交互的部分。如各种仪器设备上的各种按钮和开关,以及我们手机上的键盘,MP3上的按键等等。最常见的输入部分,莫非就是按键了。对于大多数初学者而言,编写一个好的按键程序是一件颇为头疼的事情。于是乎在网上乱搜一气,程序倒是找到了不少,但是看了半天依然是不明白。或者在某某论坛上面发帖“跪求XX按键程序,大虾帮忙”如果你偶然间进了这个论坛,又偶然看到了这个帖子,而且恰好你对按键程序的写法也不是很清楚,那么我希望你能够静静的看完这个帖子。如果你觉得对你很有

2、帮助,那么我希望你能够在以后的日子中能够坚持到这个论坛来,一起交流学习,分享自己学习过程中的喜悦或者一起探讨棘手的问题,这是我写这个帖子的最大的初衷了。OK,不能再说了,再说就变成水帖了。那么我们开始吧。按键的种类很多。不过原理基本相似。下面我们以一种轻触开关为例讲解按键程序的写法。这种轻触开关大家不陌生吧_一般情况下,按键与单片机的连接如下面这幅图所示。(图中电阻值一般去4.7k10k之间,对于内部端口有上拉电阻的单片机则可省略此电阻)单片机对于按键的按下与否则是通过检测相应引脚上的电平来实现的。对于上图而言,当P17引脚上面的电平为低时,则表示按键已经按下。反之,则表明按键没有按下。我们在

3、程序中只要检测到了P17引脚上面的电平为低了,就可以判断按键按下。呵呵,简单吧。等会,您先别乐呵,话还没说完呢。下面我们来看看,当按键按下时,P17引脚上面的波形是怎么变化的。上图是一个理想波形图,当按键按下时,P17口的电平马上被拉低到0V了。当然理想的东西都是不现实的。所以我们还是看看现实的波形图吧。看出什么区别来了没。呵呵,只要你不是傻子我相信都能看出其中的区别。由于按键的机械特性。当按键闭合时,并不能马上保存良好的接触,而是来回弹跳。这个时间很短,我们的手根本感觉不出来。但是对于一秒钟执行百万条指令的单片机而言,这个时间是相当的长了。那么在这段抖动的时间内,单片机可能读到多次高低电平的

4、变化。如果不加任何处理的话,就会认为已经按下,或者松开很多次了。而事实上,我们的手一直按在按键上,并没有重复按动很多次。要想能够正确的判断按键是否按下就要避开这段抖动的时间。根据一般按键的机械特点,以及按键的新旧程度等而言,这段抖动的时间一般在5MS20MS之间。看到这里你明白了该如何做了吧。看看下面的这个流程图,你应该不陌生吧。这个流程是好多教科书上的做法。可惜,误导了好多人。为什么呢。因为它根本就没有考虑实际情况。我们根据这幅流程图来写它的代码看看。unsigned char v_ReadKey_f( void )unsigned char KeyPress ;if( P17 = 0)De

5、lay(20) ;/延时20MSIf( P17 = 0) KeyPress = 1 ; While( !P17) ;/等待释放 elseKeyPress = 0 ; 这样一个程序,相信对很多初学者而言都不陌生。因为好多书上基本都是这样的一个流程和写法。可是当有一天,我们想做一个数码管加按键调整的时钟,发现当我们按键按下去的时候,数码管就不亮了。为什么呢。原因就在这个键盘扫描函数。平常没有按键按下还好。一旦有键按下,它先是浪费了CPU的大部分时间(就是那个什么事情都没做的延时20MS函数)然后,又霸占CPU( 就是哪个死死等在那里的while(P17);语句)直到按键释放。对于这种情况我们是忍无

6、可忍的,那么就让我们彻底的抛弃它吧。那么到底按键扫描函数改如何写呢.所谓众里寻她千XX,蓦然回首,那人却在灯火阑珊处。如果我们把CPU延时的那20MS拿出来去做其它事情,那么不就充分利用CPU的时间了吗。而一般情况下我们只要前沿去抖动就可以了。也就是说了,我们只需在按键按下后去抖就可以了,对于按键的释放抖动可以不必要过于关注。当然这主要和应用的场合有关。一个能有效识别按键按下并支持连发功能的按键已经能够应用到大多数的场合了。 下面以四个独立按键的处理程序为例来讲解(支持单击和连发)#includeregx52.h sbit KeyOne = P10 ;sbit KeyTwo = P11 ;sb

7、it KeyThree = P12 ;sbit KeyFour = P13 ;#define uint16 unsigned int#define uint8 unsigned char#define NOKEY0xff#define KEY_WOBBLE_TIME 500/去抖动时间(待定)#define KEY_OVER_TIME 15000/等待进入连击时间(待定),该常数要比正常 /按键时间要长,防止非目的性进入连击模式#define KEY_QUICK_TIME 1000 /等待按键抬起的连击时间(待定)void v_KeyInit_f( void )KeyOne = 1 ;/按键初

8、始化(相应端口写1)KeyTwo = 1 ;KeyThree = 1 ;KeyFour = 1 ;uint8 u8_ReadKey_f(void)static uint8 LastKey = NOKEY ;/保存上一次的键值static uint16 KeyCount = 0 ;/按键延时计数器static uint16 KeyOverTime = KEY_OVER_TIME ; /按键抬起时间uint8 KeyTemp = NOKEY ;/临时保存读到的键值KeyTemp = P1 & 0x0f ;/读键值if( KeyTemp = 0x0f )KeyCount = 0 ;KeyOverTi

9、me = KEY_OVER_TIME ;return NOKEY ;/无键按下返回NOKEYelseif( KeyTemp = LastKey )/是否第一次按下 if( +KeyCount = KEY_WOBBLE_TIME )/不是第一次按下,则判断/抖动是否结束return KeyTemp ;/去抖动结束,返回键值else if( KeyCount KeyOverTime )KeyCount = 0 ;KeyOverTime = KEY_QUICK_TIME ;return NOKEY ; else/是第一次按下则保存键值,以便下次执行此函数时与读到的键值作比较LastKey = Key

10、Temp ;/保存第一次读到的键值KeyCount = 0 ;/延时计数器清零KeyOverTime = KEY_OVER_TIME ;return NOKEY ; 下面是我测试用的主程序(相关头文件未列出,仅仅作测试演示用) void main(void)uint8 KeyValue ;int16 Count ;v_LcdInit_f() ;v_KeyInit_f() ;CLSLOCATE(3, 1)PRINT(Key Test)LOCATE(6, 2)SHOW_ICONwhile(1)KeyValue = u8_ReadKey_f() ;if( KeyValue != NOKEY )LOC

11、ATE(1, 2)if( KeyValue = 0x0e )Count+ ;if( KeyValue = 0x0d )Count- ;if( KeyValue = 0x0b )Count = 0 ;if( KeyValue = 0x07 )Count = 0 ;HIDE_ICONPRINTD(Count, 5)LOCATE(6, 2)else /SHOW_ICON 每次执行读键盘函数时,只是对一些标志进行判断,然后退出。因此能够充分的利用CPU的资源。同时可以处理连发按键。此按键扫描按键函数可以直接放在主函数中。如果感觉按键太过灵敏或者迟钝则改一下相关消抖动的宏定义即可。此函数也可以通过中断标

12、志位进行定时的扫描。此时,需要添加一个定时标志位,并将相关消抖动的和连击时间的宏定义改小即可。然后在主程序类似下面这样写即可if( KeyTime ) /定时扫描时间到KeyValue = u8_ReadKey_f() ; 具体的工作就交给您去完成啦。看看效果:按键单击连发时候的截图至此,关于单个按键的学习就告一段落了,您是否已经明白了。如果您还不明白,那么把这个程序好好的看看,并画下流程图,分析分析。估计您就会恍然大悟。关键是思路要转换过来。下面我们来看看多个按键的情况吧一般情况下,如果多个按键每个都直接接在单片机的I/O上的话会占用很多的I/O资源。比较合理的一种做法是,按照行列接成矩阵的

13、形式。按键接在每一个的行列的相交处。这样对于m行n列的矩阵,可以接的按键总数是m*n。这里我们以常见的4*4矩阵键盘来讲解矩阵键盘的编程。上图就是矩阵键盘的一般接法。这里我们要介绍一种快速的键盘扫描法:线反转法(或者称为行列翻转法)。具体流程如下。首先,让单片机的行全部输出0,列全部输出1,读取列的值(假设行接P3口的高四位,列接低四位)。即P3= 0x0f ; 此时读列的值,如果有键按下,则相应的列读回来的值应该为低。譬如此时读回来的值为 0x0e ; 即按键列的位置已经确定。这时反过来,把行作为输入,列作为输出,即P0 = 0xf0 ;此时再读行的值,如果按键仍然被按下,则相应的行的值应该

14、为低,如果此时读回来的值为0xe0,则确定了行的位置 。说到这里,您应该笑了,知道了一个按键被按下的行和列的位置,那么就可以肯定确定它的位置了。我们把读回来的行值和列值进行或运算。即 0xe0 | 0x 0e 即 0xee。那么0xee就是我们按下的按键的键值了。怎么样。只需几步就可以判断所有的键值,简单吧。下面再结合一个例子具体看看。/* 此模块所需相关支持库*/#includeregx52.h#define uint8 unsigned char#define uint16 unsigned int/* 与硬件连接相关的定义及宏定义和操作宏*/#define KEYBOARD P3 /键盘

15、连接到单片机上的端口位置#define READ_ROW_ENLABLEKEYBOARD = 0x0f ; /读端口之前先把相应口置位(由基本51单片机特性决定的)#define READ_COL_ENLABLEKEYBOARD = 0xf0 ; / 根据实际硬件连接情况修改/* 模块内相关的宏定义及常数宏 */#define NOKEY 0xff/定义无键按下时的返回值#define DELAY_COUNT2/消抖时间常数/* 此模块所需的全局或者外部变量 */bit bdata StartScan = 0 ;/此变量需放在定时中断中置位/* 按键扫描函数,按下去后经去抖,确定按下 * 则返

16、回键值015;无键按下则返回0xff ; * 此函数需要定时器的支持(去抖.) */uint8 u8_KeyBoardScan_f()static uint8 DelayCount = 0 ;uint8 KeyValueRow = 0 ;uint8 KeyValueCol = 0 ;uint8 KeyValue = 0 ;if( StartScan ) /开始扫描,StartScan在定时中断中置位StartScan = 0 ; /清除开始扫描标志位,避免多次重复执行扫描程序/读入按键状态前先向相应端口写1(由基本51单片机硬件结构决定)READ_ROW_ENLABLEif( ( KEYBOA

17、RD & 0x0f ) != 0x0f ) /判断是否有键按下DelayCount+; if( DelayCount = DELAY_COUNT )/有键按下则判断延时去抖的时间是否达到return NOKEY ;else /消除了抖动if( ( KEYBOARD & 0x0f ) != 0x0f )/再次判断是否按键真的按下 DelayCount = 0 ; /确定按下后,延时去抖计时器清0 KeyValueRow = KEYBOARD & 0x0f ; /取得行码/准备读列,先向相应端口写1(由基本51单片机硬件结构决定)READ_COL_ENLABLE if ( (KEYBOARD &

18、0xf0) != 0xf0 ) /反转,读列码 KeyValueCol = KEYBOARD & 0xf0 ;/取得列码 /合并取得的行码和列码,即是相应按键的键值 switch( KeyValueCol | KeyValueRow)case 0x77 : KeyValue = 0 ; break ;case 0xb7 : KeyValue = 1 ; break ;case 0xd7 : KeyValue = 2 ; break ;case 0xe7 : KeyValue = 3 ; break ;case 0x7b : KeyValue = 4 ; break ;case 0xbb : K

19、eyValue = 5 ; break ;case 0xdb : KeyValue = 6 ; break ;case 0xeb : KeyValue = 7 ; break ;case 0x7d : KeyValue = 8 ; break ;case 0xbd : KeyValue = 9 ; break ;case 0xdd : KeyValue = 10 ;break ;case 0xed : KeyValue = 11 ;break ;case 0x7e : KeyValue = 12 ;break ;case 0xbe : KeyValue = 13 ;break ;case 0xde : KeyValue = 14 ;break ;case 0xee : KeyValue = 15 ;break ;default : return NOKEY ;return KeyValue ; else DelayCount = 0 ; return NOKEY ; elseDelayCount = 0 ;return NOKEY ;elseDelayCount = 0 ;return NOKEY ;void v_T0_I

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2