☰
51单片机期末复习攻略:硬件结构、C语言编程与中断定时器串口速成
2026/10/12 4:18:41 网站建设 项目流程

先说明一下,我写这篇东西的初衷。每年期末,总能看到不少同学抱着《单片机原理与应用》的课本一脸茫然,平时实验课跟着混过去了,到了复习周才发现这课“好像学过又好像什么都没学”。其实这门课没那么可怕,它考的从来不是天马行空的东西,翻来覆去就是那几块:51单片机硬件结构、C语言编程、中断定时器串口、常见外设接口。把这四块吃透,期末拿个不错的分数完全做得到。这篇博文就是我基于多年经验和带过无数届学生复习总结出来的“速成路线图”,不讲虚的,直接告诉你怎么用有限的复习时间拿到该拿的分。

1. 期末速成的正确打开方式:这门课到底考什么

1.1 先摸清试卷的“出题地图”

很多同学复习第一天就从第一章开始看,看到中断系统就卡住,然后就没有然后了。这是效率最低的复习方式。复习之前,你先要搞清楚这门课的期末考试到底长什么样。

绝大多数院校的《单片机原理与应用》期末试卷逃不出这几种题型:选择填空(概念题)、简答题(硬件结构、寄存器功能)、读程序或程序改错题、编程题(给你一个功能要求,让你写C语言代码)、综合设计题(画硬件连接图加写程序)。分值分布大致是概念题占三到四成,读程序占两成左右,编程和综合设计占四成左右。

这意味着什么?意味着你光背概念只能拿及格,想拿高分必须会写代码。但反过来,如果你重点掌握几个经典程序模板,编程题的分数就能牢牢抓住。整张试卷的核心考点高度集中:存储器结构(程序存储器和数据存储器)、并行IO口(P0到P3)、中断系统(5个中断源)、定时器计数器(工作方式与初值计算)、串口通信(波特率设置)、LED流水灯、数码管显示、按键检测。你把这几块搞定了,试卷上至少80%的分数已经到手。

所以第一步不是打开视频课从头看,而是找近两年的真题或复习题库,先把题型分布标出来。这个动作花不了半小时,但能让你瞬间知道精力往哪里放。没有真题也没关系,就看复习资料里的模拟卷,人为地把每个题型涉及的知识点列一张表,高频考点自然一目了然。

1.2 速成不是裸考:复习资源怎么用

市面上的“速成课资源”通常包含这几样东西:知识点串讲视频、PPT讲义、题库、实验代码参考。大部分人的用法是“打开视频刷一遍,刷完觉得会了,上考场直接懵”。问题出在哪?出在单片机是实践性课程,眼睛看会的和手写出来的完全不是一回事。

我建议的用法是“三轮复习法”。第一轮用一到两天,把知识点串讲视频配合PPT过一遍,边看边做笔记,不需要记所有细节,只记关键术语和高频考点,比如堆栈指针初值、复位地址、定时器初值计算公式。第二轮用两到三天,刷题库里的选择题、填空题和简答题,遇到不会的不要急着翻答案,先翻笔记尝试自己答,再对照答案批改。第三轮就是动手写程序,把经典实验代码默写出来,默写到不看任何参考资料能流畅写完的程度。

这里有一个重要的原则:背程序不是逐字背,是背框架。比如定时器中断的程序,框架永远是“初始化(TMOD、TH/TL、EA、ET、TR)+中断服务函数”,你把这个框架刻进脑子里,考试换一个功能要求,你只需要改初值、改中断函数里的逻辑即可。后面我会把核心代码框架全部列出来,你照着搭就行。

2. 51单片机硬件核心:不背这些,程序写了也白写

2.1 硬件框图五件事:CPU、存储器、IO口、定时器、中断

学51单片机,第一件事不是写代码,而是建立“硬件图景”。很多同学编程题能写出来,但简答题问“单片机复位后PC的值是多少”就懵了,这就是硬件底子不牢。

51单片机的内部结构,你只需要抓住五大块:中央处理器CPU、存储器(程序存储器和数据存储器)、并行IO口、定时器计数器、中断系统。另外还有一个串行口,也经常考。画图题或者简答题让你描述结构时,按这个顺序答不会漏。

存储器这块,考得最细。程序存储器ROM用于存放程序,经典8051是4KB,外部可扩展64KB。数据存储器RAM用于存放运行时的数据,内部有128字节,另外还有特殊功能寄存器区(SFR),这个区域就是用来控制各种硬件模块的。你得知道,程序计数器PC不属于RAM,它是CPU里的一个16位寄存器,用来存放下一条要执行的指令地址。复位后PC被清零,也就是从0000H开始执行。堆栈指针SP复位后是07H,堆栈区默认从08H开始向上生长。

我再提一个必考点:机器周期。51单片机以12MHz晶振为例,一个机器周期是12个振荡周期,算出来就是1微秒。这个数字会频繁出现在定时器初值计算里,比如你要定时50毫秒,就是50000个机器周期。

IO口这四组要分清楚。P0口是开漏输出,作为普通IO口输出时必须外接上拉电阻,它还可以作为地址数据复用总线。P1口是准双向IO口,最“省心”,接LED、按键基本都是它。P2口可以作为高8位地址总线输出。P3口每个引脚都有第二功能,后面单独说。

2.2 端口、引脚、第二功能:连线题全靠它

综合设计题让你“设计一个LED流水灯电路并编写程序”时,硬件连接部分很多人直接放弃或者乱画。其实连线题的核心就是几个固定电路:晶振电路、复位电路、LED驱动电路、按键电路、数码管电路。

晶振电路,标准接法是在XTAL1和XTAL2之间接12MHz晶振,两个引脚各接一个20到30pF的瓷片电容到地。复位电路,最常见的是上电复位:复位引脚RST接一个10μF电解电容到VCC,同时通过一个10k电阻到地,这样上电瞬间RST会短暂为高电平完成复位。EA引脚要接高电平,表示从内部程序存储器读取指令。这些是“最小系统”的标配,画图题基本必考。

P3口第二功能表必须背熟,这是选择题和简答题的常客:P3.0是RXD串行接收,P3.1是TXD串行发送,P3.2是INT0外部中断0,P3.3是INT1外部中断1,P3.4是T0定时器0外部计数输入,P3.5是T1定时器1外部计数输入,P3.6是WR写信号,P3.7是RD读信号。背法就是:从低到高,分别对应“串口收、串口发、外中断0、外中断1、定时器0、定时器1、写、读”。

LED驱动电路,最简单的接法是LED正极接VCC(或通过限流电阻接VCC),负极接单片机IO口,这样IO口输出低电平时LED点亮,这叫“低电平点亮”或“灌电流”方式。反过来叫“高电平点亮”。两种方式段码表和逻辑会完全相反,做题时必须看清楚题目给的是哪种。数码管也同理,共阳极和共阴极的段码表是反着的,我见过太多人在这里翻车。

3. C语言编程与寄存器操作:试卷上的编程题全在这里

3.1 一套能套用的代码骨架:头文件、sbit、延时

单片机C语言和你在电脑上写的C语言最大的区别,就是它会直接操作寄存器。而操作寄存器之前,你得先包含头文件reg51.h,这个头文件把51单片机所有特殊功能寄存器的名字都定义好了,比如P1、TMOD、TH0、TL0这些,你不包含它直接用,编译器直接报“未定义标识符”。

操作单个引脚用的是sbit。比如sbit led = P1^0; 这行的意思是,把P1口的第0位单独取一个名字叫led,之后写led=0就是让这个引脚输出低电平。注意sbit是小写,后面必加分号,sbit和sfr经常有人搞混:sfr用来定义整个特殊功能寄存器,sbit是定义寄存器中的某一位。

延时函数是每个程序都少不了的。最简单的是空循环延时:

void delay(unsigned int t) { unsigned int i, j; for (i = 0; i < t; i++) for (j = 0; j < 120; j++); }

这个函数不精确,但做流水灯、按键消抖完全够用。如果你用的是12MHz晶振,内层循环大约执行120次耗时100微秒左右,外层t次就是t乘以100微秒。考试写代码时用这种延时就行,阅卷不会抠你延时的精确值,但要写清楚注释,让老师知道你的思路。

主程序的骨架一般是:先初始化(设置寄存器),然后进入while(1)死循环。51单片机的程序必须要有这个主循环,否则程序跑完就“飞”了。很多同学的代码写到初始化就结束了,这会被扣不少分。

3.2 五大必会实验代码模板:流水灯、数码管、按键、定时器、串口

第一个必会模板,流水灯。这是最经典的入门实验,也是期末编程题的高频考点,有时候会变形为“点亮第几个灯”或者“两个灯交替闪烁”。核心用左移右移函数:

#include <reg51.h> #include <intrins.h> #define uchar unsigned char void delay(unsigned int t) { unsigned int i, j; for (i = 0; i < t; i++) for (j = 0; j < 120; j++); } void main() { uchar i; while (1) { P1 = 0xFE; // 1111 1110,第一个灯亮 for (i = 0; i < 8; i++) { delay(500); P1 = _crol_(P1, 1); // 循环左移一位 } } }

_crol_这个函数在intrins.h头文件里,意思是“循环左移”,它会把最高位移回最低位,实现流水效果。注意P1=0xFE是低电平点亮,如果是高电平点亮就得改成0x01。这个细节非常容易被坑,做题时一定要看电路。

第二个必会模板,数码管显示。数码管分为段选和位选,段选决定显示什么数字,位选决定哪一位亮。以共阳数码管为例,段码表是常见到的,显示数字0的段码是0xC0,显示1是0xF9,显示2是0xA4。这个表考试可能会给你,也可能让你记住几个,但最保险的方式是理解原理:共阳数码管高电平熄灭,低电平点亮,所以0x3F在共阳极下是显示0(实际共阳极0应为0xC0,注意区分)。

动态显示的原理,就是快速轮流点亮每一位,利用人眼视觉暂留现象,看起来好像同时显示。每次选通一位,延时1到2毫秒再切换下一位。代码框架:

uchar code table[] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90}; // 共阳段码:0~9 void display() { P2 = 0x01; // 第一位位选 P0 = table[1]; // 显示数字1 delay(2); P2 = 0x02; // 第二位位选 P0 = table[2]; // 显示数字2 delay(2); }

这里我用了code关键字,意思是把数组放到程序存储器里而不是RAM里,因为段码表是只读数据,放到ROM不占宝贵的RAM空间。这个细节在简答题里可能被问到“为什么要加code”,你得答得上来。

第三个必会模板,独立按键检测。按键的经典问题就是机械抖动,按下瞬间电平会跳变多次,所以软件要消抖,通常的办法是检测到按下后延时10到20毫秒再确认一次。代码框架:

#include <reg51.h> sbit key = P3^2; sbit led = P1^0; void delay(unsigned int t); void main() { while (1) { if (key == 0) { // 检测到按下 delay(20); // 消抖 if (key == 0) { // 再次确认 led = ~led; // 翻转LED状态 while (!key); // 等待松开 } } } }

这里要特别注意,while(!key)是等按键松开,如果不加这一句,程序会循环执行很多次翻转,效果就是LED忽亮忽灭,完全不受控。考试时这个“等待释放”的语句往往就是得分点,漏掉必扣分。

第四个必会模板,定时器中断。这个模板是所有代码里最需要“硬核功夫”的,因为涉及寄存器的配置计算。定时器0工作方式1,用16位计数器,定时50毫秒,晶振12MHz。初值计算公式是:初值=65536-需要的计数次数。50毫秒就是50000个机器周期(因为机器周期是1μs),所以初值=65536-50000=15536,转成十六进制是0x3CB0,高8位存TH0=0x3C,低8位存TL0=0xB0。代码:

#include <reg51.h> void timer0_init() { TMOD = 0x01; // 定时器0,方式1(16位) TH0 = 0x3C; // 高8位初值 TL0 = 0xB0; // 低8位初值 EA = 1; // 开总中断 ET0 = 1; // 开定时器0中断 TR0 = 1; // 启动定时器0 } void timer0_isr() interrupt 1 { TH0 = 0x3C; // 重装初值 TL0 = 0xB0; // 这里写你的功能代码,比如LED翻转 } void main() { timer0_init(); while (1); }

这串代码里,interrupt 1是关键语法,1是定时器0的中断号。如果忘记重装初值,定时器会从0开始再计数65536个脉冲才溢出,定时时间就乱了。这个坑在实验中极其常见,考试改错题也爱考。

第五个必会模板,串口发送。串口通信在期末里一般是读程序题或简答,但编程题也有可能出现“让单片机通过串口发送字符串”。方式1最常用,波特率9600,晶振12MHz时定时器1的初值是0xFD。代码框架:

#include <reg51.h> void uart_init() { SCON = 0x50; // 方式1,允许接收 TMOD = 0x20; // 定时器1,方式2(8位自动重装) TH1 = 0xFD; // 波特率9600初值 TL1 = 0xFD; TR1 = 1; // 启动定时器1 } void send_char(unsigned char c) { SBUF = c; // 把数据写入发送缓冲器 while (TI == 0); // 等待发送完成 TI = 0; // 清发送完成标志 } void main() { uart_init(); while (1) { send_char('A'); } }

SBUF是串口数据缓冲寄存器,TI是发送完成标志,必须查询等待。考试时最常出的陷阱就是忘记判断TI或者忘记清零TI,导致数据发不出去。另外SCON=0x50这个值是固定的,0x50换成二进制是01010000,方式位SM0SM1=01对应方式1,REN=1允许接收,这个细节如果简答题让你解释SCON寄存器的配置含义,你要能说清楚。

4. 高频题型的答题套路与避坑清单

4.1 概念题和读程序题:背口诀、抓重点

概念题每年翻来覆去就考那几个题,总结成口诀能省大量背诵时间。比如中断系统:5个中断源,两个外部中断(INT0、INT1),两个定时器中断(T0、T1),一个串口中断。外部中断有低电平触发和下降沿触发两种,由IT0和IT1位控制,考试常问“外部中断有哪两种触发方式”。中断优先级,默认优先级从高到低是INT0、T0、INT1、T1、串口,这个顺序在选择题里很常见。再比如堆栈,SP指针初始07H,压栈时先SP加1再存入,出栈时先弹出再SP减1,常作为填空题出现。

读程序题通常给一段代码让你说出运行结果。我教你一个通用分析方法:先看main函数之前的全局声明(sbit定义、数组表),再找初始化和死循环,最后看中断函数或循环体内的关键操作。最常考的读程序就是定时器流水灯:给你一段代码,里面有TMOD=0x01、TH0和TL0初值、中断函数里P1=~P1,让你判断LED是亮还是灭、多长时间翻转一次。这类题只要你会算翘楚初值的对应定时时间,基本就能解。

还有一种常见考法,就是让读一个延时函数,问你延时了多长时间。比如:

void delay() { unsigned char i; for (i = 0; i < 250; i++); }

让你判断循环次数和大概时间。这种写法i是unsigned char,最大255,所以i<250时循环250次,单次循环耗时大约几个机器周期,算出来就是几到几十微秒级别。答案不需要特别精确,但要表明你理解机器周期和循环指令耗时。

4.2 编程题和硬件设计题:分步骤写、分模块得分

编程题最怕的不是不会,而是会一点但不知道怎么写才能拿分。阅卷老师的给分点是分步的:初始化对了给几分,主循环对了给几分,中断函数对了给几分。所以就算你最后结果不完全对,只要步骤清晰,照样能拿大部分分数。

我的建议是,编程题一定要分块写。第一块写头文件和宏定义,第二块写sbit引脚定义,第三块写延时函数(如果用到),第四块写初始化函数,第五块写main函数,第六块写中断服务函数(如果有)。每一块之间用空行隔开,加上简明注释。这样既方便阅卷老师看到你的思路,也方便你自己结构完整地回忆代码模板。

硬件设计题,比如“用51单片机设计一个8路流水灯系统,要求画出电路图并写出程序”,电路部分至少要画出单片机芯片、晶振电路、复位电路、EA接高电平、LED通过限流电阻接P1口。LED这边要注意,每个LED串一个220到470欧姆的限流电阻,不画电阻虽然不算致命错误,但属于硬件设计不完整,会被扣分。程序部分就是前面流水灯的模板。画芯片引脚时不要画得特别标准,但那几个关键引脚(VCC、GND、XTAL、RST、EA、P1口)必须标出来。

写编程题时,我强烈建议你先把“总开关”EA=1写出来,这是最容易被忘但最容易被检查出来的。每次写完代码,心里默念三句话:初始化有没有开总中断?初始化有没有写启动定时器TR?中断服务函数有没有重装初值?这三句话能救回至少5分。

5. 高频翻车现场与考场实操经验

5.1 复习阶段最容易踩的坑

第一坑,把sbit和sfr混为一谈。写代码时sbit led = P1^0;错写成sfr led = P1^0;,编译直接报错。记住:sfr是整个8位寄存器,sbit是其中一个位,语法完全不同。

第二坑,忘记头文件。有些同学默写代码时把#include <reg51.h>省了,结果后面用的P1、TMOD全变成未定义。这个错误在编程题里几乎必扣分,因为阅卷老师一眼就能看出来。

第三坑,数码管段码搞反。共阳极和共阴极的段码表是“取反”的关系。做题时先看题目有没有明确是共阳还是共阴。没写的话,默认按实验课最常用的共阳极来处理,但要写注释说明。

第四坑,定时器初值算错。初值计算这种题,最大的问题不是不会算,而是忘记“方式1是16位所以要用65536减去计数次数,方式2是8位要用256减去计数次数”。答题时一定要先写出计算式,再写十六进制结果,就算结果算错,计算过程正确也会给过程分。

第五坑,中断服务函数里用了delay。中断服务函数的执行时间越短越好,如果你在里面放一个几十毫秒的延时,主程序的实时性全毁了。期末程序题如果让你在中断里输出状态,直接赋值就行,不要加延时。有些选择题还会专门针对这个设陷阱。

5.2 考场上的时间分配和答题技巧

单片机试卷的答题时间通常足够,但很多人还是会来不及,原因是前面的概念题花太多时间纠结。我的建议是,拿到试卷先花两三分钟把所有题目扫一遍,心里有个底。选择题和填空题超过两分钟没思路就先跳过,后面有时间再回来看。简答题控制在十分钟内。重点时间留给编程题和综合设计题,这类题目分值大,而且只要你写了就有分。

编程题的书写顺序也很关键。先写完代码,再回头检查。检查顺序建议是:头文件是否包含、引脚定义是否和题目要求的端口一致、初始化是否包含所有必须的寄存器配置(尤其EA和TR)、主循环是否用while(1)、中断服务函数是否重装初值、代码末尾是否有花括号闭合。这个检查清单我在复习最后一天会让学生默背。

还有一个很容易忽略的技巧:题目里给的已知条件一定要用上。比如题目说“晶振频率为12MHz”,那你的机器周期就是1微秒,定时器初值计算就直接带这个数。如果题目说“晶振频率为11.0592MHz”,这是为了串口波特率精确设置的,那机器周期就不是整数,初值计算要小心,但考试一般不会在这种地方故意刁难你。

综合设计题如果时间不够,先把电路图画出来,程序部分至少写出初始化和主循环框架,不要空着。很多同学因为电路图花了太多时间,最后程序只写了五行,结果丢了最值钱的段落分。正确的节奏是把程序主体写完,再回头补电路的细节。

我在实际操练中发现,那些平时实验课没怎么动手的同学,靠考前三天把每个实验的代码模板默写三遍,期末编程题基本都能应付。这个功夫省不得,你可以在草稿纸上手写代码,不需要真的跑电脑,但要做到“闭眼能写出来”的程度。考试本质上就是一次默写,你平时默得越熟,考场越从容。

最后再分享一个小技巧,如果你复习时间非常紧,只有一两天,那就集中精力攻克三个模板:流水灯、定时器中断、串口发送。这三个模板覆盖了最核心的寄存器操作,而且彼此之间有很强的关联性,把定时器中断搞懂了,外部中断和串口中断基本上也就通了。这门课叫“原理与应用”,但实际上“应用”永远是拿分的主战场,原理是帮助你理解应用的,不要本末倒置。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询