51单片机作为一种经典的微控制器,因其结构简单、成本低廉、易于学习和掌握等特点,在我国电子技术领域有着广泛的应用。流水灯是实现51单片机入门学习的一个典型实例,通过控制LED灯的点亮和熄灭,产生流水般的效果。本文将详细分析51单片机实现流水灯的三种方法。
方法一:基于软件延时
1. 硬件设计:使用发光二极管(LED)连接到51单片机的I/O口,通过控制I/O口的高低电平来点亮或熄灭LED。假设使用P1端口的P1.0~P1.7八个引脚连接八个LED。
2. 软件设计:使用循环和延时函数实现流水灯效果。具体步骤如下:
a. 初始化P1端口为输出模式。
b. 使用循环结构(如for循环),依次给P1端口的每个引脚赋高电平(点亮LED)。
c. 在每次点亮一个LED后,添加适当的延时,使LED保持点亮一段时间。
d. 清除上一个LED的点亮状态(赋低电平),然后重复步骤b,实现流水灯效果。
以下是示例代码:
#include
void delay(unsigned int ms) {
unsigned int i, j;
for (i = ms; i > 0; i--)
for (j = 110; j > 0; j--);
}
void main() {
while (1) {
P1 = 0xFE; // 点亮P1.0
delay(1000);
P1 = 0xFD; // 点亮P1.1
delay(1000);
// ...
P1 = 0x01; // 点亮P1.7
delay(1000);
}
}
方法二:基于定时器
1. 硬件设计:与方法一相同,使用LED连接到51单片机的I/O口。
2. 软件设计:使用51单片机的定时器/计数器产生定时中断,从而实现流水灯的延时控制。
a. 初始化P1端口为输出模式。
b. 配置定时器,设置定时时间为1ms。
c. 开启定时中断,编写中断服务程序。
d. 在主循环中,每次进入中断后,更新LED的状态。
以下是示例代码:
#include
unsigned char led = 0xFE; // 初始状态,点亮P1.0
void timer0Init() {
TMOD |= 0x01; // 设置定时器0为模式1
TH0 = (65536 - 1000) / 256; // 定时1ms
TL0 = (65536 - 1000) % 256;
EA = 1; // 开全局中断
ET0 = 1; // 开定时器0中断
TR0 = 1; // 启动定时器
}
void timer0_ISR() interrupt 1 {
TH0 = (65536 - 1000) / 256; // 重新加载定时值
TL0 = (65536 - 1000) % 256;
P1 = ~led; // 更新LED状态
led <<= 1; // 移位操作,实现流水灯效果
if (led == 0x00) {
led = 0x01; // 循环点亮
}
}
void main() {
timer0Init();
while (1);
}
方法三:基于外部中断
1. 硬件设计:除了使用LED连接到51单片机的I/O口外,还需要一个按钮(或其他触发器)连接到外部中断引脚(如INT0)。
2. 软件设计:通过外部中断触发LED状态的改变。
a. 初始化P1端口为输出模式。
b. 配置外部中断,编写中断服务程序。

c. 在主循环中等待外部中断触发。
d. 在中断服务程序中,更新LED状态。
以下是示例代码:
#include
unsigned char led = 0xFE; // 初始状态,点亮P1.0
void externalInterruptInit() {
IT0 = 1; // 设置INT0为下降沿触发
EX0 = 1; // 开外部中断0
EA = 1; // 开全局中断
}
void externalInterrupt0_ISR() interrupt 0 {
led <<= 1; // 移位操作,实现流水灯效果
if (
