第一种方法:
;这是一种比较笨但又最易理解的方法,采用顺序程序结构,
;用位指令控制P0口的每一个位输出高低电平,
;从而来控制相应LED灯的亮灭 ;程序如下:
ORG 0000H ;单片机上电后从0000H地址执行 AJMP START ;跳转到主程序存放地址处 ORG 0030H ;设置主程序开始地址 START:MOV SP,#60H ;设置堆栈起始地址为60H clr P1.4 ;打开led使能,使得8个led灯可由P0口来控制 mov P2,#00110101B ;锁存2个74hc573,防止数码管点阵点亮. CLR P0.0 ;P0.0输出低电平,使LED1点亮 ACALL DELAY ;调用延时子程序 SETB P0.0 ;P0.0输出高电平,使LED1熄灭 CLR P0.1 ;P0.1输出低电平,使LED2点亮 ACALL DELAY ;调用延时子程序 SETB P0.1 ;P0.1输出高电平,使LED2熄灭 CLR P0.2 ;P0.2输出低电平,使LED3点亮 ACALL DELAY ;调用延时子程序 SETB P0.2 ;P0.2输出高电平,使LED3熄灭 CLR P0.3 ;P0.3输出低电平,使LED4点亮 ACALL DELAY ;调用延时子程序 SETB P0.3 ;P0.3输出高电平,使LED4熄灭 CLR P0.4 ;P0.4输出低电平,使LED5点亮 ACALL DELAY ;调用延时子程序 SETB P0.4 ;P0.4输出高电平,使LED5熄灭 CLR P0.5 ;P0.5输出低电平,使LED6点亮 ACALL DELAY ;调用延时子程序 SETB P0.5 ;P0.5输出高电平,使LED6熄灭 CLR P0.6 ;P0.6输出低电平,使LED7点亮 ACALL DELAY ;调用延时子程序 SETB P0.6 ;P0.6输出高电平,使LED7熄灭 CLR P0.7 ;P0.7输出低电平,使LED8点亮 ACALL DELAY ;调用延时子程序 SETB P0.7 ;P0.7输出高电平,使LED8熄灭 ACALL DELAY ;调用延时子程序 AJMP START ;8个LED流了一遍后返回到标号START处再循环 DELAY: ;延时子程序 MOV R0,#255 ;延时一段时间 D1: MOV R1,#255 DJNZ R1,$ DJNZ R0,D1 RET ;子程序返回 END ;程序结束 -------------------------------2循环移位法----------------------------------- /* 循环移位法: 在上个程序中我们是逐个控制P0端口的每个位来实现的,因此程序显得有点复杂, 下面我们利用循环移位指令,采用循环程序结构进行编程。我们在程序一开始就 给P0口送一个数,这个数本身就让P0.0先低,其他位为高,然后延时一段时间,再让 这个数据向高位移动,然后再输出至P0口,这样就实现“流水”效果啦。由于8051 系列单片机的指令中只有对累加器ACC中数据左移或右移的指令,因此实际编程中 我们应把需移动的数据先放到ACC中,让其移动,然后将ACC移动后的数据再转送到 P0口,这样同样可以实现“流水”效果。具体编程如下所示,程序结构确实简单了很多 */ ORG 0000H ;单片机上电后从0000H地址执行 AJMP START ;跳转到主程序存放地址处 ORG 0030H ;设置主程序开始地址 START:MOV SP,#60H ;设置堆栈起始地址为60H clr P1.4 ;打开led使能,使得8个led灯可由P0口来控制 mov P2,#00110101B ;锁存2个74hc573,防止数码管点阵点亮. MOV A,#0FEH ;ACC中先装入LED1亮的数据(二进制的11111110) MOV P0,A ;将ACC的数据送P0口 MOV R0,#7 ;将数据再移动7次就完成一个8位流水过程 LOOP: RL A ;将ACC中的数据左移一位 MOV P0,A ;把ACC移动过的数据送p0口显示 ACALL DELAY ;调用延时子程序 DJNZ R0,LOOP ;没有移动够7次继续移动 AJMP START ;移动完7次后跳到开始重来,以达到循环流动效果 DELAY: ;延时子程序 MOV R0,#255 ;延时一段时间 D1: MOV R1,#255 DJNZ R1,$ DJNZ R0,D1 RET ;子程序返回 END ;程序结束 ----------------------------------3查表法--------------------------------------- /* 查表法: 上面的两个程序都是比较简单的流水灯程序,“流水”花样只能实现单一 的“从左到右”流方式。运用查表法所编写的流水灯程序,能够实现任意方式流水, 而且流水花样无限,只要更改流水花样数据表的流水数据就可以随意添加或改变流 水花样,真正实现随心所欲的流水灯效果。我们首先把要显示流水花样的数据建在 一个以TAB为标号的数据表中,然后通过查表指令“MOVC A,@A+DPTR”把数据取到 累加器A中,然后再送到P0口进行显示。具体源程序如下,TAB标号处的数据表可以根 据实现效果的要求任意修改。 */ ORG 0000H ;单片机上电后从0000H地址执行 AJMP START ;跳转到主程序存放地址处 ORG 0030H ;设置主程序开始地址 START:MOV SP,#60H ;设置堆栈起始地址为60H clr P1.4 ;打开led使能,使得8个led灯可由P0口来控制 mov P2,#00110101B ;锁存2个74hc573,防止数码管点阵点亮. MOV DPTR,# TAB ;流水花样表首地址送DPTR LOOP: CLR A ;累加器清零 MOVC A,@A+DPTR ;取数据表中的值 CJNE A,#0FFH,SHOW ;检查流水结束标志 AJMP START ;所有花样流完,则从头开始重复流 SHOW: MOV P0,A ;将数据送到P0口 ACALL DELAY ;调用延时子程序 INC DPTR ;取数据表指针指向下一数据 AJMP LOOP ;继续查表取数据 DELAY: ;延时子程序 MOV R0,#255 ;延时一段时间 D1: MOV R1,#255 DJNZ R1,$ DJNZ R0,D1 RET ;子程序返回 TAB: ;下面是流水花样数据表,用户可据要求任意编写 DB 11111110B ;二进制表示的流水花样数据,从低到高左移 DB 11111101B DB 11111011B DB 11110111B DB 11101111B DB 11011111B DB 10111111B DB 01111111B DB 01111111B ;二进制表示的流水花样数据,从高到低右移 DB 10111111B DB 11011111B DB 11101111B DB 11110111B DB 11111011B DB 11111101B DB 11111110B DB 0FEH,0FDH,0FBH,0F7H ;十六进制表示的流水花样数据 DB 0EFH,0DFH,0BFH,7FH DB 7FH,0BFH,0DFH,0EFH DB 0F7H,0FBH,0FDH,0FEH DB 0FFH ;流水花样结束标志0FFH END ;程序结束
我放一个Keil C编的程序 ,请大家给点评
#include"AT89x51.h"
sbit LED=P1^4;
void main(void)
{
unsigned int a;
LED=0;
while(1)
{
for (a=0;a<50000;a++); //全部位均为零,LED全亮
{
P0=0x00;
}
for (a=0;a<50000;a++); //最低位为1,其余位为零,即最低位灭,其余位亮
{
P0=0x01;
}
for (a=0;a<50000;a++);
{
P0=0x02;
}
for (a=0;a<50000;a++);
{
P0=0x04;
}
for (a=0;a<50000;a++);
{
P0=0x08;
}
for (a=0;a<50000;a++);
{
P0=0x10;
}
for (a=0;a<50000;a++);
{
P0=0x20;
}
for (a=0;a<50000;a++);
{
P0=0x40;
}
for (a=0;a<50000;a++);
{
P0=0x80;
}
}
}
哎,对了,LED灯接的是P1口,数码管接的是P0口,应该控制P1口才对呀?为啥控制P0口也能让LED亮灭呢???
我也有同感,???
欢迎光临 (http://www.51hei.com/bbs/) | Powered by Discuz! X3.1 |