话不多说,先上程序
ORG 0000H
MAIN:MOV P1,#0O
LCALL DELAY
MOV A,#0FEH
SETB C
TO: MOV P1,A
LCALL DELAY
LCALL DELAY
RLC A
JC TO
MOV P1,A
LCALL DELAY
LCALL DELAY
TO1: RRC A
MOV P1,A
LCALL DELAY
LCALL DELAY
JC TO1
AJMP TO
DELAY:MOV R2,#0FEH
TC1:MOV R3,#0FEH
TC2:DJNZ R3,TC2
DJNZ R2,TC1
RET
END
这个程序的目的是使8个LED循环点亮,还有一个状态是都不亮,我的LED是搭在P1口上,给低电平就亮。总的现象就是先全部亮一次,然后从左到右依次亮,然后全部灭掉,然后从右到左依次亮一遍,然后灭掉,然后就这样循环下去。
现在来对代码一步一步进行分析 我在前面讲过的知识点我就不重复了,会写的简略点,不懂的往前看。
ORG 0000H ;这个就不说了
MAIN:MOV P1,#00 ;让灯全部都亮
LCALL DELAY ;延时
MOV A,#0FEH ;11111110 赋给累加器A,累加器A就相当于c语言中的一个临时变量,临时的寄存器。
SETB C ;把进位标志位C置为1,它就相当于给八位加上了一位,这个可以让灯有个全灭的状态,等你理解完下面的全部东西再来看这个语句的作用,这样理解起来比较好。
TO: MOV P1,A ;这个语句标号为 TO,执行后是使最左边的灯亮起来
LCALL DELAY
LCALL DELAY
RLC A ;这个是新的语句,对A进行循环左移进位,RLC,我的理解就是recircle left carry ,转化为中文就是循环左移进位,意思就是把累积器A加上进位标志位C一起进行循环左移
相当于就是9个数在循环往复的移动,里面还有一个0,这个0移到哪里,哪个灯就亮了,移到进位标志位的时候就每个灯都不亮,因为进位标志位不控制灯的亮灭。
JC TO ;JC是意思是根据进位标志位C是否为1来判断是否转移,jump carry,如果C等于1,就跳到TO里面继续执行左移,否则就就执行后面的程序,而由于8个1和一个0在这九个位置移动,所以只有当0移动到进位标志位C这里它才会执行下面的程序,所以在它没有循环到全部熄灭的状态时,就会继续执行左移
MOV P1,A ;把进位标志位C为0的这个状态也赋给P1口,让灯全部熄灭。
LCALL DELAY
LCALL DELAY
TO1: RRC A ;RRC,recircle right carry,循环右移带进位 和RLC循环的方向相反,本质没有什么不同 ,从这个时候开始右边的第一个灯亮,一直亮到最左边
MOV P1,A
LCALL DELAY
LCALL DELAY
JC TO1 ;循环右移
AJMP TO ;移到最右边就又跳回到前面开始循环左移
DELAY:MOV R2,#0FEH ;下面就是延时函数
TC1:MOV R3,#0FEH
TC2:DJNZ R3,TC2
DJNZ R2,TC1
RET
END
你们可以试试RL和RC,这个不带进位标志位的,所以就不会有全部熄灭的状态了。如果有哪里讲的不对或者不到位的地方,还请大家多多指教,大家最好买个51或者52单片机玩着来学,不然就很没效果,自己去试试少了那些语句会怎么样,然后按自己的目标改变程序。
相关文章