📄 新建 文本文档.txt
字号:
第二节
单片机自学教材之用单片机做流水灯(二)
第二节
上一节的实验最后没有得到“流水”效果,主要是单片机执行每条指令的时间很短,我们肉眼无法看到LED的熄灭与点亮;
单片机内部能按部就班的自动工作,正是在系统时钟的作用下,内部各逻辑硬件产生各种所需脉冲信号而实现的。这个时钟信号(既晶体振荡信号)的周期称“振荡周期”。我们这个实验中晶体使用的是12MHZ.
在单片机中,要处理最短周期的一条指令需要由12个振荡周期(既晶振振荡周期)组成的,这个叫“机器周期”。
8051核的单片机,大多数指令只用一个机器周期(既单周期),也有双周期和四周期的指令。本实验中用到的SETB P.x和CLR P.x均属于单周期指令,也就是说,执行一句 SETB P.x 用时仅1uS(微秒),CLR P.x 也是1uS;难怪我们前面的程序不能看到流水效果。
现在,将程序改动一下,在每点亮一个LED后,让程序干点别的事,也就是让它等一会再将该LED熄灭,继续执行下面的程序:
star: ;程序开始
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 star ;返回到开始循环
delay: ;延时子程序
mov r1,#50
del0:
mov r2,#100
del1:
mov r3,#100
djnz r3,$
djnz r2,del1
djnz r1,del0
ret ;延时子程序结束,返回到调用处的下一句
end
请将上面的程序保存为 Test.asm,进行编译,并烧写到AT89C2051中,之后将2051安装到实验板中实验,这回肯定“流水”啦!
回过头,让我们看看延时子程序是怎样工作的:
单片机内部有不少寄存器,这些寄存器在单片机通电时,你可以给他写入数据(是单片机按你程序要求写的数据,而不是编程器写的),当第二次给他写入新数据时,前次的数据就被新数据覆盖;当然也可以从寄存器中读取数据。当单片机没有电源供给时,寄存器内部的数据也随即消失;这些寄存器人们叫他RAM,而用编程器将我们编写的程序烧写到单片机中的存储器叫ROM;现在,我们应该清楚:RAM是让程序去使用的,ROM是我们编写的程序存放的地方!
前面说过,单片机内部有不少RAM,本实验用的AT89C2051有多少寄存器?我们现在不必关心,现在只须知道单片机内部有名叫R0~R7 的这8个寄存器。这8个寄存器每个都由8个单独的位寄存器组成,最大存放数据为二进制的 1111 1111,十六进制 = FF,十进制 = 255。在使用时注意不要大于其有效范围。
上面延时程序中,先用到 mov r1,#50 ,mov是移动的意思,该句是将50这个十进制数放到r1中;50是立即数,按汇编语言要求前面要加“#”号,汇编语言还规定,十六进制数后面要加“ H”,十六进制数的高位是字母时在字母前面还要加“0”,例如:#0F8H;二进制数后面加“B”,例如:#11110000B。十进制不加,例如:#100 。延时程序的第二、三句为 mve 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 需要跳转到 del1 标号处执行下面的语句,此时 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口,这样同样可以实现“流水”效果。
程序如下:
star: ;开始
mov acc,#0feh ;ACC中先装入LED1熄灭的数据(即二进制的 1111 1110)
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 star ;移动完7次后跳到开始重来,以达到循环流动效果
delay: ;延时子程序,就是上节课中的延时子程序
mov r1,#50
del0:
mov r2,#100
del1:
mov r3,#100
djnz r3,$
djnz r2,del1
djnz r1,del0
ret ;延时子程序结束,返回到调用处的下一句
end ;本汇编程序到此结束
接下来,将上述程序编译,并烧写到前面我们的实验芯片中,流水效果与第二节课的一样。
其实8051单片机有111条指令,这111条指令好比以前我们使用数字传呼机时的“短语代码”一样,可以用几个“短语代码”去表示一句完整、通顺的语句段落。有的指令常用,有的指令不常用,只要遵守语法规则,你可以用这些指令“组合”成你想象到的任何程序。当然,有时一条指令可以替代很多条指令,这样会使程序简捷,费码减少,在编写较大程序时可以让程序存储器放得下你需要的代码。这也是单片机高手所追求的。当然,在程序存储器空间不成问题时,你不这样做但也可以达到预期的功能,这也不算错。
单片机内部还有很多“部件”我们只是用到什么说什么,很不系统。但是我也不想系统的介绍这些,因系统介绍单片机结构和指令的书很多,何况写的远比我好,因此,希望你在看本讲座的过程中,还要结合正规的教材学习其更多的指令和“部件”。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -