1602全过程C语言编程

上传人:微*** 文档编号:168048018 上传时间:2022-11-07 格式:DOCX 页数:67 大小:750.91KB
收藏 版权申诉 举报 下载
1602全过程C语言编程_第1页
第1页 / 共67页
1602全过程C语言编程_第2页
第2页 / 共67页
1602全过程C语言编程_第3页
第3页 / 共67页
资源描述:

《1602全过程C语言编程》由会员分享,可在线阅读,更多相关《1602全过程C语言编程(67页珍藏版)》请在装配图网上搜索。

1、51单片机系列1 60 21602字符液晶在实际的产品中运用的也比较多了,前几天留意了一下,发现宿舍门 前的自动售水机就是采用的1 602液晶进行显示的。而且对于单片机的学习而言,掌握1602 的用法是每个学习者必然要经历的过程。在此,我将使用1602过程中遇到的问题以及感 受记录下来,希望能够给初学者带来一点指导,少走点弯路。所谓1602是指显示的内容为16* 2,即可以显示两行,每行16个字符。目前市面 上字符液晶绝大多数是基于HD44780液晶芯片的,控制原理是完全相同的,因此基于 HD44780写的控制程序可以很方便地应用于市面上大部分的字符型液晶。1602液晶的正面(绿色背光,黑色字

2、体)1602液晶背面(绿色背光,黑色字体)背光白色字体字符型LCD1602通常有14条引脚线或16条引脚线的LCD,多出来的2条线是 背光电源线VCC(1 5脚)和地线GND(16脚),其控制原理与1 4脚的LCD完全一样,引脚 定义如表所示:引脚号引脚g电平输入,输出作用1Uss电源地2Ucc电源(+5U)3Uee对比洞整电压4RS0/1输入然疑5R/W0/1输入即向LCD写入指令或数据 “从LCDi矣取信息6E1,10输入便能信号,1吋渉取信息、 1。(下降沿)舲指令7DBO0/1输入/输出数据总线line。(最低位)8DB10/1输入,输出数据总线linel9DB20/1输入/治出数据总

3、线1ine210DB30/1箱!入,播出数据总线Une311DB40/1输入输出数据总线line412DB50/1输入,输出数据总线lines13DB60/1输入/输出数据总线line614DB70/1输入输出数据总线】ine7(最髙位)15AUccD背光电源正极16K接地D背光电源负极HD44780 内置了 DDRAM、CGROM 和 CGRAM。DDRAM就是显示数据RAM,用来寄存待显示的字符代码。共80个字节,其地址和屏幕的对应关系如卜.表:显示位置123456740DDRAM地址第一行0OH01H02H03H04H05H06H27H第二行40H41H42H43H115H46H67H也

4、就是说想要在LCD1602屏幕的第一行第一列显示个A字,就要向DDRAM的 OOH地址写入“字的代码就行了。但具体的写入是要按LCD模块的指令格式来进行的, 后面我会说到的。那么一行可有40个地址呀?是的,在1602中我们就用前16个就行了。 第二行也样用前16个地址。对应如下:DDRAM地址与显示位置的对应关系f)i OOH 01H 02H 03H 04H 05H 06H 07H 08H 09H OAH OBH OCH ODH OEH OFH j :40H 41H 42H 43H 44H 45H 46H 47H 48H 49H 4AH 4BH 4cH UDH EH 4FH iIJ(事实上我们

5、往DDRAM里的OOH地址处送个数据,譬如0x31(数字1的代码) 并不能显示1出来。这是个令初学者很容易出错的地方,原因就是如果你要想在DDRAM 的00H地址处显示数据,则必须将00H加上80H,即80H,若要在DDRAM的01 H处 显示数据,则必须将01 H加上80H即81 H。依次类推。大家看一下控制指令的的8条: DDRAM地址的设定,即可以明白是怎么样的一回事了)1602液晶模块内部的字符发生存储器(CGROM)已经存储了 160个不同的点阵字 符图形,如下表所示,这些字符有:阿拉伯数字、英文字母的大小写、常用的符号、和日文 假名等,每个字符都有一个固定的代码,比如大写的英文字母

6、“A”的代码是01000001 B (41H),显示时模块把地址41H中的点阵字符图形显示出来,我们就能看到字母“A”CGRO!中字符码与字字符字模关系对奥表(20 00010010 0011 0100 0101 0110 0111 100010011010 1011 H00 1101 11101111oxkOOOCCG RAN (1)00P、戸yW瞑PoxxOOOli! 1旧回o I心后qx*x0010(3)IZIBIRIblrl四加e.xx00:1(4)1#|3|C|S|c|s|Z5M&mxxxOIOC0*|4|D|T|d|t叵GoxkOIOI15i|5|ElU|e|u|币后MXxxOl

7、10&|6|F|U|f|u|引力目,)000(0111*331酮向芹冈目 x*l9IIIVIi|y|司吁HoomlOO(3) J*|5|J|Z|J|Z|同5xxxxlOHH) 1+ISIKIC |k|(|旧口声万MXXXllOC(S)/L用1111向G年円mxmIIOI(6) JEHHIIlnlH国麻*(7) |-lINrinH回I肝JOUU1111(8) J l?IOl_lo*ly|U|?|Bo1上表中的字符代码与我们PC中的字符代码是基本一致的。因此我们在向DDRAM 写C51字符代码程序时甚至可以直接用P1 =A这样的方法。PC在编译时就把“A”先转为 41H代码了。字符代码OxOO-O

8、xOF为用户自定义的字符图形RAM(对于5X8点阵的字符,可以 存放8组,5X10点阵的字符,存放4组),就是CGRAM 了。后面我会详细说的。0x20x7F为标准的ASCII码,OxAOxFF为日文字符和希腊文字符,其余字 符码(0x1 0x1 F及0x80x9F)没有定义。那么如何对DDRAM的内容和地址进行具体操作呢,面先说说HD44780的指令 集及其设置说明,请浏览该指令集,并找出对DDRAM的内容和地址进行操作的指令。共 11条指令:1 .清屏指令指令功能指令编码齬 /HSRSR/VDB7DB6DBSDBUDB3DB2DB1DBO清屏0电00000011.611功能:清除液晶显示器

9、,即将DDRAM的内容全部填入空白的ASCII码20H;光标归位,即将光标撤冋液晶显示屏的左上方;将地址计数器(AC)的值设为。2.光标归位指令1指令功能指令编码执行 时间 RSRSR/WD87DB6DBSDBDB3DB2OB1DBD光标归位000000001X1.611功能:把光标撤冋到显示器的左上方;把地址计数器(AC)的值设置为;保持DDRAM的内容不变3 .进入模式设置指令指令功能指令编码牖 /USRSR/WDB7DB6DBSDBHDB3DB2DB1DBO逬入模式设置00000001I/DSiiO功能:设定每次定入1位数据后光标的移位方向,并且设定每次写入的个字符是否移动。参数设定的情

10、况如所示:位名设置I/D=写入新数据后光标左移1 =写入新数据后光标右移S0=写入新数据后显示屏不移动1 =写入新数据后显示屏整体右移1个字4 .显示开关控制指令指令功能指令编码駆 /USRSR/WDB7DB6DBSDBDB3DB2DB1DBO显示开关控制0000001DCB功能:控制显示器开/关、光标显示/关闭以及光标是否闪烁。参数设定的情况如下:位名设置D0=显示功能关1 =显示功能开C0=无光标1 =有光标B0=光标闪烁1 =光标不闪烁5 .设定显示屏或光标移动方向指令指令功能指令编码牆 /USRSR/WDB7DB6DBSDBDB3DB2DB1DBO聯齬關000001S/CR/LXX功能

11、:使光标移位或使整个显示屏幕移位。参数设定的情况如:S/CR/L设定情况00光标左移1格,且AC值减101光标右移1格,且AC值加110显示器上字符全部左移一格,但光标不动11显示器上字符全部右移一格,但光标不动6 .功能设定指令指令功能指令编码办行 时向 /USRSR/VDB7DB6DBSDB4DB3DB2DB1DBO功能设定0001DLNFXx40功能:设定数据总线位数、显示的行数及字型。参数设定的情况如下:位名设置DL0=数据总线为4位1 =数据总线为8位N0=显示1行1 =显示2行F0=5x7点阵/每字符1 = 5x 10点阵/每字符7 .设定CGRAM地址指令指令功能指令编码嬌 /U

12、SRSR/WDB7086DB5DB4DB3DB2DB1DB0设定CGRAM 地址0001CGRAM的地址(6位)40功能:设定下个要存入数据的CGRAM的地址。8 .设定DDRAM地址指令I指令功能指令编码豊行 时间 /USRSR/WDB7DB6DBSDB4DB3DB2DB1DB0设定DDRAM 地址001CGRAM的地址(7位)40功能:设定个要存入数据的CGRAM的地址。(注意这里我们送地址的时候应该是0x80+ Address,这也是前面说到写地址命令的时候要加上0x80的原因)9 .读取忙信号或AC地址指令指令功能指令编码时恂 /USRSR/WDB7DB6DB5DB4DB3DB2DB1

13、DB0族取忙对 或AC先灌号01FBAC内容(7位)40功能:1读取忙碌信号BF的内容,BF= 1表示液晶显示器忙,暂时无法接收单片机送来的数据或指令;当BF=O时,液晶显示器可以接收单片机送来的数据或指令;读取地址计数器(AC)的内容。! .数据写入DDRAM或CGRAM指令一览指令功能指令编码时拘 /USRSR/WDB70B6DBSDB4DB3DB2。“DBO数据写入到 DDRAM或CGRAM10要写人的数据07-00H0功能:将字符码写入DDRAM,以使液晶显示屏显示出相对应的字符;将使用者自己设计的图形存入CGRAM。11 .从CGRAM或DDRAM读出数据的指令一览指令功能指令编码嬌

14、 /usRSR/WDBZDB6DBSDB8DB3DB2DH1DBO从CGRAM或 DDRAMi笑出 数据,11要读岀的数据07-0040功能:读取DDRAM或CGRAM中的内容。基本操作时序:读状态输入:RS=L, RW=H, E=H输出:DBDB7=状态字写指令输入:RS=L, RW=L, E=下降沿脉冲,DBDB7=指令码输出:无读数据输入:RS=H, RW=H, E=H输出:DBDB7=数据写数据输入:RS=H, RW=L, E=下降沿脉冲,DBDB7=数据输出:无呵呵,看到这么多的控制指令希望你没有头晕。其实这么多的指令刚开始的时候没 有必要全部掌握,随着学习的深入可以再尝试去用更复杂

15、的控制指令。卜.面让我们起驱动 1602的液晶吧。卜,面是我的液晶的连接图,用的是那种蓝底白字的液晶,其实蓝底白字和 那种绿底黑字的液晶唯一的区别就是颜色的问题,至于用哪种液晶,就看各位自己的喜好 咯。这就是我做测试用的最小系统,单片机是STC89c51 6,晶振为12M。液晶为蓝底 白字的那种1602。当我们硬件连接错误,或者程序错误时就会出现图这种情况,就是上排显示16的 白色的块(蓝底黑字的液晶则显示的是16个黑块)。面我们来驱动1602吧在1602的上排显示“LCD1602 check ok”下排显示,study up”程序中没有用到忙检测,而是用的是延时函数来替代忙检测# inclu

16、de包含头文件,这个嘛,就不用多说了# define uint unsigned int 预定义一下# define uchar unsigned charsbit rs=P3A 5;/1602的数据/指令选择控制线sbit rw=P3A 6; 1602的读写控制线sbit en=P3A 7;/1602的使能控制线/*P2 口接1602的D0D7,注意不要接错了顺序,我以前可在这上面吃过亏/ uchar code table =LCD1602 check ok; 要显示的内容 1 放入数组 tablet uchar code tablel = study up;要显示的内容 2 放入数组tab

17、lelvoid delay(uint n)延时函数uint x,y;for(x= n;x 0;x-) for(y= 110;y0;y-); void lcd_wcom(uchar com) /1602 写命令函数 rs=O;选择指令寄存器rw= 0;选择写P2=com;把命令字送入P2delay(5);延时小会儿,让1602准备接收数据en=1J使能线电平变化,命令送入1602的8位数据口en= 0; ) void lcd_wdat(uchar dat) /1602 写数据函数 rs=1;选择数据寄存器rw=0; 选择写P2=dat;把要显示的数据送入P2delay(5);延时小会儿,让160

18、2准备接收数据en=1J使能线电平变化,数据送入1602的8位数据口en= 0;)void lcd_init()/1602 初始化函数(Icd_wcom(0x38);8 位数据,双列,5* 7 字形lcd_wcom(0x0c);开启显示屏,关光标,光标不闪烁Icd_wcom(0x06);显示地址递增,即写个数据后,显示位置右移一位Icd_wcom(0x01);清屏)void main()主函数(uchar n,m= 0;lcd_init();液晶初始化Icd_wcom(0x80); 显示地址设为80H (即00H,)上排第一位 for(m=0;m16;m+ + )将table口中的数据依次写入

19、1602显示(lcd_wdat(tablem);delay(200);)Icd_wcom(0x80+ 0x44); 重新设定显示地址为0xc4,即卜,排第5位 for(n=0;n8;n+ +) 将tablel 口中的数据依次写入1602显示 (Icd_wdat(table1 n);delay(200);)while(1);动态停机程序写好后烧写进单片机,现在让我们看看效果吧这就是显示的效果,你做成功了吗?面让我们来看看如何显示个自定义的字符吧我们从CGROM表上可以看到,在表的最左边是一列可以允许用户自定义的 CGRAM,从上往下看着是16个,实际只有8个字节可用。它的字符码是() 00000

20、111这8个地址,表的面还有8个字节,但因为这个CGRAM的字符码规定 一 2位为地址,3位无效,4-7全为零。因此CGRAM的字符码只有最后三位能用也就是8 个字节了。等效为0000X111, X为无效位,最后三位为000 111共8个。如果我们要想显示这8个用户自定义的字符,操作方法和显示CGROM的样,先 设置DDRAM位置,再向DDRAM写入字符码,例如“A”就是41 H。现在我们要显示CGRAM 的第一个自定义字符,就向DDRAM写入000000OOB(OOH),如果要显示第8个就写入 00000111 (08H),简单吧!好!现在我们来看怎么向这八个自定义字符写入字模。有个设置CG

21、RAM地址的指 令大家还记得吗?赶快再找出来看看。指令功能指令编码離 /USRSR/WDB7DB6DBSDB4DB3DB2DB1DHI1设定CCRAM 地址0001CGRAN的地址(地)k0从这个指令可以看出指令数据的高2位已固定是01,只有后面的6位是地址数据, 而这6位中的高3位就表示这八个自定义字符,最后的3位就是字模数据的八个地址了。 例如第一个自定义字符的字模地址为01000000 010001 1 1八个地址。我们向这8个字 节写入字模数据,让它能显示出“。C”地址:01000000数据:00010000图小:OOOBOOOO0100000100000110OOOOOHBO0100

22、001000001001ooooioob0100001100001000oooobooo0100010000001000oooobooo0100010100001001OOOOBOOB0100011000000110OOOOOBBO0100011100000000oooooooo下面我们写一段程序让这8个自定义字符显示出个心的图案:(由于上面那个显 示程序已经有很详细的注释了,因此这个程序只对与上个程序不同的地方写注释)# include# define uint unsigned int# define uchar unsigned charsbit rs= P3A 5;sbit rw= P

23、3A 6;sbit en= P3A 7;uchar code table = 0x03,0x07,OxOf,Ox 1 f,0x1 f,0x1 f,0x1 f,0x1 f,0x18,0x1 E,0x1 f,0x1 f,0x1 f,0x1 f,0x1 f,0x1 f,0x07,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1 0,0x1 8,0x1 c, 0x1 E, 0x1 E, 0x1 E, 0x1 E, 0x1 E,OxOf,0x07,0x03,0x01,0x00,0x00,0x00,0x00,0x1f,0x1f,0x1f,0x1f,0x1f,0x0f,0x07,

24、0x01,0x1 f, 0x1 f, 0x1 f, 0x1 f, 0x1 f, 0x1 c, 0x1 8,0x00,0x1 c,0x18,0x10,0x00,0x00,0x00,0x00,0x00;心图案/* uchar code table1 = 0x10,0x06,0x09,0x08,0x08,0x09,0x06,0x00 /字符 */void delay(uint n)(uint x,y;for(x= n;x 0;x-)for(y= 110;y0;y-);void lcd_wcom(uchar com)(rs=O;rw= 0;R2= com;delay(5);en= 1;en= 0;)v

25、oid lcd_wdat(uchar dat)rs= 1;rw= 0;P2= dat;delay(5);en= 1;en= 0;)void lcd_init()|Icd_wcom(0x38);lcd_wcom(0x0c);Icd_wcom(0x06);Icd_wcom(0x01);)void main()(char m= 0;lcd_init();Icd_wcom(0x40);设定 CGRAM 地址for(m= 0;m64;m+ )将心型代码写入 CGRAM 中Icd_wdat(tablem);Icd_wcom(0x85);设定上排的显示位置for(m = 0;m4;m + + )显示心型图案

26、的上半部分lcd_wdat(m);Icd_wcom(0xc5);将显示坐标转移到卜.排和上排相对应的地方for(m = 4;m KeyOverTime ) (KeyCount = 0 ;KeyOverTime = KEY_QUICK_TIME ;)return NOKEY ;)else是第一次按下则保存键值,以便下次执行此函数时与读到的键值作比较(Last Key = KeyTemp ;保存第一次读到的键值KeyCount = 0 ;延时计数器清零KeyOverTime = KEY_OVER_TIME ; return NOKEY ;)下面是我测试用的主程序(相关头文件未列出,仅仅作测试演示用

27、)void main(void)uint8 KeyValue ;int16 Count ;v_Lcdlnit_f();v_Keylnit_f();CLSLOCATE(3, 1)PRINT(MKey Test)LOCATE(6, 2)SHOW_ICONwhile(1)KeyValue = u8_ReadKey_f();if( KeyValue != NOKEY) LOCATE(1, 2)if( KeyValue = = OxOe )Count+ + ;if( KeyValue = OxOd )Count-;if( KeyValue = = OxOb )Count = 0 ; if( KeyVal

28、ue = = 0x07 )Count = 0 ; HIDE_ICONPRINTD(Count, 5)LOCATE(6, 2)else(/SHOW_ICON)每次执行读键盘函数时,只是对些标忐进行判断,然后退出。因此能够充分的利用CPU的资源。同时可 以处理连发按键。此按键扫描按键函数可以直接放在主函数中。如果感觉按键太过灵敏或者迟钝则改下 相关消抖动的宏定义即可。此函数也可以通过中断标志位进行定时的扫描。此时,需要添加 个定时标志 位,并将相关消抖动的和连击时间的宏定义改小即可。然后在主程序类似下面这样写即可if( KeyTime )定时扫描时间到(KeyValue = u8_ReadKey_

29、f();)具体的工作就交给您去完成啦。看看效果:按键单击连发时候的截图至此,关于单个按键的学习就告一段落了,您是否经明白了。如果您还不明白,那么把这个程序好好的 看看,并画下流程图,分析分析。估计您就会恍然大悟。关键是思路要转换过来。下而我们来看看多个按键的情况吧般情况下,如果多个按键每个都直接接在单片机的I/O上的话会占用很多的I/O资源。比较合理的种 做法是,按照行列接成矩阵的形式。按键接在每个的行列的相交处。这样対于m行n列的矩阵,可以接 的按键总数是m* n。这里我们以常见的4*4矩阵键盘来讲解矩阵键盘的编程。上图就是矩阵键盘的般接法。这里我们要介绍种快速的键盘扫描法:线反转法(或者称

30、为行列翻转法)。具体流程如。首先,让单片 机的行全部输出0,列全部输出1,读取列的值(假设行接P3 口的高四位,列接低四位)。即P3= OxOf!此 时读列的值,如果冇键按,则相应的列读冋来的值应该为低。譬如此时读冋来的值为OxOe ;即按键列 的位置已经确定。这时反过来,把行作为输入,列作为输出,即P0= OxfO ;此时再读行的值,如果按键 仍然被按,则相应的行的值应该为低,如果此时读冋来的值为OxeO,则确定了行的位置。说到这里, 您应该笑了,知道了一个按键被按下的行和列的位置,那么就可以肯定确定它的位置了。我们把读回来的 行值和列值进行或运算。即OxeO| Ox 0e即Oxee。那么O

31、xee就是我们按的按键的键值了。怎么样。 只需几步就可以判断所有的键值,简单吧。下面再结合一个例子具体看看。/*# 此模块所需相关支持库#includeregx52.h# define uint8 unsigned char# define uintl6 unsigned int# 与硬件连接相关的定义及宏定义和操作宏*/# define KEYBOARD P3键盘连接到单片机上的端口位置# define READ_ROW_ENLABLE KEYBOARD = OxOf ;读端口之前先把相应U置位(由基本51单片机特性决定的)# define READ_COL_ENLABLE KEYBOARD

32、 = OxfO ;根据实际硬件连接情况修改,模块内相关的宏定义及常数宏,*/# define NOKEY Oxff定义无键按下时的返回值# define DELAY_COUNT 2消抖时间常数# 此模块所需的全局或者外部变量*/ bit bdata StartScan = 0 ;此变量需放在定时中断中置位.按键扫描函数,按下去后经去抖,确定按下# 则返回键值。 15:无键按下则返回Oxff;此函数需要定时器的支持(去抖.)*uint8 u8_KeyBoardScan_f()(static uint8 DelayCount = 0 ;uint8 KeyValueRow = 0 ;uint8 Ke

33、yValueCol = 0 ;uint8 KeyValue = 0 ;if( StartScan )开始扫描,StartScan在定时中断中置位(StartScan = 0 ;清除开始扫描标忐位,避免多次重复执行扫描程序读入按键状态前先向相应端口写1(由基本51单片机硬件结构决定)READ ROW ENLABLEif( ( KEYBOARD & OxOf ) != OxOf ) 判断是否有键按下DelayCount+ +;if( DelayCount = DELAY_COUNT )有键按下则判断延时去抖的时间是否达到(return NOKEY ;)else消除了抖动(if( ( KEYBOAR

34、D & OxOf ) != OxOf )再次判断是否按键真的按下DelayCount = 0 ;确定按下后,延时去抖计时器清KeyValueRow = KEYBOARD & OxOf ; 取得彳了码准备读列,先向相应端口写1(由基本51单片机硬件结构决定)READ_COL_ENLABLEif ( (KEYBOARD & OxfO) != OxfO ) 反转,读列码(KeyValueCol = KEYBOARD & OxfO ; 取得列码合并取得的行码和列码,即是相应按键的键值switch( KeyValueCol | KeyValueRow)(case 0x77 : Key Value = 0

35、 ; break ;case 0xb7 : KeyValue = 1 ; break ;case 0xd7 : KeyValue = 2 ; break ;case 0xe7 : KeyValue = 3 ; break ;case 0x7b : KeyValue = 4 ; break ;case Oxbb : KeyValue = 5 ; break ;case Oxdb : KeyValue = 6 ; break ;case Oxeb : KeyValue = 7 ; break ;case 0x7d : KeyValue = 8 ; break ;case Oxbd : KeyVal

36、ue = 9 ; break ;case Oxdd : KeyValue = 10 ; break ;case Oxed : KeyValue = 11 ;break ;case 0x7e : KeyValue = 12 ;break ;case Oxbe : KeyValue = 13 ;break ;case Oxde : KeyValue = 14 ; break ;case Oxee : KeyValue = 15 ; break ;default : return NOKEY ;return KeyValue ; else DelayCount = 0 ; return NOKEY

37、;) else DelayCount = 0 ; return NOKEY ;)else(DelayCount = 0 ;return NOKEY ;) void v_T0_lsr_f( void ) interrupt I NTERRUPT_TI MER2_OVERFLOWStartScan模块调试主函数仅作演示用,主函数除按键扫描外的函数并没在这里给出void v_lnit_T2_f( void )T2CON = 0x04 ;T2MOD = 0x00 ;TH2= 0xd8;RCAP2H = 0xd8 ;TL2= OxfO;RCAP2L = OxfO ;ET2= 1 ;TR2= 1 ;voi

38、d main( void )(uint8 readkey = 0 ;v_lnit_T2,f();v_Lcdlnit_f();LOCATE( 1,1)PRINT(H4*4KeyBoard Test*1)EA = 1 ;LOCATE( 3, 2)while( 1 )(SHOW_ICONreadkey = u8_KeyBoardScan_f() if) readkey != NOKEY)(PRINTN) readkey , 2)LOCATE) 3, 2) continue ;elsecontinue ;)呵呵,按键扫描程序己经注释的很详细了。我就不多费嘴后了。如果有不清楚的地方,欢迎跟帖讨论。 下面

39、是按键测试的截图我的门己搭建的实验板OK, Enioy it !自此按键检测告段落。下次如果再讲按键。将会讨论另外 种按键的写法:基于状态机 的按键程序设计。欢迎讨论。tiankai (2010-2-05 16:37:53)晨辉教你轻松学51按键篇对于个由单片机为核心构成的系统而言。输入通道是相当重:要的。可以看到几乎每样基于单片机的产 品都有人机交互的部分。如各种仪器设备上的各种按钮和开关,以及我们手机上的键盘,MP3上的按键等 等。最常见的输入部分,莫非就是按键了。对于大多数初学者而言,编写个好的按键程序是一件颇为头 疼的事情。于是乎在网上乱搜气,程序倒是找到了不少,但是看了半天依然是不明

40、白。或者在某某论坛 上面发帖“跪求XX按键程序,大虾帮忙.:如果你偶然间进了这个论坛,又偶然看到了这个帖子,而且恰 好你对按键程序的写法也不是很清楚,那么我希望你能够静静的看完这个帖子。如果你觉得对你很有帮助, 那么我希望你能够在以后的日子中能够坚持到这个论坛来,起交流学习,分享自己学习过程中的喜悦或 者起探讨棘手的问题,这是我写这个帖子的最大的初衷了。K,不能再说了,再说就变成水帖了。那么 我们开始吧。按键的种类很多。不过原理基本相似。下面我们以 种轻触开关为例讲解按键程序的写法。这种轻触开关大家不陌生吧_A一一般情况下,按键与单片机的连接如下面这幅图所示。U1(图中电阻值一般去4.7k10

41、k之间,对于内部端口有上拉电阻的单片机则可省略此电阻)单片机对于按键的按与否则是通过检测相应引脚上的电平来实现的。对于上图而言,当P17引脚上面的 电平为低时,则表示按键已经按下。反之,则表明按键没有按下。我们在程序中只要检测到了 P17引脚I: 面的电平为低了,就可以判断按键按。呵呵,简单吧。等会,您先别乐呵,话还没说完呢。面我们来 看看,当按键按下时,P17引脚I:面的波形是怎么变化的。上图是个理想波形图,当按键按下时,P1 7 U的电平马上被拉低到0V 了。当然理想的东西都是不现实 的。所以我们还是看看现实的波形图吧。看出什么区别来了没。呵呵,只耍你不是傻子我相信都能看出其中的区别。由丁

42、按键的机械特性。当按键 闭合时,并不能马上保存良好的接触,而是来冋弹跳。这个时间很短,我们的手根本感觉不出来。但是对 于一秒钟执行百万条指令的单片机而言,这个时间是相当的长了。那么在这段抖动的时间内,单片机可能 读到多次高低电平的变化。如果不加任何处理的话,就会认为已经按,或者松开很多次了.而事实上, 我们的手一直按在按键k,并没有重复按动很多次。要想能够正确的判断按键是否按下就要避开这段抖动 的时间。根据一般按键的机械特点,以及按键的新旧程度等而言,这段抖动的时间一般在5Ms20Ms之 间。看到这里你明白了该如何做了吧。看看下面的这个流程图,你应该不陌生吧。这个流程是好多教科书上的做法可惜,

43、误导了好多人。为什么呢。因为它根本就没有考虑实际情况。我 们根据这幅流程图来写它的代码看看。unsigned char v_ReadKey_f( void )(unsigned char KeyPress ;if ( P17 = = 0)(Delay(20)J延时 20Mslf( P17 = 0)(KeyPress = 1 ;While( !P17): 等待释放)elseKeyPress = 0 ;)这样个程序,相信对很多初学者而言都不陌生。因为好多书上基本都是这样的个流程和写法。可 是当有天,我们想做个数码管加按键调整的时钟,发现当我们按健按下去的时候,数死管就不亮了。 为什么呢。原因就在这

44、个键盘扫描函数。平常没有按键按下还好。一旦有键按下,它先是浪费了 CPU的大 部分时间(就是那个什么事情都没做的延时20Ms函数)然后,乂霸占CPU(就是哪个死死等在那里的 while (P17):语句)直到按键释放。对于这种情况我们是忍无可忍的,那么就让我们彻底的抛弃它吧。 那么到底按键扫描函数改如何写呢所谓众里寻她千百度,蓦然回首,那人却在灯火阑珊处。如果我们 把CPU延时的那20Ms拿出来去做其它事情,那么不就充分利用CPU的时间了吗。而一般情况下我们只 要前沿去抖动就可以了。也就是说了,我们只需在按键按下后去抖就可以了,对于按键的释放抖动可以不 必要过于关注。当然这主要和应用的场合有关

45、。个能仃效识别按键按下并支持连发功能的按键经能够 应用到大多数的场合了。下面以四个独立按键的处理程序为例来讲解(支持单击和连发)#includeHregx52.hnsbit KeyOne = P1A 0 ;sbit KeyTwo = P1 A 1 ;sbit KeyThree = P1A 2 ;sbit Key Four = P1A 3 ;# define uintl6 unsigned int# define uint8 unsigned char# define NOKEY Oxff# define KEY_WOBBLE_TIME 500去抖动时间(待定)# define KEY_OVER_TIME 15000等待进入连击时间(待定),该常数要比正常按键时间要长,防止非冃的性进入连击模式#define KEY_QUICK_TIME 1000 等待按键抬起的连击时间(待定) void v_Keylnit_f( void )(KeyOne = 1 ;按键初始化(相应端口写1)

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!