很早以前,在某个论坛上就看到下面的题目:
用单片机的I/O口控制8个LED,要求编写程序,实现下面的功能。
1.第1、3、5、7个灯半亮,其余的全亮。
2.第1个亮1/8、第2个亮2/8、第3个亮3/8、第4个亮4/8、第5个亮5/8、第6个亮6/8、第7个亮7/8、第8个全亮。
3.所有的灯逐渐从暗到全亮,再由全亮到暗。
4.8个灯从第一个开始依次渐亮,直到最后一个。再从最后一个起渐暗,直到第一个。如此循环。
好像是用来搞竞赛的,只是没有看到像样的结果。
这些个要求,都是要使用PWM来解决。下面,依次写出程序,大家看看是否能够满足题目的要求。
----------------------------------
1.第1、3、5、7个灯半亮,其余的全亮。
这就太简单了。就是要求LED如下显示:
程序,都没有什么好编的,就是下面的几行就行。
;-----------------------------------------
ORG0000H
START:
MOVP0,#0
XRLP0,#55H;第1、3、5、7取反
DJNZR7,$;延时
SJMP$-5;再去取反
END
;-----------------------------------------
---------------------------------
2.第1个亮1/8、第2个亮2/8、第3个亮3/8、第4个亮4/8、第5个亮5/8、第6个亮6/8、第7个亮7/8、第8个全亮。
这个小题,要求LED的显示如下:
程序的思路也不难,只要按照下面的形式,输出数据到接口就行了。
○○○○○○○○全亮
○○○○○○○●D0灭
○○○○○○●●D1又灭了
○○○○○●●●
○○○○●●●●
○○○●●●●●
○○●●●●●●
○●●●●●●●D6~D0都灭了
反复循环的输出上述8个数据,那么D7就永远是亮的,D6有7/8的时间是亮的,...D0只亮了1/8的时间。
程序如下:
;-----------------------------------------
ORG0000H
JMPSTART
ORG000BH
JMPT0_INT
ORG0030H
START:
MOVTH0,#220;1250us@11.0592MHz,T0定时方式0
SETBTR0
MOVIE,#82H
MOV30H,#00H;准备数据
MOV31H,#03H
MOV32H,#0FH;这些数据是交错存放的
MOV33H,#3FH;类似“隔行扫描”
MOV34H,#01H;显示起来就显得平滑、稳定
MOV35H,#07H
MOV36H,#1FH
MOV37H,#7FH
/*
○○○○○○○○
○○○○○○●●
○○○○●●●●
○○●●●●●●
○○○○○○○●
○○○○○●●●
○○○●●●●●
○●●●●●●●
*/
MOVR0,#30H;设定指针
SJMP$
;-----------------------------------------
T0_INT:;1.25ms中断一次
MOVTH0,#220;220:1250us@11.0592MHz
MOVP0,@R0;输出一个数据
INCR0;修改指针
CJNER0,#38H,$+5
MOVR0,#30H
RETI
;-----------------------------------------
END
;-----------------------------------------
----------------------------------
3.所有的灯逐渐从暗到全亮,再由全亮到暗。
这个就是呼吸灯,看看做而论道的前一篇博文吧,这里就不重复了。
---------------------------------
4.8个灯从第一个开始依次渐亮,直到最后一个。再从最后一个起渐暗,直到第一个。如此循环。
这个才是真正的流水灯。LED显示的一部分截图如下:
程序也不长,全部的代码,都在下面:
;-----------------------------------------
ORG0000H
JMPSTART
ORG000BH
JMPT0_INT
ORG0030H
START:
MOVTH0,#220;1250us@11.0592MHz,T0定时方式0
SETBTR0
MOVIE,#82H
MOVR2,#100
MOVR3,#0
MOVR4,#0
SJMP$;此处可以编写主程序
;-----------------------------------------
T0_INT:;1.25ms中断一次
MOVTH0,#220;220:1250us@11.0592MHz
DJNZR2,T0_2
MOVR2,#100
INCR3
CJNER3,#33,T0_2
MOVR3,#0
T0_2:
MOVA,R3;R3:0~32
ADDA,R4;R4:0~7
ADDA,#TAB-$-3
MOVCA,@A+PC
MOVP0,A
INCR4
CJNER4,#08H,$+5
MOVR4,#0
RETI;本程序用不上15us
;-----------------------------------------
TAB:DB255,255,255,255,255,255,255,255
DB127,63,31,15,7,3,1,0
DB0,0,0,0,0,0,0,0
DB0,1,3,7,15,31,63,127
DB255,255,255,255,255,255,255,255
;-----------------------------------------
END
;-----------------------------------------
这个小题,是用查表的方法解决的,程序相当的简短,而且还比较通用,改成别的花样也很容易。
也有另外的方法,毕竟LED变化还是有明显的规律的,所以也可以用计算的方法来解决。
----------------------------------
上述各个程序,都在硬件系统中,通过了验证。图中的8个电容,做硬件试验时,就不用了。