文章目录
-
- 前言
- 一、51单片机基本概念
-
- [1.1 什么是51单片机](#1.1 什么是51单片机)
- [1.2 51单片机典型内部资源](#1.2 51单片机典型内部资源)
- [1.3 最小系统](#1.3 最小系统)
- [1.4 IO口特点](#1.4 IO口特点)
- 二、51单片机的基本实现方式
-
- [2.1 硬件实现方式](#2.1 硬件实现方式)
- [2.2 软件实现方式](#2.2 软件实现方式)
- [2.3 开发流程](#2.3 开发流程)
- [2.4 时钟与周期](#2.4 时钟与周期)
- 三、流水灯实验
-
- [3.1 实验目的](#3.1 实验目的)
- [3.2 硬件连接](#3.2 硬件连接)
- [3.3 实验原理](#3.3 实验原理)
- [3.4 完整代码:库函数循环移位版](#3.4 完整代码:库函数循环移位版)
- [3.5 数组版流水灯](#3.5 数组版流水灯)
- [3.6 实验现象](#3.6 实验现象)
- 四、独立按键实验
-
- [4.1 实验目的](#4.1 实验目的)
- [4.2 硬件连接](#4.2 硬件连接)
- [4.3 按键消抖原理](#4.3 按键消抖原理)
- [4.4 完整代码:按键控制 LED 亮灭切换](#4.4 完整代码:按键控制 LED 亮灭切换)
- [4.5 扩展:按键控制流水灯启停](#4.5 扩展:按键控制流水灯启停)
- [4.6 实验现象](#4.6 实验现象)
- 五、常见问题
-
- [5.1 程序下载失败](#5.1 程序下载失败)
- [5.2 LED 不亮](#5.2 LED 不亮)
- [5.3 按键不灵敏](#5.3 按键不灵敏)
- [5.4 延时不准](#5.4 延时不准)
- 六、总结
前言
51单片机是很多嵌入式初学者的第一块开发板。它结构简单、资料丰富,非常适合理解单片机的基本工作原理、GPIO控制、延时、按键消抖等入门知识。
本文从51单片机的基本概念出发,总结其基本实现方式、最小系统、开发流程,并给出两个经典实验:流水灯 和独立按键。代码基于 Keil C51 和常见 STC89C52 / AT89C51 开发板,可直接参考移植。
注意:不同开发板的 LED、按键引脚可能不同,请以实际原理图为准。
一、51单片机基本概念
1.1 什么是51单片机
单片机(MCU)可以理解为"把一台微型计算机集成到一块芯片上"。它通常包含:
- CPU:执行指令、运算
- ROM / Flash:存储程序
- RAM:存储临时数据
- IO口:输入输出
- 定时器 / 计数器
- 中断系统
- 串口通信
- 时钟电路
51单片机是指以 Intel 8051 内核为基础的一类 8 位单片机。常见型号有:
- AT89C51 / AT89C52
- STC89C52 / STC89C52RC
- STC12、STC15 等增强型51
其中 STC89C52RC 在入门开发板中非常常见。
1.2 51单片机典型内部资源
以 STC89C52 / AT89C52 为例:
| 资源 | 说明 |
|---|---|
| CPU | 8位 |
| Flash | 8KB 左右 |
| RAM | 256B 左右 |
| IO口 | P0、P1、P2、P3,共32位 |
| 定时器 | 2~3个 |
| 中断 | 外部中断、定时器中断、串口中断等 |
| 串口 | 1个 UART |
| 时钟 | 常用 11.0592MHz 或 12MHz 晶振 |
1.3 最小系统
51单片机要正常工作,至少需要以下电路:
- 电源电路:通常 5V 供电,加滤波电容。
- 晶振电路:晶振 + 两个小电容,接到 XTAL1、XTAL2。
- 复位电路:上电复位 + 按键复位,接到 RST。
- EA 引脚:EA 接 VCC,表示从内部程序存储器取指令。
这就是常说的"51最小系统"。
1.4 IO口特点
51单片机有 P0、P1、P2、P3 四组 IO:
- P0:开漏输出,作为普通 IO 时通常需要外接上拉电阻,常见 10K 排阻。
- P1、P2、P3:准双向 IO,内部有弱上拉。
- P3 口有第二功能,例如串口、外部中断、定时器输入等。
- 写 1 时可以作为输入读取;写 0 时输出低电平。
在代码中,常用 sbit 定义单个引脚:
c
sbit LED1 = P2^0;
sbit KEY1 = P3^1;
也可以用字节方式控制一整组 IO:
c
P2 = 0xFE; // 1111 1110
二、51单片机的基本实现方式
2.1 硬件实现方式
51单片机的硬件实现通常是:
最小系统 + 外设电路 + 下载接口
外设包括:
- LED:用于显示
- 按键:用于输入
- 数码管:用于显示数字
- 蜂鸣器:用于发声
- 传感器:如温度、红外、超声波等
常见开发板会通过排针、排阻、限流电阻把外设连接到单片机 IO 口。
2.2 软件实现方式
51单片机一般使用 C 语言开发,常用 Keil uVision 编写和编译。核心步骤:
- 包含头文件:
#include <reg52.h> - 定义引脚:
sbit - 编写延时函数
- 在
main()中写主循环 - 编译生成
.hex文件 - 用 STC-ISP 等工具烧录到单片机
基本程序结构:
c
#include <reg52.h>
void main()
{
while(1)
{
// 循环执行
}
}
51单片机程序通常是"主循环 + 中断"的结构:
- 主循环处理常规任务
- 中断处理紧急或周期性任务,如定时器、串口接收
2.3 开发流程
- 新建 Keil 工程
- 选择单片机型号,如 AT89C52 或 STC89C52
- 新建
.c文件并加入工程 - 编写代码
- 编译,生成
.hex - 打开 STC-ISP,选择串口和固件
- 给开发板冷启动下载
- 观察实验现象
2.4 时钟与周期
传统 8051 中:
- 时钟周期 = 1 / 晶振频率
- 机器周期 = 12 个时钟周期
- 指令周期 = 1~4 个机器周期
例如 12MHz 晶振:
- 时钟周期 = 1/12 us
- 机器周期 = 1us
因此,软件延时函数中的循环次数需要根据晶振频率调整。
三、流水灯实验
3.1 实验目的
- 掌握 51单片机 GPIO 输出控制
- 理解 LED 低电平点亮 / 高电平点亮
- 掌握延时函数和循环移位
- 实现 LED 依次点亮效果
3.2 硬件连接
常见开发板连接方式:
- LED 阳极通过限流电阻接 VCC
- LED 阴极接 P2.0 ~ P2.7
- 所以 低电平点亮,高电平熄灭
例如:
text
P2.0 -> LED1 -> 电阻 -> VCC
P2.1 -> LED2 -> 电阻 -> VCC
...
P2.7 -> LED8 -> 电阻 -> VCC
如果开发板是共阴接法,则高电平点亮,代码需要取反。
3.3 实验原理
输出 0xFE:
text
0xFE = 1111 1110
最低位 P2.0 为 0,所以 P2.0 对应的 LED 点亮。
延时后,让这个 0 循环左移:
text
1111 1110 -> P2.0 亮
1111 1101 -> P2.1 亮
1111 1011 -> P2.2 亮
...
0111 1111 -> P2.7 亮
再回到 1111 1110,形成流水灯。
3.4 完整代码:库函数循环移位版
c
#include <reg52.h>
#include <intrins.h>
typedef unsigned char u8;
typedef unsigned int u16;
// 约1ms延时,12MHz晶振下近似,实际可调整
void delay_ms(u16 ms)
{
u16 i, j;
for(i = ms; i > 0; i--)
for(j = 110; j > 0; j--);
}
void main()
{
u8 led = 0xFE; // 1111 1110,P2.0先亮
while(1)
{
P2 = led; // 输出到P2口
delay_ms(500); // 延时500ms
led = _crol_(led, 1); // 循环左移1位
}
}
3.5 数组版流水灯
如果不使用 _crol_,也可以用数组:
c
#include <reg52.h>
typedef unsigned char u8;
typedef unsigned int u16;
u8 code led_table[] = {
0xFE, 0xFD, 0xFB, 0xF7,
0xEF, 0xDF, 0xBF, 0x7F
};
void delay_ms(u16 ms)
{
u16 i, j;
for(i = ms; i > 0; i--)
for(j = 110; j > 0; j--);
}
void main()
{
u8 i;
while(1)
{
for(i = 0; i < 8; i++)
{
P2 = led_table[i];
delay_ms(500);
}
}
}
3.6 实验现象
下载程序后,LED 会从 P2.0 到 P2.7 依次点亮,形成流水效果。
注意事项:
- 如果 LED 不亮,先确认是共阳还是共阴。
- 如果亮度异常,检查限流电阻。
- 如果顺序相反,可以改用
_cror_或调整数组顺序。 - 延时时间与晶振频率有关。
四、独立按键实验
4.1 实验目的
- 掌握 51单片机 GPIO 输入检测
- 理解按键按下为低电平的常见电路
- 掌握软件消抖
- 实现按键控制 LED
4.2 硬件连接
常见独立按键接法:
text
P3.1 -> 按键 -> GND
由于 P3 口内部有弱上拉:
- 按键未按下:P3.1 为高电平
- 按键按下:P3.1 被拉到 GND,为低电平
所以代码中判断:
c
if(KEY1 == 0)
{
// 按键按下
}
4.3 按键消抖原理
机械按键在按下和松开瞬间会产生 5~10ms 左右的抖动,导致单片机可能误判多次。
软件消抖方法:
- 检测到低电平
- 延时 20ms
- 再次检测
- 如果仍为低电平,确认按下
- 等待按键释放
4.4 完整代码:按键控制 LED 亮灭切换
c
#include <reg52.h>
typedef unsigned char u8;
typedef unsigned int u16;
sbit KEY1 = P3^1;
sbit LED1 = P2^0;
void delay_ms(u16 ms)
{
u16 i, j;
for(i = ms; i > 0; i--)
for(j = 110; j > 0; j--);
}
void main()
{
LED1 = 1; // 默认熄灭,低电平点亮
while(1)
{
if(KEY1 == 0) // 检测按键
{
delay_ms(20); // 消抖
if(KEY1 == 0) // 再次确认
{
LED1 = !LED1; // 状态翻转
while(KEY1 == 0); // 等待松手
}
}
}
}
4.5 扩展:按键控制流水灯启停
思路:用一个标志位控制流水灯是否运行。
c
#include <reg52.h>
#include <intrins.h>
typedef unsigned char u8;
typedef unsigned int u16;
sbit KEY1 = P3^1;
bit run_flag = 1; // 1运行,0停止
void delay_ms(u16 ms)
{
u16 i, j;
for(i = ms; i > 0; i--)
for(j = 110; j > 0; j--);
}
void main()
{
u8 led = 0xFE;
while(1)
{
if(KEY1 == 0)
{
delay_ms(20);
if(KEY1 == 0)
{
run_flag = !run_flag;
while(KEY1 == 0);
}
}
if(run_flag)
{
P2 = led;
delay_ms(500);
led = _crol_(led, 1);
}
}
}
注意:上面这种写法在 delay_ms(500) 期间无法及时检测按键。实际项目中更推荐用定时器中断来刷新流水灯,这样按键响应更灵敏。
4.6 实验现象
- 按下按键,LED 亮;再按一次,LED 灭。
- 或者按下按键,流水灯开始 / 停止。
注意事项:
- 如果按键无反应,检查接线和上拉。
- 如果一按就连续触发,说明消抖不够或等待松手没写好。
- 如果按键引脚不同,修改
sbit KEY1 = P3^1;。 - 如果 LED 极性不同,修改
LED1 = !LED1;或初始电平。
五、常见问题
5.1 程序下载失败
- 检查串口是否选对
- 检查开发板是否冷启动
- 检查单片机型号和波特率
- 检查 TX、RX 是否交叉连接
5.2 LED 不亮
- 确认 LED 是共阳还是共阴
- 确认引脚是否对应
- 确认限流电阻是否正常
- P0 口作为普通 IO 时可能需要上拉电阻
5.3 按键不灵敏
- 检查按键是否一端接 IO,一端接 GND
- 检查 IO 是否配置为输入
- 加入 20ms 软件消抖
- 等待松手,避免一次按下触发多次
5.4 延时不准
- 延时函数与晶振频率有关
- 12MHz 和 11.0592MHz 下延时不同
- 需要精确定时建议使用定时器中断
六、总结
51单片机入门可以围绕三条主线:
- 基本概念:单片机是什么、最小系统、IO口、时钟、复位。
- 基本实现方式:Keil 编写 C 程序,生成 hex,烧录运行,通过 GPIO 控制外设。
- 经典实验 :
- 流水灯:学习输出控制、延时、循环移位。
- 独立按键:学习输入检测、按键消抖、状态切换。
掌握流水灯和按键后,就可以继续学习:
- 数码管动态显示
- 定时器中断
- 外部中断
- 串口通信
- PWM 控制
- 矩阵按键
- 温度传感器、红外、超声波等模块
51单片机虽然简单,但它是理解嵌入式系统很好的起点。把 GPIO、延时、中断、定时器这些基础打牢,后面学习 STM32、Arduino、ESP32 等平台会轻松很多。
本文为学习笔记,欢迎交流指正。如果对你有帮助,可以点赞收藏。