目录
一、基础准备
1. 硬件材料
2. 开发软件
二、方案 1:基础延时实现 LED 闪烁(入门级)
1. 硬件接线
2. 完整代码(Keil C51)
3. 代码解析
4. 编译与下载
三、方案 2:定时器中断实现 LED 闪烁(进阶版)
1. 硬件接线
2. 完整代码(晶振 12MHz)
3. 代码核心解析
(1)定时器初值计算(晶振 12MHz)
(2)中断配置关键
(3)闪烁逻辑
四、常见问题与调试技巧
1. LED 不亮
2. LED 常亮 / 常灭
3. 闪烁频率不准
五、扩展玩法
一、基础准备
1. 硬件材料
| 元件 | 数量 | 备注 |
|---|---|---|
| STC89C52 单片机最小系统板 | 1 块 | 核心控制单元 |
| LED 发光二极管 | 1 个 | 任意颜色(红 / 绿 / 蓝) |
| 限流电阻 | 1 个 | 220Ω~330Ω(保护 LED,防止过流烧坏) |
| 杜邦线 | 若干 | 连接电路 |
| USB 转 TTL 模块 | 1 个 | 下载程序 + 供电 |
| 5V 电源 | 1 个 | 也可通过 USB 转 TTL 给最小系统供电 |
2. 开发软件
- 编译器:Keil uVision4/5(需安装 C51 编译器);
- 下载工具:STC-ISP(STC 单片机专用下载软件)。
二、方案 1:基础延时实现 LED 闪烁(入门级)
1. 硬件接线
以控制 P1.0 引脚为例,接线逻辑(灌电流驱动,51 单片机推荐方式):
- LED 负极(短脚)→ 串联 220Ω 限流电阻 → 单片机 P1.0 引脚;
- LED 正极(长脚)→ 5V 电源(VCC);
- 单片机 GND → 电源 GND(共地)。
⚠️ 若用拉电流驱动(LED 正极接 P1.0,负极接 GND),亮度会稍低,因为 51 拉电流能力弱,优先推荐灌电流方式。
2. 完整代码(Keil C51)
c
运行
// 头文件:51单片机寄存器定义 #include <reg52.h> // 引脚定义:将P1.0定义为LED_PIN,方便修改 sbit LED_PIN = P1^0; // 延时函数:软件延时约1秒(晶振12MHz) void Delay1s() { unsigned int i, j, k; for(i=15; i>0; i--) for(j=200; j>0; j--) for(k=200; k>0; k--); } // 主函数:程序入口 void main() { while(1) { // 死循环,持续执行 LED_PIN = 0; // P1.0输出低电平,LED导通亮 Delay1s(); // 延时1秒 LED_PIN = 1; // P1.0输出高电平,LED截止灭 Delay1s(); // 延时1秒 } }3. 代码解析
sbit LED_PIN = P1^0;:位定义,将 P1 口的第 0 位命名为 LED_PIN,可直接操作该引脚电平;Delay1s():三层嵌套循环实现软件延时,晶振 12MHz 时,1 个机器周期 = 1μs,循环次数决定延时时间(可根据实际需求调整);while(1):死循环保证 LED 持续闪烁,不会执行一次就停止;- 电平逻辑:灌电流驱动下,引脚低电平(0)→ LED 亮,高电平(1)→ LED 灭。
4. 编译与下载
- Keil 中新建工程,选择器件为
Atmel → AT89C52(STC89C52 兼容此型号); - 添加上述代码文件(.c),勾选 “Options for Target → Output → Create HEX File”;
- 编译生成
.hex文件; - 打开 STC-ISP,选择单片机型号
STC89C52RC,导入.hex文件,选择正确串口,点击 “下载 / 编程”,给单片机上电即可。
三、方案 2:定时器中断实现 LED 闪烁(进阶版)
软件延时的缺点是占用 CPU 资源(延时期间 CPU 无法做其他事),定时器中断是更高效的方式,CPU 可在定时期间处理其他任务。
1. 硬件接线
与方案 1 完全相同(P1.0 接 LED)。
2. 完整代码(晶振 12MHz)
c
运行
#include <reg52.h> sbit LED_PIN = P1^0; unsigned int count = 0; // 中断计数变量 // 定时器0初始化函数:配置10ms定时 void Timer0_Init() { TMOD &= 0xF0; // 清空定时器0模式位 TMOD |= 0x01; // 定时器0模式1(16位定时) TH0 = 0xDC; // 高8位初值:65536 - 10000 = 55536 → 0xDC00 TL0 = 0x00; // 低8位初值 ET0 = 1; // 开启定时器0中断 EA = 1; // 开启总中断(必须) TR0 = 1; // 启动定时器0 } // 定时器0中断服务函数 void Timer0_ISR() interrupt 1 { TH0 = 0xDC; // 重装初值(16位定时器溢出后需手动重装) TL0 = 0x00; count++; // 每10ms计数+1 if(count == 100) { // 10ms×100=1000ms=1秒 count = 0; // 计数清零 LED_PIN = ~LED_PIN; // 翻转LED电平(亮→灭/灭→亮) } } void main() { Timer0_Init(); // 初始化定时器 while(1) { // 此处可添加其他任务,如按键检测、串口通信等 // 定时器中断会自动触发,不影响主函数执行 } }3. 代码核心解析
(1)定时器初值计算(晶振 12MHz)
- 机器周期 = 12 / 晶振频率 = 12/12MHz = 1μs;
- 定时 10ms 需要计数次数 = 10ms / 1μs = 10000 次;
- 16 位定时器最大计数 65536 次,因此初值 = 65536 - 10000 = 55536 → 十六进制
0xDC00(TH0=0xDC,TL0=0x00)。
(2)中断配置关键
interrupt 1:中断号,定时器 0 中断对应中断号 1(外部中断 0=0,定时器 1=3,串口 = 4);ET0=1:开启定时器 0 中断,EA=1:开启总中断(51 所有中断必须先开总中断);- 中断服务函数中需重装初值:16 位定时器模式 1 溢出后,TH0/TL0 会清零,需手动重新赋值才能保证下次定时准确。
(3)闪烁逻辑
- 每 10ms 进入一次中断,
count加 1; - 当
count=100时(累计 1 秒),翻转 LED 引脚电平,实现 1 秒闪烁。
四、常见问题与调试技巧
1. LED 不亮
- 接线错误:检查 LED 正负极是否接反,限流电阻是否串联,GND 是否共地;
- 引脚定义错误:确认代码中引脚(如 P1.0)与实际接线一致;
- 程序未下载成功:重新打开 STC-ISP,降低下载波特率(如 2400bps),下载时重新上电;
- 晶振问题:最小系统晶振未接或损坏,导致单片机无法运行,用万用表测晶振引脚是否有电压。
2. LED 常亮 / 常灭
- 延时时间过短 / 过长:调整延时函数的循环次数,或定时器计数阈值;
- 中断未开启:检查
EA=1和ET0=1是否配置; - 初值计算错误:晶振非 12MHz 时,需重新计算定时器初值(如 11.0592MHz 晶振,定时 10ms 初值 = 65536 - (10000×11.0592/12) ≈ 65536 - 9216 = 56320 → 0xD8F0)。
3. 闪烁频率不准
- 软件延时:晶振频率非 12MHz 时,延时误差大,建议换用定时器方案;
- 定时器:未重装初值,或晶振精度差(换用高精度晶振,如 11.0592MHz/12MHz)。
五、扩展玩法
- 多灯闪烁:定义多个引脚(如
P1^0、P1^1、P1^2),实现流水灯; - 按键控制:增加按键(接 P3.2),通过外部中断实现 “按一下亮,再按一下灭”;
- 呼吸灯:通过定时器快速翻转引脚电平,调整高低电平占空比(PWM 模拟),实现 LED 渐亮渐灭。