流水灯
用51单片机实现点亮1个2个3个……8个流水灯。我们选择P1口作为控制端口,输出0时LED灯点亮。流水灯实现步骤如下:
点亮第一个LED灯,对P1口赋值为“ 1111 1110“;点亮第二个LED灯,对P1口赋值为“ 1111 1100“;
……
3.点亮第八个LED灯,对P1口赋值为“ 0000 0000 “;
4.只点亮第八个LED灯,对P1口赋值为 “ 0111 1111 “;
5.点亮第七个LED灯, 对P1口赋值为 “ 0011 1111 “;
……
6.点亮第一个LED灯,对P1口赋值为 “ 0000 0000“;
7.只点亮第一个LED灯,对P1口赋值为 “ 1111 1110“;
重复上面流程实现LED流水灯。
汇编语言实现:
因为51单片机为8位数处理器,所以从“ 1111 1110“到“ 1111 1100“是左移1位补充数为0 ,我们可以根据左移指令或乘法指令实现。本程序使用乘法指令实现,每次*2都会溢出一次,相应的右边会多出1个0。同理左移根据除法实现每/2右移一位左边补充0。
参考代码如下:
ORG 0000H
AJMP MAIN
//主函数
MAIN: MOV A, #11111111B //初始化累加器
LOOP:
LCALL LEFT //左移程序
CPL A //取反累加器,关闭LED灯
LCALL RIGHT //右移程序
CPL A //取反累加器,关闭LED灯
AJMP LOOP //跳转到LOOP,循环
//左移程序
LEFT: MOV B, #02H //赋值寄存器B位2
MUL AB //使用乘法*2,实现左移2位
MOV P1, A //把累加器A的值赋值给P1口,点亮LED
LCALL DELAY //调用延时函数
JNZ LEFT //累加器不为0,跳转到LEFT左移一位
RET //累加器为0,结束
//右移程序
RIGHT: MOV B, #02H //赋值寄存器B位2
DIV AB //使用除法/2,实现右移2位
MOV P1, A //把累加器A的值赋值给P1口,点亮LED
LCALL DELAY //调用延时函数
JNZ RIGHT //累加器不为0,跳转到RIGHT右移一位
RET //累加器为0,结束
//延时函数
DELAY: MOV R0, #20 //延时0.5秒,使用参数R0、R7、R6。
DEL0: MOV R7, #100
DEL1: MOV R6, #250
DJNZ R6, $
DJNZ R7, DEL1
DJNZ R0, DEL0
RET
END
C语言实现:
本程序使用移位指令实现,每次左移一位,右边补0。同理左移一位左边补充0。
参考代码如下:
#include "reg52.h"
#include<intrins.h>
typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;
#define LED P2 //将P2口定义为led 后面就可以使用led代替P2口
/* 延时函数,i=1时,大约延时10us*/
void delay(u16 i)
{
while(i--);
}
/*主函数*/
void main()
{
u16 i;
LED=0xff; //初始化LED
delay(50000); //大约延时450ms
while(1)
{
for(i=0;i<=7;i++) //左移循环
{
LED<<=1; //将led左移一位
delay(50000); //大约延时450ms
}
LED=~LED; //关闭LED
for(i=0;i<=7;i++) //右移循环
{
LED>>=1; //将led右移一位
delay(50000); //大约延时450ms
}
LED=~LED; //关闭LED
}
}
欢迎大家留言讨论!