51单片机:点灯程序

目录

一、基础准备

[1. 硬件材料](#1. 硬件材料)

[2. 开发软件](#2. 开发软件)

[二、方案 1:基础延时实现 LED 闪烁(入门级)](#二、方案 1:基础延时实现 LED 闪烁(入门级))

[1. 硬件接线](#1. 硬件接线)

[2. 完整代码(Keil C51)](#2. 完整代码(Keil C51))

[3. 代码解析](#3. 代码解析)

[4. 编译与下载](#4. 编译与下载)

[三、方案 2:定时器中断实现 LED 闪烁(进阶版)](#三、方案 2:定时器中断实现 LED 闪烁(进阶版))

[1. 硬件接线](#1. 硬件接线)

[2. 完整代码(晶振 12MHz)](#2. 完整代码(晶振 12MHz))

[3. 代码核心解析](#3. 代码核心解析)

[(1)定时器初值计算(晶振 12MHz)](#(1)定时器初值计算(晶振 12MHz))

(2)中断配置关键

(3)闪烁逻辑

四、常见问题与调试技巧

[1. LED 不亮](#1. LED 不亮)

[2. LED 常亮 / 常灭](#2. LED 常亮 / 常灭)

[3. 闪烁频率不准](#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. 编译与下载

  1. Keil 中新建工程,选择器件为Atmel → AT89C52(STC89C52 兼容此型号);
  2. 添加上述代码文件(.c),勾选 "Options for Target → Output → Create HEX File";
  3. 编译生成.hex文件;
  4. 打开 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=1ET0=1是否配置;
  • 初值计算错误:晶振非 12MHz 时,需重新计算定时器初值(如 11.0592MHz 晶振,定时 10ms 初值 = 65536 - (10000×11.0592/12) ≈ 65536 - 9216 = 56320 → 0xD8F0)。

3. 闪烁频率不准

  • 软件延时:晶振频率非 12MHz 时,延时误差大,建议换用定时器方案;
  • 定时器:未重装初值,或晶振精度差(换用高精度晶振,如 11.0592MHz/12MHz)。

五、扩展玩法

  1. 多灯闪烁:定义多个引脚(如P1^0P1^1P1^2),实现流水灯;
  2. 按键控制:增加按键(接 P3.2),通过外部中断实现 "按一下亮,再按一下灭";
  3. 呼吸灯:通过定时器快速翻转引脚电平,调整高低电平占空比(PWM 模拟),实现 LED 渐亮渐灭。
相关推荐
亦诚亦心2 小时前
单片机各种驱动简要解释
单片机·嵌入式硬件
逐步前行2 小时前
C51_AT24C02 EEPROM
单片机
zhmc3 小时前
单片机ADC内部基准参考电压有那些应用
单片机·嵌入式硬件
阿拉斯攀登3 小时前
51单片机概述
单片机·嵌入式硬件·51单片机
tang_shou3 小时前
STM32CubeMx使用STM32F4系列芯片实现串口DMA接收
c语言·arm开发·stm32·单片机·嵌入式硬件·mcu·stm32cubemx
m0_553210043 小时前
stm32读取rtc年份错误问题,需要指定星期几
stm32·单片机
Jerry丶Li3 小时前
NXP--S32K移植FreeRTOS
嵌入式硬件·rtos·nxp·s32k
q27551300424 小时前
PL27A1对拷线搭配 PTCB818A 设计资料 高速跨系统互传+键鼠共享一缆搞定
经验分享·单片机·嵌入式硬件·硬件架构·信号处理
Joshua-a4 小时前
SPI芯片选择(CS)引脚的深层作用:为什么必须直连MCU的GPIO?
单片机·嵌入式硬件