【51单片机学习笔记】 最小系统、GPIO、数码管、按键、LED、外部中断、 定时器中断
📖今日学习:51单片机最小系统、GPIO口使用、LED点亮、数码管显示、按键检测;外部中断、定时器/计数器中断。
🔍文章大纲
—

1. 51单片机最小系统
最小系统是单片机能够正常运行的最少硬件电路,4部分组成:
- 12MHz:机器周期 = 1us,方便延时计算
- 11.0592MHz:串口波特率可以精准匹配,串口项目首选
机器周期:51单片机12个时钟周期 = 1个机器周期。
晶振12MHz,时钟周期1/12us,机器周期恰好1us。
2. GPIO口基础概念
51单片机标准有4组IO口:P0、P1、P2、P3,每组8位(P0.0~P0.7)。
| P0 | 开漏输出,无上拉电阻;做输出必须外接上拉电阻;可地址/数据复用 |
| P1 | 准双向口,内部带上拉电阻,普通IO,无复用功能 |
| P2 | 准双向口,带上拉;外部存储器高8位地址复用 |
| P3 | 准双向口,带上拉;引脚复用功能(外部中断、定时器、串口) |
准双向口:作为输入之前,必须先向端口写1,释放引脚,才能正确读取外部电平。
P0口特殊:内部没有上拉,输出低电平有效,输出高电平是高阻态。
寄存器操作示例:
// P1口全部置0
P1 = 0x00;
// P1.0单独置1
P1_0 = 1;
3. LED灯点亮(GPIO输出)
LED二极管:阳极接高电平,阴极接低电平才会点亮。
两种硬件接法:
必须串联限流电阻(220Ω左右),防止电流过大烧毁LED和IO引脚。
示例代码(P1.0控制LED,低电平点亮)
#include <reg52.h>
sbit led = P1^0;
void main(void)
{
while(1)
{
led = 0; //点亮
}
}
简单延时函数,实现LED闪烁
void delay_ms(unsigned int t)
{
unsigned int i,j;
for(i=t;i>0;i–)
for(j=110;j>0;j–);
}
4. 数码管显示
数码管由a~g七个段 + dp小数点组成。
- 共阳数码管:公共端接VCC;段脚输出低电平点亮段。
- 共阴数码管:公共端接GND;段脚输出高电平点亮段。
静态数码管
每个数码管段脚独立;只要赋值段码,数字持续显示。
优点:程序简单,无闪烁;缺点:占用IO多,数码管数量多时不适合。
段码表:
共阴:0~9:0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F
动态扫描数码管
多位数码管,段选共用一套IO,位选控制哪一个数码管点亮。
流程:
利用人眼视觉暂留,高速循环扫描,人眼看到多位同时显示。
⚠️消影很关键:不关闭位选直接切换段码,会出现重影乱码。
动态扫描简单逻辑伪代码:
while(1)
{
送第一位段码;
开第一位位选;
delay();
关闭所有位选; //消影
送第二位段码;
开第二位位选;
delay();
关闭所有位选;
}
5. 按键输入检测(查询方式)
按键原理:按下引脚电平翻转;松开恢复。
机械按键存在机械抖动:按下/松开瞬间电平抖动5‑10ms,直接读取会误判多次。
解决抖动两种方案:
51准双向口做输入:读取按键前,IO口先写1。
查询方式按键示例:
sbit key = P3^2;
void key_scan(void)
{
if(key == 0) //按键按下低电平
{
delay_ms(10); //软件消抖
if(key == 0)
{
//按键处理业务
}
while(key == 0); //等待松开
delay_ms(10);
}
}
查询方式缺点:CPU一直循环扫描按键,占用CPU资源。可以使用外部中断实现按键检测。
6. 51中断系统基础
中断:CPU正在执行主程序,收到外部事件信号,暂停主程序,跳转去执行中断服务函数;执行完毕回到断点继续运行主程序。
51单片机5个中断源:
| 外部中断0 | 0 | INT0(P3.2) |
| 定时器0中断 | 1 | T0 |
| 外部中断1 | 2 | INT1(P3.3) |
| 定时器1中断 | 3 | T1 |
| 串口中断 | 4 | UART |
关键寄存器:
- EA:总中断开关,必须置1,所有中断才能生效。
中断服务函数格式:
void 中断服务函数名(void) interrupt 中断号
{
//中断处理代码
}
⚠️中断服务函数不要写延时、复杂业务;尽量简短快速执行完。
7. 外部中断
外部中断0:P3.2(INT0);外部中断1:P3.3(INT1)
两种触发方式:
配置步骤:
示例:外部中断0,下降沿触发按键
#include <reg52.h>
sbit led = P1^0;
void int0_init(void)
{
IT0 = 1; //下降沿触发
EX0 = 1; //开启外部中断0
EA = 1; //打开总中断
}
//外部中断0服务函数,中断号0
void int0_isr(void) interrupt 0
{
led = ~led; //按键触发翻转LED状态
}
void main(void)
{
int0_init();
while(1)
{
//主循环可以做别的事情
}
}
边沿触发:只会跳变瞬间进一次中断;低电平触发,如果引脚一直低电平,会反复进入中断。
8. 定时器/计数器中断
定时器本质:对机器周期计数;计数值溢出,触发定时器中断。
- 定时器模式:对单片机内部机器周期计数,用来定时。
- 计数器模式:对外部T0(P3.4)、T1(P3.5)引脚外部脉冲计数。
TMOD寄存器:设置T0、T1工作模式;模式1最常用:16位定时器,TH高8位,TL低8位,最大计数65536。
12M晶振机器周期1us;模式1,最多定时65536us = 65.536ms。
定时时间 = (65536‑初值) * 机器周期。
定时器配置步骤:
示例:12M晶振,定时器0模式1定时50ms中断
void timer0_init(void)
{
TMOD |= 0x01; //T0模式1,16位定时器
//50ms 初值 65536‑50000 = 15536
TH0 = 15536 / 256;
TL0 = 15536 % 256;
ET0 = 1; //开启T0中断
TR0 = 1; //启动定时器0
EA = 1; //总中断打开
}
//定时器0中断服务函数,中断号1
void timer0_isr(void) interrupt 1
{
//模式1,必须手动重装初值!!
TH0 = 15536 / 256;
TL0 = 15536 % 256;
//定时到,业务处理
}
✨学习重点
⚠️易错点&踩坑记录
📝今日学习小结
今天学习51单片机基础硬件与软件编程:掌握最小系统组成;理解4组GPIO口电气特性;完成LED点亮闪烁;数码管静态、动态扫描显示;按键查询检测。
学习51中断系统,掌握外部中断实现按键触发;定时器中断完成定时功能。



