为什么以下汇编程序和编译程序不能使LED灯以灭2秒、亮2秒的方式循环

已有天涯账号?
这里是所提的问题,您需要登录才能参与回答。
"天涯问答"是天涯社区旗下的问题分享平台。在这里您可以提问,回答感兴趣的问题,分享知识和经历,无论您在何时何地上线都可以访问,此平台完全免费,而且注册非常简单。
led灯的英文介绍
led灯的英文介绍
09-11-27 &匿名提问 发布
只要把汇编指令都写出来了,你就可以到指令表中找到每一条指令所对应的机器码,然后你只要在机器码后面加上操作数即可,比如,把一个30H单元送入A累加器;指令是这样的:MOV A , 30H .那么你可以在指令表中查到执行这条指的机器码是,但是由于这条指令后面的那个30H单元的数是根据你的要求在不断的变的,机器没规定你只能用30H单元,所以这个30的操作数必须由你填,它们和在一块儿,这条指令的机器码是:11 0000用十六进制来表示:E530,很明显前两位E5是机器指定的,而后两位30是你自己加进去的。共是十六位,占用两个字节……。你说的LED灯闪烁,不知是指的流水灯还是一只发光二极管在不停地闪烁?但不管是哪一种,有一点很重要。你在编写此程序时必须要考虑延时,因为51单片机的晶体振荡器最低频率可能是6M(具体数值我已记不清了)。也就是说单片机的每一个机器周期所占用的时间仅2微秒,如果你不考虑延时的话,那么你设计的那盏灯,它闪烁的结果是;亮2微秒,熄2微秒,也就是说每一秒钟要亮暗50万次,肉眼看这盏灯根本就不会有熄灭的时候,只是比不闪的灯暗了一半。我们生活中用的白炽灯,每秒钟亮暗100次,你能感觉出灯泡有熄灭的时候吗?更何况那是50万次啊!比如设计流水灯的程序,不妨可以这样考虑它的算法。计数寄存器的高八位加上低八位,合起来也只有十六位,它能数的数最大也就是65535,就算单片机用的是最低的6M的晶体振荡器,一个机器周期是12个机器节拍,所以,每一个机器周期占用2微秒时间,从0数到65535,仅用了131070微秒就数完了,约130毫秒,如果就按这个延时去改变灯的亮暗时间,那么这盏灯每秒钟要亮暗3、4次,肉眼虽然能够看到灯有熄灭的时间了。但是眼睛看这样的灯总不会那么舒服,所以至少应让它延时到1秒钟亮暗一次。为了计算方便,就让计数器数100毫秒的时间吧!等计数器数到100毫秒后,就让它再数一次,然后再数一次……,等它数满5次后,这就是500毫秒(半秒钟),然后,我们再去改变灯的亮暗状态。这个程序可以这样来编: MOV  A ,#0FEH
;最低位设为0 MOV  P1, A
;点亮最低位灯 MOV  TCON,#10H
;T1为方式1,定时BEGIN: MOV  R7  ,#05H
;设循环5次STAR: MOV  TH1  #3CH
;计数器数100毫秒 MOV  TL1  #AFH SETB  TR1
;开始计数ROU: JBC   TF1
;100毫秒到否? SJMP ROU
        ;等待到100毫秒SE: CLR TR1
;关闭计数器 DJNZ  R7   STAR
        ;5次循环到否?
RL  A
;把0向左移一位         MOV  P1 ,A
;改下一只灯亮 SJMP BEGIN
51的单片机     ORG  0000HMAIN:MOV R2,#2  L1:MOV R3,#200  L2:MOV R4,#200  L3:NOP     NOP     DJNZ R4,L3     DJNZ R3,L2     DJNZ R2,L1     CPL P1.7     JMP MAIN     ENDMedwin编写C51汇编
八只LED灯做流水灯实验单片机在上电初始后,其各端口输出为高电平。如果我们现在想让接在P1.0口的LED1亮,那么我们只要把P1.0口的电平变为低电平就可以了。想让LED1灭,LED0亮,只需将P1.0升高,P1.1变低,LED1就熄灭LED2随后既点亮!依始类推如下所示8只LED变会一亮一暗的做流水灯了.P1.0低、P1.0高、P1.1低、P1.1高、P1.2低、P1.2高、P1.3低、P1.3高、P1.4低、P1.4高、P1.5低、P1.5高、P1.6低、P1.6高、P1.7低、P1.7高、返回到开始、程序结束。我们不能说P1.1你变低,它就变低了。因为单片机听不懂我们的汉语的,只能接受二进制的“1、0......”代码。我们又怎样来用二进制语议论使单片机按我们的意思去工作呢?为了让单片机工作,只能将程序写为二进制代码交给其执行;早期单片机开发人员就是使用人工编写的二进制代码交给单片机去工作的。今天,我们不必用烦人的二进制去编写程序,完全可以将我们容易理解的“程序语言”通过“翻译”软件“翻译”成单片机所需的二进制代码,然后交给单片机去执行。这里的“程序语言”目前主要有汇编和C两种;在这里我们所说的“翻译”软件,同行们都叫它为“编译器”,将“程序语言”通过编译器产生单片机的二进制代码的过程叫编译。前面说到,要想使LED1变亮,只需将对应的单片机引脚电平变为低电平就可以了。现在让我们将上面提到的8只LED流水灯实验写为汇编语言程序。“汉语”语言 汇编语言 开始: star: P1.0低 clr p1.0 P1.0高 setb p1.0 P1.1低 clr p1.1 P1.1高 setb p1.1 P1.2低 clr p1.2 P1.2高 setb p1.2 P1.3低 clr p1.3 P1.3高 setb p1.3 P1.4低 clr p1.4 P1.4高 setb p1.4 P1.5低 clr p1.5 P1.5高 setb p1.5 P1.6低 clr p1.6 P1.6高 setb p1.6 P1.7低 clr p1.7 P1.7高 setb p1.7 返回到开始 ljmp star 结束 end 这里用到了四条汇编指令:clr、 setb、 ljmp 、end;clr:是将其后面指定的位清为0;setb:是将其后面指定的位置成1;ljmp:是无条件跳转指令,意思是:跳转到指定的标号处继续运行。end:是一条告诉编译器:程序到此结束的伪指令。伪指令只告诉编译器此程序到此有何 要求或条件,它不参与和影响程序的执行。这里需要说明的是,按汇编语法要求,所编制的程序(下称源程序)之格式和书写要求必须依下列原则:1、源程序必须为纯文本格式文件,如用Windows“附件”中的“记事本”编写的文本文件;2、源程序的扩展名应是 *.ASM; 3、一行只能写一条语句,以回车作为本句的结束,每一语句行长度应少于80个字符(即40个汉字)。 4、每行的格式应为:标号: 命令 参数 ;注释即一行由四部份组成,各部份的顺序不能搞错,依实际要求可以缺省其中的一部份或几部份,甚至全部省去,即空白行。需要使用标号时标号后面必须有“:”(冒号),而命令语句和参数之间必须用空格分开,如果命令有多个参数,则参数与参数之间必须用“,”(逗号)分开,需要注释时注释前必须用“;”(分号),“;”后面的语句可以写任何字符,包括汉字用于解释前面的汇编语句,它将不参与汇编,不生成代码。由于汇编程序对我们还不直观,所以在编写源程序时,应当养成多写注释的习惯,这样有助于今后源程序的阅读和维护。标号是标志程序中某一行的符号名,编译后标号的数值就是标号所在行代码的地址。在宏汇编ASM51中标号的长度不受限制,但标号中不能包含‘:’或其它的一些特殊符号,也不能用汉字,可以用数字作标号,但必须用字母开头。当标号作参数用(如标号作转移地址),在命令后面出现时,必须舍去‘:’(如上面程序中的 LJMP STAR中的 STAR 是不能再有:)。每行只能有一个标号,一个标号只能用在一处,如果有两行用了同一个标号,则汇编时就会出错。由于标号的长度没有限制,可以用有意义的英文或汉语拼音来说明行,使源程序读起来更方便。源程序中的字母不区分大小写,也就是说 star 和 STAR 是一样的,请不要用大小写方式去区分不同的标号:流水灯实验详解二 上一节的实验最后没有得到“流水”显示的效果,主要是单片机执行每条指令的时间很短,我们肉眼无法看到LED的熄灭与点亮。单片机内部能按部就班的自动工作,正是在系统时钟的作用下,内部各逻辑硬件产生各种所需脉冲信号而实现的。这个时钟信号(既晶体振荡信号)的周期称“振荡周期”。我们这个实验中晶体使用的是12MHZ. 在单片机中,要处理最短周期的一条指令需要由12个振荡周期(既晶振振荡周期)组成的,这个叫“机器周期”。 8051核的单片机,大多数指令只用一个机器周期(既单周期),也有双周期和四周期的指令。本实验中用到的SETB P.x和CLR P.x均属于单周期指令,也就是说,执行一句 SETB P.x 用时仅1uS(微秒),CLR P.x 也是1uS;难怪我们前面的程序不能看到流水效果。 现在,将程序改动一下,在每点亮一个LED后,让程序干点别的事,也就是让它等一会再将该LED熄灭,继续执行下面的程序:DDW: ;程序开始 CLR P1.0 ;LED1亮 ACALL DELAY ;调用延时子程序 SETB P1.0 ;LED1灭 CLR P1.1 ;换灯,同上 ACALL DELAY   SETB P1.1   CLR P1.2   ACALL DELAY   SETB P1.2   CLR P1.3   ACALL DELAY   SETB P1.3   CLR P1.4   ACALL DELAY   SETB P1.4   CLR P1.5   ACALL DELAY   SETB P1.5   CLR P1.6   ACALL DELAY   SETB P1.6   CLR P1.7   ACALL DELAY   SETB P1.7   LJMP DDW ;返回到开始循环 DELAY:   ;延时子程序 MOV R1,#50   AD10:     MOV R2,#100   AD11:     MOV R3,#100   DJNZ R3,$   DJNZ R2,AD11   DJNZ R1,AD10   RET ;延时子程序结束,返回到调用处的下一句 END   请将上面的程序保存为 1LED.asm,进行编译,并烧写到AT89S51中,之后将89S51安装到套件的实验部份插座上实验,这回显示的就是“流水灯”的效果了!?回过头,让我们看看延时子程序是怎样工作的:单片机内部有不少寄存器,这些寄存器在单片机通电时,你可以给他写入数据(是单片机按你程序要求写的数据,而不是编程器写的),当第二次给他写入新数据时,前次的数据就被新数据覆盖;当然也可以从寄存器中读取数据。当单片机没有电源供给时,寄存器内部的数据也随即消失;这些寄存器人们叫他RAM,而用编程器将我们编写的程序烧写到单片机中的存储器叫ROM;现在,我们应该清楚:RAM是让程序去使用的,ROM是我们编写的程序存放的地方! 前面说过,单片机内部有不少RAM,本实验用的AT89C51有多少寄存器?我们现在不必关心,现在只须知道单片机内部有名叫R0~R7 的这8个寄存器。这8个寄存器每个都由8个单独的位寄存器组成,最大存放数据为二进制的 ,十六进制 = FF,十进制 = 255。在使用时注意不要大于其有效范围。上面延时程序中,先用到 MOV R1,#50 ,MOV是移动的意思,该句是将50这个十进制数放到R1中;50是立即数,按汇编语言要求前面要加“#”号,汇编语言还规定,十六进制数后面要加“?H”,十六进制数的高位是字母时在字母前面还要加“0”,例如:#0F8H;二进制数后面加“B”,例如:#B。十进制不加,例如:#100。延时程序的第二、三句为: MOV R2,#100 ;MOV R3,#100 ;这两句意思同前。第四句中DJNZ R3,$ 的意思是将 R3 里面的数减 1 后如果 R3 不等于 0 则跳到后面指定的程序位置,这里的“$”既要跳转的程序位置,“$”代表当前语句处,也就是说,R3不等于 0,程序返回再次执行本句。如果R3 减 1 后等于0,程序结束本句,继续执行下面的语句。延时程序的最后一句是RET ,意思是退出本子程序,返回到调用本子程序处的下一句。根据上面的解释,一进入延时子程序首先为R1, R2, R3 寄存器装入我们需要的数据,然后先对R3 进行减数,每次减 1 ,R3 减完后减R2 ,减R2 时就费事啦,因为R2 每减 1 后不为 0 需要跳转到AD11 标号处执行下面的语句,此时R3 再次装入数据100,并且还要再次对R3 进行减数......,R2 减完后减R1,减R1的过程你研究研究看看。 每执行 DJNZ ?Rn,rel (Rn 指 R0~R7,rel 指转移地址)指令一次,需要2个机器周期,单片机需耗时2uS(指本实验),若忽略装数等语句,延时子程序从开始到结束,单片机共耗时100*100*50*2nS,既1000000uS=1秒!若加上装数等语句的耗时,延时时间大于1秒。 到此,我们做的流水灯已成功,原理大致也明白啦,若你自认为这一课你完全明白了,那请你将“流水灯”的流向改变一下,也可以改为两边向内流,内部向外流......,我想你一定能用前面学到的方法实现这些功能。可能有些高手说,前面的编程方法是最最笨的!,不错!但玩单片机初期不必讲究语言的简练,只要能完成预先要求就好,这是初学者要知道的。那么还有更好的编程思路吗?有!请继续学习下节课做流水灯实验详解三在上节课中让 LED 流水是去逐个控制P1端口的每个位来实现的,那么我们在程序一开始就给P1口送一个数,这个数本身就让P1.0先低,其他位为高,然后让这个数据向高位移动不就实现“流水”效果啦?的确如此!可惜,8051没有让P1数据移动的指令,但有对累加器ACC中数据左移或右移的指令,ACC是8051单片机内部算术逻辑单元中的一个“寄存器”(这里叫他寄存器是不正确的,但你可以先这样理解,ACC在指令中常写为A),他在数据传输和数据处理过程中作用十分重要,ACC为8位。他可与片内所有单字节寄存器交换数据,实际上P1和其他端口在单片机中也是一个寄存器。这样我们可以将需移动的数据先放到ACC中,让其移动,然后将ACC移动后的数据再转送到P1口,这样同样可以实现“流水”效果。程序如下:DDW:   ;开始 MOV ACC,#0FEH ;ACC中先装入LED1熄灭的数据(即二进制的 ) MOV P1,ACC ;将ACC的数据送P1口 MOV R0,#7 ;因上句送到?p1口的数据就熄灭了一位,所以将数据再移动7次就完成一个8位流水过程 LOOP:   ;数据移动循环 Rl A ;将ACC中的数据左移一位 MOV P1,A ;把ACC移动过的数据送p1口显示 ACALL DELAY ;调用延时 DJNZ R0,LOOP ;没有移动够7次继续移动 LJMP DDW ;移动完7次后跳到开始重来,以达到循环流动效果 DELAY:   ;延时子程序,就是上节课中的延时子程序 MOV R1,#50   ADl0:     MOV R2,#100   ADl1:     MOV R3,#100   DJNZ R3,$   DJNZ R2,AD11   DJNZ R1,AD10   RET   ;延时子程序结束,返回到调用处的下一句 END   ;本汇编程序到此结束 接下来,将上述程序编译,并烧写到前面我们的实验芯片中,流水效果与第二节课的一样。 其实8051单片机有111条指令,这111条指令好比以前我们使用数字传呼机时的“短语代码”一样,可以用几个“短语代码”去表示一句完整、通顺的语句段落。有的指令常用,有的指令不常用,只要遵守语法规则,你可以用这些指令“组合”成你想象到的任何程序。当然,有时一条指令可以替代很多条指令,这样会使程序简捷,费码减少,在编写较大程序时可以让程序存储器放得下你需要的代码。这也是单片机高手所追求的。当然,在程序存储器空间不成问题时,你不这样做但也可以达到预期的功能,这也不算错。 单片机内部还有很多“部件”我们只是用到什么说什么,很不系统。但是我也不想系统的介绍这些,因系统介绍单片机结构和指令的书很多,何况写的远比我好,因此,希望你在看本讲座的过程中,还要结合正规的教材学习其更多的指令和“部件”。这是我在别的地方找过来的,希望对你有所帮助。我用的是WAVE6000编译的。
请登录后再发表评论!扫二维码下载作业帮
拍照搜题,秒出答案,一键查看所有搜题记录
下载作业帮安装包
扫二维码下载作业帮
拍照搜题,秒出答案,一键查看所有搜题记录
如何用汇编语言写一个循环彩灯的程序,采用定时器方式1工作由89C51内部定时器1按方式1工作,即作为16位定时器使用,每0.05秒钟T1溢出中断一次.P1口的P1.P1.7分别接发光二极管的L1~L8.要求编写程序模拟一循环彩灯.彩灯变化花样可自行设计.例程给出的变化花样为:①L1、L2、…L8依次点亮;②L1、L2、…L8依次熄灭;③L1、L2、…L8全亮、全灭.各时序间隔为0.5秒.让发光二极管按以上规律循环显示下去.
肺炎是飞扬椷
扫二维码下载作业帮
拍照搜题,秒出答案,一键查看所有搜题记录
ORG 0000HLJMP MAINORG 000BHLJMP T0ISRORG 0030HMAIN:MOV TMOD,#01HMOV TH0,#HIGH()MOV TL0,#LOW()SETB TR0SETB ET0SETB EAMOV R2,#0SJMP $T0ISR:CLR TR0MOV TH0,#HIGH()MOV TL0,#LOW()SETB TR0MOV A,R0CJNE A,#18,T001MOV R0,#0T001:MOV DPTR,#LEDTABMOVC A,@A+DPTRMOV P1,AINC R0RETILEDTAB:DB 0FEH,0FCH,0F8H,0F0H,0E0H,0C0H,80H,00HDB 80H,0C0H,0E0H,0F0H,0F8H,0FCH,0FEH,0FFHDB 00H,0FFHEND
非常感谢!如果不用查表的话,把灯亮灭编在定时器中,该怎么编呢?急急急!!!!!!!!!!!!!!!!!!
LJMP T0ISR
MOV TMOD,#01H
MOV TH0,#HIGH()
MOV TL0,#LOW()
MOV R3,#0FEH
MOV TH0,#HIGH()
MOV TL0,#LOW()
CJNE A,#8,T01
CJNE A,#16,T03
CJNE A,#17,T05
MOV P1,#0FFH
MOV R3,#0FEH
MOV P1,#00H
为您推荐:
扫描下载二维码实训内容;实训1:;P1口做输出口,控制八只发光二极管,编写程序,使;P3口的P3.0连接一个开关,作为输入端;P1口;用8051单片机控制八个发光二极管,先1~8依次;P1接8个发光二极管,编译程序使二极管从1亮到8;用89S52单片机构件建一个彩灯控制系统,系统用;状态1:控制系统通电或复位后,8个LED发光二极;状态2:8个LED发光二极管全亮后,从右
实训内容 实训1: P1口做输出口,控制八只发光二极管,编写程序,使相邻的发光二极管从左到右循环点亮。
实训2: P3口的P3.0连接一个开关,作为输入端;P1口的P1.0~P1.7连接八只发光二极管,作为输出端。要求用P3.0来控制P1输出的循环灯,即当P3.0输出高电平时,控制P1口的发光二极管右循环点亮;当P3.0输出低电平时,控制P1口的发光二极管左循环点亮(P1口输出低电平时发光二极管被点亮)。
实训3: 用8051单片机控制八个发光二极管,先1~8依次点亮,再1357同时亮。闪三下,再2468亮,闪三下,再循环。 实训4: P1接8个发光二极管,编译程序使二极管从1亮到8,然后熄灭1个,2个直到8个全熄灭,循环进行。 实训5: 用89S52单片机构件建一个彩灯控制系统,系统用P1口外接8个发光二极管。 状态1:控制系统通电或复位后,8个LED发光二极管依次从左向右开始逐个点亮,间隔时间为0.2S。
状态2:8个LED发光二极管全亮后,从右向左LED发光二极管再逐个熄灭,间隔时间仍为0.2S。 状态3:8个LED发光二极管全灭后,从左右两边开始同时点亮LED发光二极管,全亮后,8个LED发光二极管再明暗一起闪烁2次,间隔时间仍为0.2s。 实训6: 用89S52单片机构件建一个彩灯控制系统,系统用P1口外接8个发光二极管,没有键按下时,8支彩灯每隔0.5s全亮全灭一次。 按K1时,8支彩灯从左至右循环点亮。 按K2时,8支彩灯从右至左循环点亮。 按K3时,8支彩灯先右循环点亮后左循环点亮。 同时按下K1和K2时,8支彩灯从中间向外循环点亮。 同时按下K2和K3时,8支彩灯从两端向内循环点亮。 同时按下K1和K3时,8支彩灯从左到右依次点亮后从右到左依次熄灭,反复循环。 同时按下三个键时,0、2、4、6、1、3、5、7循环点亮。 实训7: 定时器T1每0.05秒中断一次,单片机P1口接8个发光二极管LED0~LED7,编写程序,使发光二极管有规律地循环点亮。例如:开机后,第一秒钟LED0、LED2亮,第二秒钟LED1、LED3亮,第三秒钟LED4、LED6亮,第四秒钟LED5、LED7亮,第五秒钟LED0、LED2、LED4、LED6亮,第六秒钟LED1、LED3、LED5、
LED7亮,第七秒钟全亮,第八秒钟全灭;再从头开始一直循环下去。 实训8: P1口做输出口,正常时控制八只灯(P1口输出低电平时灯被点亮),从左向右开始逐个点亮,间隔时间为0.5S;按下开关1(接P3.2)0、2、4、6依次点亮,按下开关2(接P3.3)1、3、5、7依次点亮。(要求用中断写) 实训9: P1.1输出脉冲宽度调制(PWM)信号,即脉冲频率为1kHz、占空比为2∶3的矩形波,以控制直流电动机按一定的速度转动,晶振频率为24MHz。 实训10: 单片机控制一共阳数码管,实现每秒钟点亮一段,当单击按钮(连接p3.2)时,在数码管上闪烁显示“8”,闪烁两次后返回。(采用中断实现) 附加:单片机控制数码管实现9s倒计时实训。要求采用两种方法实现,一种要求采用串转并芯片74HC595实现。 实训11: 单片机模拟交通灯实训。详见教材126页。
三亿文库包含各类专业文献、高等教育、外语学习资料、文学作品欣赏、专业论文、应用写作文书、中学教育、8051汇编语言实训71等内容。 
 7页 2财富值 汇编语言上机 20页 10财富值 汇编语言上机指导 27页 免费 8051汇编语言实训 3页 1财富值 汇编语言上机调试 4页 免费喜欢此文档的还喜欢 ...  8051 程序设计实验二 多字节十进制加法 (设计性实验) 一、实验目的: ⑴掌握 8051 汇编语言程序设计方法 ⑵掌握 8051 汇编语言程序的调试方法 二、实验内容: 多...  实验时间: 2011 年 5 月 14 日 实验二一、实验目的: 实验目的: 8051 程序设计实验一 (设计性实验) 设计性实验) 数据传送 (1)掌握 8051 汇编语言程序设计方...  实验 3 8051 定点数运算程序设计 一、实验目的与要求通过本实验,学习编写 8051 单片机定点数运算汇编语言程序,同时进一步熟悉 用伟福单片机开发实验系统进行软件调试的...  单片机实训 8051 单片机实训指导书目 录第一章 单片机仿真系统简介 1.1 仿真...单片机开发实验系统软、硬件的基本操作,同时学习简 单的 8051 汇编语言程序的...  2011 时间:2011 年 月日 实验二 8051 程序设计实验一 数据传送(设计性实验) 一、 实验目的: ⑴掌握 8051 汇编语言程序设计方法 ⑵进一步熟悉 Keil C51 的运用...  2. 3. 8086 汇编语言程序设计(实模式下,.COM 文件格式) 8051 汇编语言程序设计 8051 C 语言程序设计 通过上述实验,掌握 8086 汇编语言程序设计和 8051 汇编...  8051单片机汇编指令速查表 13页 5财富值 关于实验五 熟悉8051汇编语... 2页...8051 系列单片机汇编语言指令速查表编号 指令名称 指令助记符 指令说明 数据传送...51单片机按键控制LED灯亮灭【程序+图文】-51单片机-单片机入门教程日记
51单片机按键控制LED灯亮灭【程序+图文】
51单片机按键控制LED灯亮灭【程序+图文】
阅读:(32979)
& & & &还是先看下面的一个电路图,还是仔细看P2接口,这里我们接了一个发光二极管D1,又接了一个按键S2,我们想实现的功能是:按下按键S2,发光二极管D1改变发光状态。实际上就是模拟家庭的电灯开关。& & & &当然了,要实现这样一个功能大可不必如此兴师动众,又是单片机又是最小系统的,实际用一个简单的闭合开关、一个限流电阻、一节电池、一个灯泡就足矣啦。但是在这可不单单是为了点亮一个灯而已,通过这个小案例,我们会引出单片机开发板系统里面两个非常重要的概念,“按键去抖”和“中断”!下面的内容涉及到好多编程理念,请认真阅读。& & & &说到按键作者不禁要吐一下槽。作者曾经问(其实也被问过)这样一个问题:假设说单片机的P2.0管脚接按键,P2.4接发光二极管,怎样用按键控制灯的亮灭?& & & &有人脱口而出:按键中断!(这是后文书,现在说出来太早了,掌嘴!)& & & &还有人说:在单片机内部从P2.0直接接一条电线到P2.4……& & & &我说:……& & & &好吧,作者承认第一天学单片机的时候我也是这么认为的!& & & &为什么要说这个呢,因为正如第一节我说的,很多人初学单片机的时候会错误地认为单片机是靠纯电路实现的控制,但是事实上它是依靠单片机识别和控制管脚电平来实现各种功能的。单片机就是一个非常听你话的大脑,你让它做啥,它就做啥了。比如想要实现如图按键控制二极管的功能,就让单片机一直监测P2.0的电平状态,S2在没有按下的时候,P2.0通过R4直接连接到VCC,电平状态肯定是高电平,若S2按下,P2.0此时会接地,电平变成低电平,所以当单片机发现P2.0管脚的电平状态变成低电平的时候就知道此时有按键按下了,然后单片机再通知P2.4管脚,让D1转变发光状态,整个过程就是这样的,然后我们将它转换成一个比较专业的程序流程图,就如下图所示。然后再根据上面的流程图编写程序,代码如下所示:#include&reg52.h& &sbit S2=P2^0; &sbit D1=P2^4; &/********************************************************&**函数名:main(void)&**返回:无&**函数功能描述:按键控制灯的亮灭&**********************************************************/ &voidmain(void) & & //程序开始运行 &{ && & D1=1; & & & & &//程序初始化,令二极管不发光 && & while(1) & & & &//循环检测 && & { && & & & if(S2==0) & //如果检测到P2.0管脚为低电平,即按键按下 && & & & { && & & & & & D1=~D1; //二极管转换发光状态,返回继续循环检测 && & & & } & && & } &} && & 应该可以看出,根据流程图来编程会让思路更加清晰,以后等大家编程编的多了的时候就更能体会程序流程图的重要性。& & 好了,一个按键控制电灯的程序就编好了。& & 那么,真的编好了吗?& & 试着把程序下载到单片机里,运行一下,看看是不是您想要的效果呢?& & 好吧,告诉你,这样还不行。你可以试着按下按键,会发现电灯并不是像您想的那样那么听话,有时候确实改变了发光状态,有时候就不变,有时候还会变好几次,这是要闹哪样?& & 我们来看一下按键按下去后P2.0管脚电平的变化情况,下图是一个理想情况的示意图。& & T0时刻:按下按键,P2.0电平由高电平转换为低电平。& & T1时刻:抬起按键,P2.0电平由低电平转换为高电平。& & 当单片机P2.0管脚检测到低电平的时候,D1发生转变。你要知道,这个过程在单片机里发生的极快,大概是微秒级的数量级,而按键按下去再抬起来,这个时间段对应的是毫秒级的数量级,所以在T0到T1这个时间段里,其实D1已经发生了若干次的转换,这个不是我们想要的效果,我们想着按键按一次,D1就转换一次,那这该如何实现呢!& & 思路是这样的,当按键按下去的时候,单片机开始等待,一直等到按键抬起来的时候让D1再转变状态。代码改成下面的样子。#include&reg52.h& &sbit S2=P2^0; &sbit D1=P2^4; &/********************************************************&**函数名:main(void)&**返回:无&**函数功能描述:按键控制灯的亮灭&**********************************************************/ &voidmain(void) & & //程序开始运行 &{ && & D1=1; & & & & &//程序初始化,令二极管不发光 && & while(1) & & & &//循环检测 && & { && & & & if(S2==0) & //如果检测到P2.0管脚为低电平,即按键按下 && & & & { & && & & & & & while(S2==0); //当P2.0为低电平的时候,单片机在此等待 && & & & & & D1=~D1; //二极管转换发光状态,返回继续循环检测 && & & & } & && & } &} && & 上面加了一句“while(S2==0);”这句代码等效于“while(!S2);”,意思是当括号内的语句为真时(P2.0为低电平),单片机程序在此等待,直到括号内语句为假时(P2.0变回高电平),程序往下继续运行。好了,这下运行一下程序,看看是不是能达到您想要的效果来了。& & 。。。& & 那么,效果真的好了吗?& & 。。。& & 好吧,好像还是不行,上面的程序如果加载到类似于Proteus的仿真软件里(请参阅第五章Proteus仿真软件教程),程序运行起来一点问题也没有。但是下载到真正的单片机里运行起来虽然比不加“while(S2==0);”这句代码的时候要强一些,但时不时的还是不太听话。原因何在?& & 原因就在于一句非常有名的名言啊“现实往往比理想差好远!”,按键按下的电平变化会由于电路的稳定性和手的抖动产生一个非常不规则的波形,如下图所示,在按下和抬起的一刹那都会产生一个抖动区,不要小看这个抖动区,它足以让单片机产生误会,导致D1发生偏转。& & 所以在编写按键程序的时候往往都要加一个“去抖”过程,也就是当单片机P2.0口检测到低电平时,单片机不做任何处理,空等一段时间(10ms左右),再次检测P2.0端口,如果此时P2.0端口仍然是低电平,那就认为此次果然按下了按键,D1开始转换状态。重新编写程序,如下所示:#include&reg52.h& &#define uintunsigned int &sbit S2=P2^0; &sbit D1=P2^4; &/********************************************************&**函数名: delay(uint x)&**返回:无&**函数功能描述:延时函数,延时大概x毫秒&**********************************************************/ &voiddelay(uint x) & & & & & &//延时函数,让单片机空跑一段时间。 &{ & && & uint i,j; && & for(i=0;i&=x;i++) && & & for(j=0;j&=100;j++); &} &/********************************************************&**函数名:main(void)&**返回:无&**函数功能描述:按键控制灯的亮灭&**********************************************************/ &voidmain(void) & & //程序开始运行 &{ && & D1=1; & & & & &//程序初始化,令二极管不发光 && & while(1) & & & &//循环检测 && & { && & & & if(S2==0) & //如果检测到P2.0管脚为低电平,即按键按下 && & & & { & && & & & & &delay(10); & //延时一下 && & & & & & & & if(S2==0) && & & & & & & & { && & & & & & & & &while(S2==0); && & & & & & & & &D1=~D1; //二极管转换发光状态,返回继续循环检测 & & & & & & & &&& & & & & & & & } && & & & & & & & & & && & & & } & && & } &} && & 这下再试试,看看效果如何?& & 。。。& & 好吧& & 。。。& & 效果应该是不错了,假如还有问题的话就改改delay函数里面的参数值,多试几次肯定能调整出最好的效果。(这里如果告诉你,其实程序还是有问题的话,你会不会疯掉呢?-_-||)& & 再补充一句,有些时候我们闲编写去抖程序比较麻烦,可以在按键那里加一个滤波电容,如下图所示。按键按下后,若有抖动,电容C会起到一定的滤波作用,效果就会强很多,大家可以做实验试试看。& & 还有一个思路呢!上文咱们用到的按键都是自动弹起的,还有一种按下去就不弹起的开关呢,那种开关就简单多了,按下去就一直导通,再按一下才抬起,我用这么文艺的方式给您解释相信您一定能想的出那种开关长得什么样子吧。
还没有留言,还不快点抢沙发?

我要回帖

更多关于 汇编程序 的文章

 

随机推荐