最新单片机与常用外围设备接口电路ppt课件.ppt
10.1.1 物理特性 发光二极管的两根引线中较长的一根为正极,应接电源正极。有的发光二极管的两根引线一样长,但管壳上有一凸起的小舌,靠近小舌的引线是正极。 发光二极管与小白炽灯泡和氖灯相比,发光二极管的特点是:工作电压很低(有的仅一点几伏);工作电流很小(有的仅零点几毫安即可发光);抗冲击和抗震性能好,可靠性高,寿命长;通过调制通过的电流强弱可以方便地调制发光的强弱。由于有这些特点,发光二极管在一些光电控制设备中用作光源,在许多电子设备中用作信号显示器。把它的管心做成条状,用7条条状的发光管组成7段式半导体数码管,每个数码管可显示09十个数目字。多种颜色的发光二极管如图10-2所示。 程序如下: #include #include void delay(unsigned char tmp);/延时子函数 unsigned chartmpled50=0X01,0X02,0X04,0X08,0X10,0X20,0X40,0X80,0X81,0X82,0X84,0X88,0X90,0XA0,0XC0,0XC1,0XC2,0XC4,0XC8,0XD0,0XE0,0XE1,0XE2,0XE4,0XE8,0XF0,0XF1,0XF2,0XF4,0XF8,0XF9,0XFA,0XFC,0XFD,0XFE,0XFF,0XFF,0X00,0XFF,0X00;/定义数组常量,前面加code表示常量在程序代码中存放,/不占用RAM。该数组为发光二极管的输出数据void main(void) /入口函数unsigned char i;/定义变量while(1) /无限循环 for(i=0;i50;i+)/连续输出50个数据 P0=tmpledi; /这个符号是取反,因发光二极管采用共阳极,所以将数据取反再输出delay(50); /调用延时子函数,改变参数大小,调整变化速度void delay(unsigned char tmp)/延时子函数unsigned char i,j;i=tmp;while(i) i-;j=255;while(j) j-; 10.2 数码管数码管 数码管按段数分为七段数码管和八段数码管,八段数码管比七段数码管多一个发光二极管单元(多一个小数点显示);按能显示多少个“8”可分为1位、2位、4位等数码管。常用的LED显示器有LED状态显示器(俗称发光二极管)、LED七段显示器(俗称数码管)和LED十六段显示器。 发光二极管可显示两种状态,用于系统状态显示;数码管用于数字显示;LED十六段显示器用于字符显示。10.2.1 数码管简介 1. 数码管结构数码管结构如图10-4所示。 数码管由8个发光二极管(以下简称字段)构成,通过不同的组合可用来显示数字0-9、字符A -F、H、L、P、R、U、Y、符号“”及小数点“”。 数码管又分为共阴极和共阳极两种结构。 LED数码管分类:1)按其内部结构可分为共阴型和共阳型;2)按其外形尺寸有多种形式,使用较多的是0.5和0.8;3)按显示颜色也有多种形式,主要有红色和绿色;4)按亮度强弱可分为超亮、高亮和普亮。5)正向压降一般为1.52V,额定电流为10mA,最大电流为40mA。 共阳极数码管的8个发光二极管的阳极(二极管正端)连接在一起。通常,公共阳极接高电平(一般接电源),其它管脚接段驱动电路输出端。当某段驱动电路的输出端为低电平时,则该端所连接的字段导通并点亮。根据发光字段的不同组合可显示出各种数字或字符。此时,要求段驱动电路能吸收额定的段导通电流,还需根据外接电源及额定段导通电流来确定相应的限流电阻。 共阴极数码管的8个发光二极管的阴极(二极管负端)连接在一起。通常,公共阴极接低电平(一般接地),其它管脚接段驱动电路输出端。当某段驱动电路的输出端为高电平时,则该端所连接的字段导通并点亮,根据发光字段的不同组合可显示出各种数字或字符。此时, 要求段驱动电路能提供额定的段导通电流,还需根据外接电源及额定段导通电流来确定相应的限流电阻。 3. 数码管字形编码()要使数码管显示出相应的数字或字符,必须使段数据口输出相应的字形编码。字型码各位定义为:数据线D0与a字段对应,D1与b字段对应,依此类推。 如使用共阳极数码管,数据为0表示对应字段亮,数据为1表示对应字段暗;如使用共阴极数码管,数据为0表示对应字段暗,数据为1表示对应字段亮。如要显示“0”,共阳极数码管的字型编码应为:11000000B(即C0H);共阴极数码管的字型编码应为:00111111B(即3FH)。依此类推。数码管字形编码表如表10-1所示。10.2.2 驱动方式 数码管要正常显示,就要用驱动电路来驱动数码管的各个段码,从而显示出我们要的数字,因此根据数码管的驱动方式的不同,可以分为和两类。 是指数码管显示某一字符时,相应的发光二极管恒定导通或恒定截止。这种显示方式的各位数码管相互独立,公共端恒定接地(共阴极)或接正电源(共阳极)。每个数码管的8个字段分别与一个8位I/O口地址相连,I/O口只要有段码输出,相应字符即显示出来,并保持不变,直到I/O口输出新的段码。采用静态显示方式,较小的电流即可获得较高的亮度,且占用CPU时间少,编程简单,显示便于监测和控制,但其占用的口线多,硬件电路复杂,成本高,只适合于显示位数较少的场合。 是一位一位地轮流点亮各位数码管,这种逐位点亮显示器的方式称为位扫描。通常,各位数码管的段选线相应并联在一起,由一个8位的I/O口控制;各位的位选线(公共阴极或阳极)由另外的I/O口线控制。动态方式显示时,各数码管分时轮流选通,要使其稳定显示,必须采用扫描方式,即在某一时刻只选通一位数码管,并送出相应的段码,在另一时刻选通另一位数码管,并送出相应的段码。依此规律循环,即可使各位数码管显示将要显示的字符。 虽然这些字符是在不同的时刻分别显示,但由于人眼存在,只要每位显示间隔足够短就可以给人以同时显示的感觉。 采用动态显示方式比较节省I/O口,硬件电路也较静态显示方式简单,但其亮度不如静态显示方式,而且在显示位数较多时,CPU要依次扫描,占用CPU较多的时间。10.2.3 常见问题常见问题 1、显示效果 由于发光二极管基本上属于电流敏感器件,其正向压降的分散性很大, 并且还与温度有关,为了保证数码管具有良好的亮度均匀度,就需要使其具有恒定的工作电流,且不能受温度及其它因素的影响。另外,当温度变化时驱动芯片还要能够自动调节输出电流的大小以实现色差平衡温度补偿。 2、安全性 即使是短时间的电流过载也可能对发光管造成永久性的损坏,采用恒流驱动电路后可防止 由于电流故障所引起的数码管的大面积损坏。另外,我们所采用的超大规模集成电路还 具有级联延时开关特性,可防止反向尖峰电压对发光二极管的损害。超大规模集成电路还具有热保护功能,当任何一片的温度超过一定值时可自动关断,并且可在控制室内看到故障显示。1、使用三极管目的是放大电流2、三极管三脚顺序ebc(三极管平的一面向自己时的顺序),3、NPN(箭头向出):脚e接数码管的公共脚,脚c接+5V电源,脚b接P1.7;4、数码管的脚abcdefgh并不是按一定的顺序排列的,要用万用表进行测量,看那段发亮;5、PNP(箭头向入);6、电解电容长为正|-符号,短(灰白色)为负(-符号 关于亮度一致性的问题是一个行业内的常见问题。 有二个大的因素影响到亮度一致性。一是使用原材料芯片的选取,一是使用数码管时采取的控制方式。 1、原材料-芯片的UF和亮度和波长是一个,即使筛选过芯片,UF和亮度和波长已在一个很小的范围了,生产出来的产品还是在一个范围内,结果就是亮度不一致。 2、要保证数码管亮度一样,在控制方式选取上也有差别。最好的办法是恒流控制,流过每一个发光二极管的电流都是相同的,这样发光二极管看起来亮度就是一样的了。如恒压控制,则导致UF不相同的发光二极管分到的电流不相同,所以亮度也不同。当然以上二个条件是相辅相成的。 找公共共阴和公共共阳:首先,我们找个电源(3到5伏)和1个1K(几百欧的也行)的电阻,Vcc串接一个电阻后和GND接在任意2个脚上,组合有很多,但总有一个LED会发光的,找到一个就够了,然后GND不动,Vcc(串电阻)逐个碰剩下的脚,如果有多个LED(一般是8个),那它就是共阴的了。相反用Vcc不动,GND逐个碰剩下的脚,如果有多个LED(一般是8个),那它就是共阳的。也可以直接用数字万用表,红表笔是电源的正极,黑表笔是电源的负极。10.2.4 10.2.4 数码管与单片机的应用数码管与单片机的应用 例10-2 如图10-5所示,单片机的P2口接数码管的字形口,P1.0-P1.2接译码器74LS138的A-C实现片选Y0-Y7,E1、E2、E3为使能端,E2=E3=0(4脚、5脚接低电平),E1=1(6脚接高电平),74LS138被选通工作。数码管的字位口接74LS128的Y0-Y7,因为Y0-Y7是低电平(即0)表示选中,所以数码管应该采用共阴管。要求:在数码管上动态显示24C02。 1)采用74LS138译码器为中间器件,采用减少P口的使用,只用了P1.0-P1.2则可实现8个数码管字位的控制;2)在实际硬件制作过程中,由于采用共阴管,靠P2口提供的电流令数码管发光,存在电流拉动不够,管不够亮的情况;可以在74LS138后再加74LS240芯片,再把共阴管改为共阳管则可(记得程序代码也要做相应调整)。市面上现在也很少八为一体数码管,可以用2个四为一体的代替。在P2口和数码管之间增加74LS373锁存器(或者74HC573锁存器)3)74LS240是八反相缓冲器/线驱动器。也就是一片芯片上,有八路(个)反相缓冲器/线驱动器。反相的意思是当输入是高电平,输出就是低电平,当输入是低电平,输出就是高电平。缓冲器,因为芯片有三态门,数据可在用时打开三态门,驱动能力强,可用于总线上驱动用。 4)四位一体数码管有12个脚,有4个公共端,8个字型端。万用表选X10电阻挡,红笔出来“负”,黑笔出来“正”。 思考:有没有译码器是高电平输出有效,若有则不需要用74LS240,硬件电路更加简单。图图10-5 单片机与数码管的连接单片机与数码管的连接/*数码管的显示*/#include #include void display(unsigned char *lp,unsigned char lc); /数字的显示函数;lp为指向数组的地址,lc为显示的个数void displaystr(unsigned char *lp,unsigned char lc); /字符的显示函数,同上void delay(); /延时子函数,5个空指令code unsigned char table=0 x3f,0 x06,0 x5b,0 x4f,0 x66,0 x6d,0 x7d,0 x07,0 x7f,0 x6f,0 x40,0 x00;/共阴数码管 0-9 , , 全灭unsigned char l_tmpdate8=0,1,2,3,4,5,6,7;/定义数组变量,并赋值0,12,3,4,5,6,7,就是本程序要显示的八个数code unsigned char l_24C025=0 x5b,0 x66,0 x39,0 x3f,0 x5b;/24C02 /定义数组常量,前面加code表示常量在程序代码中存放,ROM /不占用RAM,在数码管上显示24C02void main(void) unsigned char i=0;while(1) display(l_tmpdate,8);/用数字显示函数显示八个数字 /displaystr(l_24C02,5);/或者用这个函数显示5个字符void display(unsigned char *lp,unsigned char lc) /显示 unsigned char i;/定义变量 P2=0;/端口2为输出 P1=P1&0 xF8; /将P1口的前3位输出0,对应74LS138译门输入脚,全0为第一位数码管 for(i=0;ilc;i+) /循环显示 P2=tablelpi; /查表法得到要显示数字的数码段 delay( ); /延时5个空指令 if(i=7) /检测显示完8位否,完成直接退出,不让P1口再加1,否则进位影响到第四位数据 break; P2=0;/清0端口,准备显示下位 P1+;/下一位数码管void displaystr(unsigned char *lp,unsigned char lc)/显示unsigned char i;P2=0;P1=P1&0 xF8;for(i=0;ilc;i+) P2=lpi;/本函数跟上面函数一样,不同的是它不用查表, /直接输出显示已设定好的数值到数码段 delay(); if(i=7) break; P2=0; P1+;void delay(void) /空5个指令_nop_();_nop_();_nop_();_nop_();_nop_();10.3 点阵点阵 为集中反映晶体结构的周期性而引入的一个概念。首先考虑一张二维周期性结构的图像。可在图上任选一点 O作为原点。在图上就可以找到一系列与O点环境完全相同的点子,这一组无限多的点子就构成了。将图像作一平移,对应于从原点O移至点阵的任意位置,图像仍然不变。这种不变性表明点阵反映了原结构的平移对称性。上述的考虑显然可以推广到具有三维周期性结构的无限大晶体。应该指出,原点位置可以任意选,但得到的点阵却是等同的。 点阵平移矢量L总可以选用三个非共面的基矢A1、A2及A3的组合来表示:L=mA1+nA2+pA3,这里的m、n、p为三个整数。A1、A2与A3所构成的平行六面体,称为晶胞或初基晶胞,它包含了晶体结构的基本重复单元。 值得注意:基矢与晶胞的选择都不是唯一的,存在无限多种选择方案。一个初基晶胞是晶体结构的最小单元。但是有时为了能更充分地反映出点阵的对称性,也可选用稍大一些的非初基晶胞(即晶胞中包含一个以上的阵点)。2讲 一个点阵可以还原为一系列平行的阵点行列(简称阵列),或一系列的平行的阵点平面(简称阵面)。可用由一组基矢所确定的坐标系来描述某一组特定的阵列或阵面族的取向。 我们选取通过原点的阵列上任意阵点的三个坐标分量,约化为互质的整数u、v、w作为阵列方向的指标,可用符号【uvw】来表示。为了标志某一特定阵面族的方向,可选择最靠近(但不通过)原点的阵面,读取它在三个坐标轴上截距的倒数,将这三个数约化为互质的数h、k、l就得该阵面旋的方向指标,可用符号(hkl)来表示。这就是阵面族的密勒指数。点阵外形图如图10-6所示,点阵电路结构图图10-7所示。 图图10-6 点阵外形图点阵外形图 图图10-6 点阵外形图点阵外形图 图图10-7 点阵结构图点阵结构图 例10-3 如图10-8所示,点阵8*8的行X0-X7接单片机P2.0-P2.7,列L0-L7接P3.0-P3.7,实现行列扫描。 单片机的P1.0接按键,初始状态点阵显示数码“0”,每按一下按键,数码管则加1显示,到数码“9”,再按则变回“0”,即0-9循环。 图图10-8 单片机和点阵的连接单片机和点阵的连接程序如下:#include #define hang P2 /*定义行的IO口*/#define lie P3 /*定义列的IO口*/sbit an = P10; /定义按键char shu=0 ; /定义一个变量记下当前的数字unsigned char code tab =0 x00,0 x7E,0 xFF,0 xC3,0 xC3,0 xFF,0 x7E,0 x00, /字符00 x00,0 x00,0 x43,0 xFF,0 xFF,0 x03,0 x00,0 x00, /字符10 x00,0 x63,0 xC7,0 xCF,0 xDB,0 xF3,0 x63,0 x00, /字符20 x00,0 x42,0 xDB,0 xDB,0 xDB,0 xFF,0 x66,0 x00, /字符30 x00,0 x3E,0 x46,0 xFF,0 xFF,0 x06,0 x06,0 x00, /字符40 x00,0 xF6,0 xF7,0 xD3,0 xD3,0 xDF,0 xDE,0 x00, /字符50 x00,0 x7E,0 xFF,0 xDB,0 xDB,0 xDF,0 x4E,0 x00, /字符60 x00,0 xC0,0 xC0,0 xC7,0 xFF,0 xF8,0 xC0,0 x00, /字符70 x00,0 xFF,0 xFF,0 xDB,0 xDB,0 xFF,0 xFF,0 x00, /字符80 x00,0 x72,0 xFB,0 xDB,0 xDB,0 xFF,0 x7E,0 x00, /字符9 ;void delay(unsigned int a)/延时子函数 while(a-);/*8x8点阵子函数,显示数字子函数*/void draw_8x8(char tu) /定义一个名为tu的数组,形参用数组 char n; /变量标记扫描的次数 for(n=0;n8;n+) hang=1n; /选行 /hang=1=00000001B0,向左边移动0位,就是说首次不用移动 /P2.0=1,有效,选中首行,即第0行; lie=tun; /送出8个列的状态,即显示tu0。 delay(50); void qudoudong()/按键去抖动子函数 char a=10; while(a-) draw_8x8(&tabshu*8);/去抖动时显示当前数字void main() unsigned int n=0;/按键超时变量 while(1) draw_8x8(&tabshu*8); /显示数字 /实参用指针变量;&tabshu*8是变量tabshu*8的地址;&是取地址运算符 /设shu=1,则darw_8x8(&tab1*8)=darw_8x8(&tab8),意思是指向tab8, /从第9个内容开始抽数,一抽抽8个,这样送列才会显示1; an=1;/按键没有按下则为1;(按键首状态) if(an=0)/有按下 qudoudong();/去抖动; if(an=0)/真的按下了键(再判) while(an=0) /等手放开,放手则不能进入这个循环体,因为an=1; draw_8x8(&tabshu*8);/显示数字 n+; if(n=100) /n起到判断作用,按的时间长了,就break,转到去做显示 break; /如果按键超时则退出 n=0;/回复按键超时变量为0 shu+; if(shu=10) /如果数字超过了9 shu=0; /回复为0 an=1; 例10-4 如图10-9所示,在16*16点阵上循环显示“单片机点阵实验!”字样。初始点阵屏幕显示“单”字,向左移动。按下按键,则字样向右移动。 图10-9 点阵16*16#include #include #include /*字模*/unsigned char code zdan32= /单0 x10,0 x10,0 x08,0 x20,0 x04,0 x48,0 x3f,0 xfc,0 x21,0 x08,0 x21,0 x08,0 x3f,0 xf8,0 x21,0 x08,0 x21,0 x08,0 x3f,0 xf8,0 x21,0 x00,0 x01,0 x04,0 xff,0 xfe,0 x01,0 x00,0 x01,0 x00,0 x01,0 x00;unsigned char code zpian32= /片0 x00,0 x80,0 x20,0 x80,0 x20,0 x80,0 x20,0 x80,0 x20,0 x84,0 x3f,0 xfe,0 x20,0 x00,0 x20,0 x00,0 x3f,0 xc0,0 x20,0 x40,0 x20,0 x40,0 x20,0 x40,0 x20,0 x40,0 x20,0 x40,0 x40,0 x40,0 x80,0 x40;unsigned char code zji32= /机0 x10,0 x00,0 x10,0 x10,0 x11,0 xf8,0 x11,0 x10,0 xfd,0 x10,0 x11,0 x10,0 x31,0 x10,0 x39,0 x10,0 x55,0 x10,0 x51,0 x10,0 x91,0 x10,0 x11,0 x10,0 x11,0 x12,0 x12,0 x12,0 x14,0 x0e,0 x18,0 x00;unsigned char code zdian32= /点0 x02,0 x00,0 x02,0 x00,0 x02,0 x08,0 x03,0 xfc,0 x02,0 x00,0 x02,0 x10,0 x3f,0 xf8,0 x20,0 x10,0 x20,0 x10,0 x20,0 x10,0 x3f,0 xf0,0 x00,0 x00,0 x29,0 x10,0 x24,0 xc8,0 x44,0 x44,0 x80,0 x04;unsigned char code zzhen32= /阵0 x00,0 x80,0 x78,0 x84,0 x4f,0 xfe,0 x50,0 x80,0 x50,0 xa0,0 x61,0 x20,0 x51,0 x28,0 x4b,0 xfc,0 x48,0 x20,0 x48,0 x20,0 x68,0 x24,0 x57,0 xfe,0 x40,0 x20,0 x40,0 x20,0 x40,0 x20,0 x40,0 x20;unsigned char code zshi32= /实0 x02,0 x00,0 x01,0 x00,0 x7f,0 xfe,0 x48,0 x02,0 x86,0 x84,0 x02,0 x80,0 x10,0 x80,0 x0c,0 x80,0 x04,0 x84,0 xff,0 xfe,0 x01,0 x00,0 x01,0 x40,0 x02,0 x20,0 x04,0 x10,0 x18,0 x0c,0 x60,0 x04;unsigned char code zyan32= /验0 x08,0 x40,0 xfc,0 x40,0 x08,0 xa0,0 x48,0 xa0,0 x49,0 x10,0 x4a,0 x0e,0 x4d,0 xf4,0 x48,0 x00,0 x7c,0 x48,0 x06,0 x48,0 x05,0 x48,0 x1d,0 x50,0 xe5,0 x10,0 x44,0 x24,0 x17,0 xfe,0 x08,0 x00;unsigned char code ztanhao32= /!0 x00,0 x00,0 x01,0 x80,0 x03,0 xc0,0 x03,0 xc0,0 x03,0 xc0,0 x01,0 x80,0 x01,0 x80,0 x01,0 x80,0 x01,0 x80,0 x01,0 x80,0 x00,0 x00,0 x00,0 x00,0 x01,0 x80,0 x01,0 x80,0 x00,0 x00,0 x00,0 x00;unsigned char *z_q=zdan,zpian,zji,zdian,zzhen,zshi,zyan,ztanhao,0; /要显示的字/定义了*z_q指针指向数组,只是它的每一个数组元素又是一个数组(二维数组)unsigned char TU32; /要显示的画面sbit A_A =P11 ; /移动sbit P21 =P21 ;sbit P22 =P22 ;sbit P23 =P23 ;sbit P24 =P24 ;#define P00P0#define ZUO(a) P00=a;P24=0;P24=1#define YOU(a) P00=a;P21=0;P21=1#define SHANG(a) P00=a;P22=0;P22=1#define XIA(a) P00=a;P23=0;P23=1extern void xianshiyanshi(unsigned int n); /显示延时子程序extern void chuqitu(void); /初始图第一个字单extern void dian1616(unsigned char ZZ); /显示画图子程序extern void DELAY(unsigned int a); /延时子函数 void DELAY(unsigned int a) /延时子函数a最大为十进制65535 while(a-) ; void dian1616(unsigned char ZZ)/显示画图子程序 unsigned char a,b; /a放行号,b放字在数组的序号 b=0;XIA(0 x00);/不送出下半部分 for(a=0 x01;a!=0;a=(a1)/上半个字 DELAY(2) ; /延时一小段时间为看清楚 ZUO(ZZb); b+ ; YOU(ZZb); /送出右 b+ ; SHANG(a) ;/送出行号 DELAY(30) ;/延时一小段时间为了字型显示更清楚 ZUO(0) ; /消影 YOU(0); SHANG(0 x00);/不送出上半部分 for(a=0 x01;a!=0;a=(a1)/下半个字 DELAY(2) ;/延时一小段时间为看清楚 ZUO(ZZb) ; b+ ; YOU(ZZb); /送出右 b+ ; XIA(a); /送出行号 DELAY(30) ;/延时一小段时间为了字型显示更清楚 ZUO(0) ; /消影 YOU(0); void chuqitu(void)/初始图为第一个字单 char n; for(n=0;n32;n+) TUn=z_q0n; /二维数组 void xianshiyanshi(unsigned int n)/显示延时 while(n-) dian1616(TU);/显示画图子程序void zychulimain(void)/左右处理子程序 unsigned char hao=0; /记第一序号 idata unsigned char haox=1; /记下一个序号 unsigned char n=0; /当前的处理的地方unsigned char n_n=0; /移动后的地方标记 haox=1; while(1) n_n+; if(n_n=16) n_n=0; haox+; if(z_qhaox=0) /如下一个序号为最后复位为0 haox=0; hao+; if(z_qhao=0) /如下第一序号为最后复位为0 hao=0; for(n=0;n16;n+)/左右处理 A_A=1; if(A_A=1)/没有按下则左移 TU2*n7)&1); TU2*n+1=1;/右半处理 if(n_n(7-n_n)&0 x01); else TU2*n+1|=(z_qhaox2*n+1(15-n_n)&0 x01); else/有按下右移 TU2*n+1=1;/右半处理 TU2*n+1|=(TU2*n=1;/左半处理 if(n_n8) TU2*n|=(z_qhaox2*n+1(7-n_n)&0 x80); else TU2*n|=(z_qhaox2*n(15-n_n)&0 x80); xianshiyanshi(15);/显示延时 main( ) /主程序 chuqitu(); /初始图为第一个字单while(1) zychulimain() ;/左右处理子程序 10.4 键盘接口原理键盘接口原理10.4.1 按键的分类 按键按照结构原理可分为两类,一类是触点式开关按键,如机械式开关、导电橡胶式开关等;另一类是无触点式开关按键,如电气式按键,磁感应按键等。前者造价低,后者寿命长。目前,微机系统中最常见的是触点式开关按键。 10.4.2 输入原理 在单片机应用系统中,除了复位按键有专门的复位电路及专一的复位功能外,其它按键都是以开关状态来设置控制功能或输入数据的。当所设置的功能键或数字键按下时,计算机应用系统应完成该按键所设定的功能,键信息输入是与软件结构密切相关的过程。 对于一组键或一个键盘,总有一个接口电路与CPU相连。CPU可以采用查询或中断方式了解有无将键输入,并检查是3讲 哪一个键按下,将该键号送入累加器ACC,然后通过跳转指令转入执行该键的功能程序,执行完后再返回主程序10.4.3按键结构与特点 微机键盘通常使用,其主要功能是把机械上的通断转换成为电气上的逻辑关系。也就是说,它能提供标准的TTL逻辑电平,以便与通用数字系统的逻辑电平相容。机械式按键再按下或释放时,由于机械弹性作用的影响,通常伴随有一定时间的,然后其触点才稳定下来。其抖动过程如下图所示,抖动时间的长短与开关的机械特性有关,一般为510 ms。在触点抖动期间检测按键的通与断状态,可能导致判断出错,即按键一次按下或释放被错误地认为是多次操作,这种情况是不允许出现的。为了克服按键触点机械抖动所致的检测误判,必须采取去抖动措施。这一点可从硬件、软件两方面予以考虑。在键数较少时,可采用硬件去抖,而当键数较多时,采用软件去抖。按键触点机械抖动如图10-10所示。 图图10-10 按键触点机械抖动按键触点机械抖动闭合稳定键按下前沿抖动后沿抖动 1. 1. 按键编码按键编码 一组按键或键盘都要通过I/O口线查询按键的开关状态。根据键盘结构的不同,采用不同的编码。无论有无编码,以及采用什么编码,最后都要转换成为与累加器中数值相对应的键值,以实现按键功能程序的跳转。 2. 2. 键盘程序键盘程序 一个完善的键盘控制程序应具备以下功能: (1) 检测有无按键按下,并采取硬件或软件措施,消除键盘按键机械触点抖动的影响。 (2) 有可靠的逻辑处理办法。每次只处理一个按键,其间对任何按键的操作对系统不产生影响,且无论一次按键时间有多长,系统仅执行一次按键功能程序。 (3) 准确输出按键值(或键号),以满足跳转指令要求。 3. 3. 独立式按键独立式按键 单片机控制系统中,往往只需要几个功能键,此时,可采用独立式按键结构。 1)独立式按键结构独立式按键是直接用I/O口线构成的单个按键电路,其特点是每个按键单独占用一根I/O口线,每个按键的工作不会影响其它I/O口线的状态。独立式按键的典型应用如图所示。独立式按键电路配置灵活,软件结构简单,但每个按键必须占用一根I/O口线,因此,在按键较多时,I/O口线浪费较大,不宜采用。独立式按键如图10-11所示。P1.0P1.1P1.2P1.3P1.4P1.5P1.6P1.78031VCC8051 图图10-11 独立式按键独立式按键 2) 独立式按键的软件结构 独立式按键的软件常采用查询式结构。先逐位查询每根I/O口线的输入状态,如某一根I/O口线输入为低电平,则可确认该I/O口线所对应的按键已按下,然后,再转向该键的功能处理程序。4. 矩阵式按键矩阵式按键 单片机系统中,若使用按键较多时,通常采用矩阵式(也称行列式)键盘。 1) 矩阵式键盘的结构及原理 矩阵式键盘由行线和列线组成,按键位于行、列线的交叉点上,其结构如下图所示。 由图可知,一个44的行、列结构可以构成一个含有16个按键的键盘,显然,在按键数量较多时,矩阵式键盘较之独立式按键键盘要节省很多I/O口。行列式按键如图10-12所示。 矩阵式键盘中,行、列线分别连接到按键开关的两端,行线通过矩阵式键盘中,行、列线分别连接到按键开关的两端,行线通过上拉电阻接到上拉电阻接到5V5V上。当无键按下时,行线处于高电平状态;当有键上。当无键按下时,行线处于高电平状态;当有键按下时,行、列线将导通,此时,行线电平将由与此行线相连的列线按下时,行、列线将导通,此时,行线电平将由与此行线相连的列线电平决定。这是识别按键是否按下的关键。然而,矩阵键盘中的行线、电平决定。这是识别按键是否按下的关键。然而,矩阵键盘中的行线、列线和多个键相连,各按键按下与否均影响该键所在行线和列线的电列线和多个键相连,各按键按下与否均影响该键所在行线和列线的电平,各按键间将相互影响,因此,必须将行线、列线信号配合起来作平,各按键间将相互影响,因此,必须将行线、列线信号配合起来作适当处理,才能确定闭合键的位置。适当处理,才能确定闭合键的位置。 2) 矩阵式键盘按键的识别 识别按键的方法很多,其中,最常见的方法是扫描法。 按键按下时,与此键相连的行线与列线导通,行线在无键按下时处在高电平。显然,如果让所有的列线也处在高电平,那么,按键按下与否不会引起行线电平的变化,因此,必须使所有列线处在低电平。只有这样,当有键按下时,该键所在的行电平才会由高电平变为低电平。CPU根据行电平的变化,便能判定相应的行有键按下。 3) 键盘的编码 对于独立式按键键盘,因按键数量少,可根据实际需要灵活编码。对于矩阵式键盘,按键的位置由行号和列号惟一确定,因此可分别对行号和列号进行二进制编码,然后将两值合成一个字节,高4位是行号,低4位是列号。10.4.4 键盘的工作方式 对键盘的响应取决于键盘的工作方式,键盘的工作方式应根据实际应用系统中CPU的工作状况而定,其选取的原则是既要保证CPU能及时响应按键操作,又不要过多占用CPU的工作时间。通常,键盘的工作方式有三种,即编程扫描、定时扫描和中断扫描。 1. 编程扫描方式 编程扫描方式是利用CPU完成其它工作的空余时间,调用键盘扫描子程序来响应键盘输入的要求。在执行键功能程序时,CPU不再响应键输入要求,直到CPU重新扫描键盘为止。2. 定时扫描方式 定时扫描方式就是每隔一段时间对键盘扫描一次,它利用单片机内部的定时器产生一定时间(例如10 ms)的定时,当定时时间到就产生定时器溢出中断。CPU响应中断后对键盘进行扫描,并在有键按下时识别出该键,再执行该键的功能程序。 3. 中断扫描方式 采用上述两种键盘扫描方式时,无论是否按键,CPU都要定时扫描键盘,而单片机应用系统工作时,并非经常需要键盘输入,因此,CPU经常处于空扫描状态。 为提高CPU工作效率,可采用中断扫描工作方式。其工作过程如下:当无键按下时,CPU处理自己的工作,当有键按下时,产生中断请求,CPU转去执行键盘扫描子程序,并识别键号。10.4.5 实例分析实例分析 例10.5 如图10-13所示,编程实现4x4键盘,按“0”号键在数码管显示“0”,按“1”号键在数码管显示“1”,.,按“F”号键在数码管显示“F”。 分析: 在单片机应用系统中,键盘是人机对话不可缺少的组件之一。在按键比较少时,我们可以一个单片机I/O口接一个按键,但当按键需要很多,I/O资源又比较紧张时,使用矩阵式键盘无疑是最好的选择。 4x4矩阵键盘是运用得最多的键盘形式,也是单片机入门必需掌握的一种键盘识别技术,下面我们就以实例来说明一下4 x 4矩阵键盘的识别方法。如下图所示,我们把按键接成矩阵的形式,这样用8个I/O口就可以对16个按键进行识别了,节省了I/O口资源。 (1)我们的识别思路是这样的,初使化时我们先让P1口的低四位输出低电平,高四位输出高电平,即让P1口输出0 xF0。 (2)扫描键盘的时候,我们读P1口,看P1是 否还为0 xF0,如果仍为0 xF0,则表示没有按键按下;如果不0 xF0,我们先等待10ms左右,再读P1口,再次确认是否为0 xF0,这是为了防止是 抖动干扰造成错误识别,如果不是那就说明是真的有按键按下了,我们就可以读键码来识别到底是哪一个键按下了。 (3)识别的过程是这样的,初使化时我们让P1口的低四位输出低电平,高四位输出高电平,确认了真的有按键按下时,我们首先读P1口的高四位,然后P1口输出 0 x0F,即让P1口的低四位输出高电平,高四位输出低电平,然后读P1口的低四位,最后我们把高四位读到的值与低四位读到的值做或运算就得到了该按键的 键码。就可以知道是哪个键按下了。 (4)以0键为例,初使化时P1输出0 xF0,当0键按下时,我们读高四位的状态应为1110,即P1为0 xe0,然后让P1输出0 x0F,读低四位产