键盘接口键盘接口第十章键盘接口知识目标:掌握独立式与行列式键盘的工作原是理解键盘接口程序的编制方法掌握按键抖动的原因及处理方法。
技能目标:能设计两种键盘电路会编写简单的独立式键盘程序。
素质目标:养成扩展嵌入式系统芯片外围相关知识的习惯。
项目四数字万年历的设计要求:设计一单片机控制的数字万年历。
它采用液晶显示可以显示年、月、日、星期小时、分钟、秒及当前的温度等信息。
、项目介绍:此项目涉及键盘、显示接口的问题还要用到数字温度传感器DSB及时间芯片DS。
所涉及的知识广泛综合性也很强。
只要认真、耐心地去边做边学一定会提高综合编程能力及调试能力达到单片机助理工程师甚至是工程师的水平。
、电路图如图所示。
实际连接中要将DSB的中间一个引脚通过K的电阻上拉到电源正极。
、元件清单单片机ATSLCDSMCALCM数字温度传感器B(或)TO封装时间芯片DS晶振MHZ、KHZ电阻:K、K可调、K排阻、K各一个电容:uF、pF*、电池:V*(或V)可充电(带电池座)按键*项目四任务万年历键盘的设计要求设计个输入键的键盘它能调整日期、时间。
任务分析:万年历中的时间或日期要经常进行效正这里就牵涉到从外部输入到单片机信息的问题即人要输入接口。
键盘基本问题键盘分编码键盘和非编码键盘。
键盘上闭合键的识别由专用的硬件编码器实现并产生键编码号或键值的称为编码键盘如BCD码键盘、ASCLL码键盘等而靠软件来识别的称为非编码键盘非编码键盘有分为:独立式非编码键盘和行列式非编码键盘。
在单片机组成的测控系统及智能化仪器中用的最多的是非编码键盘。
键的识别即如何识别键盘的问题。
按键键盘由一组规则排列的按键组成一个按键实际上是一个开关元件也就是说键盘是一组规则排列的开关。
单片机使用的按键是一种常开型的开关平时按键的两个触点处于断开状态按下键时它们才闭合。
键的抖动按键在闭合和断开时触点会存在抖动现象:抖动时间一般为~ms。
抖动会引起一次按键被误读多次。
为确保CPU对键的一次闭合仅做一次处理必须去除键抖动。
抖动的去除可以采用硬件的办法也可以软件的办法。
硬件去抖动的方法这里不予介绍可参考数字电路相关的书籍。
软件去抖动的方法其实就是利用延时来去掉这一抖动时间在具体程序设计中再讨论独立式键盘独立式按键是指各按键相互独立地接通一条输入数据线。
当任何一个键按下时与之相连的输入数据线即可读入数据而没有按下时读入。
图独立键盘电路图独立式键盘的电路简单易于编程但占用的IO 口线较多当需要较多按键时可能产生IO资源紧张问题。
设计一个独立式按键的键盘接口并编写键扫描程序电路原理图如图所示键号从上到下分别为~。
C语言程序清单:#includereghvoidkey(){unsignedcharkP=xff输入时P口置全k=P读取按键状态if(k==xff)无键按下返回returndelayms()有键按下延时去抖k=Pif(k==xff)确认键按下return抖动引起返回while(P!=xff)等待键释放switch(k){case:xfe…号键按下时执行程序段breakcase:xfd…号键按下时执行程序段break…~号键程序省略case:xf…号键按下时执行程序段break}行列式键盘为了减少键盘与单片机接口时所占用IO线的数目在键数较多时通常都将键盘排列成行列矩阵形式。
每一水平线(行线)与垂直线(列线)的交叉处通过一个按键来连通。
将IO口分为行线和列线按键跨接在行线和列线上列线通过上拉电阻接正电源。
利用这种结构只需N条行线和M条列线即可组成具有N×M个按键的键盘。
键值:按键闭合时的数值键模:按键代表的数值。
特点:占用IO口线较少但软件将较为复杂。
矩阵式键盘按键的识别:行扫描法及线反转法工作原理扫描法线反转法一、扫描法判别键盘中有无键按下。
向行线输出全读入列线状态。
如果有键按下总有一列线被拉至低电平从而使列输入不全为。
查找按下键所在位置。
依次给行线送低电平查列线状态。
全为则所按下的键不在此行否则所按下的键必在此行且是在与零电平列线相交的交点上的那个键。
图矩阵键盘电路图对按键位置进行编码。
找到所按下按键的行列位置后对按键进行编码即求得按键键值。
二、线反转法、判断哪一列有键压下写端口(xf):行线电平=列线电平=。
读端口进行判断:若P=xf→没有按键压下若P≠xf→某列有键压下→K、判断哪一行有键压下写端口(xf):行线电平=列线电平=。
读端口进行判断:若P=xf→没有按键压下若P≠xf→某行有键压下→K、将K与K相“或”并存于K(形成键值)闭合键所在行、列的状态均为其余皆为。
第一行的键值:、、、整个键盘的键值(对应为F):xee,xde,xbe,xe,xed,xdd,xbd,xd,xeb,xdb,xbb,xb,xe,xd,xb,x、利用查表比对法求出闭合按键的键模。
将各键的键值依次存放在一个数组中其顺序号就是键模。
charkeybuf={xee,xde,xbe,xe,xed,xdd,xbd,xd,xeb,xdb,xbb,xb,xe,xd,xb,x}利用循环变量i控制比对过程两者相等时的i就是闭合键的键模。
eedebeeedddbddABebdbbbbCDEFedb行列式键盘扫描流程及程序要求:×行列式键盘按下任意按键后LED显示器上显示该键的键模(~F)。
图×行列式键盘仿真电路仿真电路图程序流程图线反转法#includereghcharledmod={xf,x,xb,xf,x,xd,xd,x,xf,xf,x,xc,x,xe,x,x}共阴段码表charkeybuf={xee,xde,xbe,xe,xed,xdd,xbd,xd,xeb,xdb,xbb,xb,xe,xd,xb,x}键盘编码表chargetKey(void)voiddelay(unsignedinttime){unsignedintj=for(timetime) for(j=jj)}voidmain(void){charkey=P=xwhile(){key=getKey()获取键盘键值if(key!=)如果有键按下{P=ledmodkey在P口显示相应的键值(F)delay()}elseP=x如果没有键按下则不显示。
}}chargetKey(void){chark=,k=,i=P=xf输出行扫描码delay()if(P!=xf)如果有键按下{k=P读取列键值delay()if(P==k)如果值不变{P=xf输出列扫描码delay()k=P读取行键值k=k|k合成行列键值for(i=ii){if(keybufi==k)returni查表得到键值并返回键值(F)}}}return 如果没有键按下则返回}扫描法P口接*键盘作为输入P口输出。
按下号键数码管显示按下号键数码管显示以此类推。
#includeregh#includeabsacch#defineucharunsignedchar#defineuintunsign edintucharcodenum={xf,x,xb,xf,x,xd,xd,x,xf,xf,x,xc,x,xe,x,x,x}voiddelay s(void)ucharkbscan(void)voidmain(){ucharkey,tempwhile(){key=kbscan( )switch(key){casex:temp=breakcasex:temp=breakcasex:temp=breakcasex :temp=breakcasex:temp=breakcasex:temp=breakcasex:temp=breakcasex: temp=breakcasex:temp=breakcasex:temp=breakcasex:temp=breakcasex:t emp=breakcasex:temp=breakcasex:temp=breakcasex:temp=breakcasex:te mp=breakdefault:temp=break}P=numtempdelays()}}键消抖的延时函数voiddelays(void){ucharifor(i=ii)}键扫描函数ucharkbscan(void){ucharscancode,recodeP=xfif((Pxf)!=xf){delays()if((P xf)!=xf){scancode=xfe逐行扫描的初值while((scancodex)!=){P=scancode输出扫描码if((Pxf)!=xf)本行有键按下{recode=(Pxf)|xfreturn((~scancode)(~recode))返回特征字节码}elsescancode=(scancode)|x}}}return()无键按下返回值为}项目训练(作业):在P口增加几个按键使之可以调整班级、学号。
万年历中键盘的度值ucharTempBuffer,weekvalue万年历主程序流程图��开始初始化:时钟芯片、液晶模块、温度检测芯片�显示时间、时期及温度信息�有无按键按下?调用按键调整程序�图万年历主程序流程图是否main(){flag=时钟停止标志LCDInitial()液晶初始化InitDSB()DSB初始化InitialDS()时钟芯片初始化upflag=downflag=done=进入默认液晶显示while(){while(done==)keydone()进入调整模式while(done==){showtime()液晶显示数据flag=Setkey()扫描各功能键}}}键盘扫描程序voidSetkey()模式选择按键{Set=if(Set==)如果有键按下{mdelay()延时去抖动。
count=countSetkey按一次,count就加done=置进入调整模式标志。
while(Set==)等待按键释放。
}}voidkeydone()按键功能执行{ucharSecondif(flag==)关闭时钟,停止计时{Write(xe,x)写入允许temp=Read(x)Write(x,temp|x)Write(xe,x)禁止写入flag=}Setkey()扫描模式切换按键switch(count)三个子函数outkey()扫描跳出按钮Upkey()扫描加按钮Downkey()扫描减按钮、outkey()voidoutkey()跳出调整模式,返回默认显示{ucharSecondif(out==)调整确认键按下{mdelay()延时去抖动count=调整项目回到初始值。
下面一段程序主要是与时间芯片相关暂不讨论。
hidesec=,hidemin=,hidehour=,hideday=,hideweek=,hidemonth=,hideyear =Second=Read(DSSECOND)Write(xe,x)写入允许Write(x,Secondxf)Write(xE,x)禁止写入done=置调整结束标志while(out==)等待跳出键松开}}、Upkey()扫描加按钮voidUpkey()升序按键{Up=置升序结束标志if(Up==)如果升序按键按下则UP={mdelay()延时去抖动switch(count)根据要调整的项目不同决定升序键按下后的具体调整内容。