简介:面向单片机学习者的51单片机篮球计分器课程设计资源,涵盖24秒倒计时、两队比分数码管显示和矩阵键盘加1、2、3分等核心功能,适合电子设计作业或练手。压缩包共34个文件,约827KB,含C源码、汇编程序、Keil工程、Proteus仿真、原理图、流程图、物料清单及PDF说明,软硬件资料齐全。已有105人学习下载,参考价值明确。利用它可对照原理图、流程图理解代码结构,通过仿真验证计分与倒计时逻辑,按清单搭建实物;同时能学到定时器、键盘扫描、数码管动态显示等典型51单片机技能,便于二次开发与排错。
1. 基于51单片机的篮球计分器,为什么先做 Proteus 再焊板子
篮球计分器这个题目在 51 单片机课程设计里出现频率极高,但它并不是一个「点灯级别」的练习:24 秒倒计时、两队比分、节次切换、加减分按键,这些功能叠在一起,直接暴露了初学者最常见的两个问题——I/O 口不够用,以及按键扫描和动态扫描打架。很多人第一版代码在开发板上跑得好好的,一到 Proteus 仿真就花屏、按键失灵,根源往往不是代码逻辑,而是数码管位选和矩阵键盘扫描共用了同一组 I/O,时序上互相抢占。
我一般会建议先把 Proteus 仿真跑通,再谈焊接和实物调试。原因很直接:Proteus 里你能用逻辑探针和虚拟示波器看位选信号,能随时改引脚映射,不用反复拆线;而实物版一旦布线不合理,排查一条走线可能比写整份代码还久。这篇文章就按「原理图 → 仿真 → 代码 → 物料 → 排错」的顺序,把 24 秒倒计时、数码管显示、矩阵键盘输入这三件事完整串起来。适合正在做课程设计、或者想把 Proteus 仿真和 Keil 代码真正对应起来的读者。
2. 系统框架与 51 单片机引脚分配:数码管和矩阵键盘怎么共用 I/O
2.1 篮球计分器的功能拆解:需要几个输入、几个输出
先别急着画原理图,把功能列清楚。常规篮球计分器至少要有:A 队比分、B 队比分、24 秒进攻倒计时、节次显示(1~4 节),以及对应的操作按键。比分范围按 0~199 设计比较合理,三位数码管足够;24 秒倒计时用两位数码管;节次用一位数码管。这样一共是 3 + 2 + 1 = 6 个数码管位。
按键按最小集来算:A 队加 1 分、A 队减 1 分、B 队加 1 分、B 队减 1 分、24 秒复位、开始/暂停。这 6 个功能至少需要 6 个按键。如果每个按键独占一个 I/O,加数码管段选 8 根、位选 6 根,51 单片机的 32 个 I/O 勉强够,但扩展性为零。所以矩阵键盘几乎是必然选择:4×4 矩阵键盘只用 8 个 I/O 就能提供 16 个按键,比独立按键省 8 个引脚。这也是本题要求矩阵键盘的根本原因——不是题目故意为难,而是引脚预算不够。
2.2 用 P0 驱动数码管段选,P2 做位选和矩阵键盘的典型接法
常见做法是用 P0 口输出段码(a~g 加 dp),通过 74HC245 或直接灌电流驱动共阴数码管;P2.0~P2.5 做 6 位数码管的位选;P2 剩余引脚或 P1 口接矩阵键盘的行列。下面给出一套我常用的引脚映射表,Proteus 仿真和实物焊接都用同一套,减少转换成本。
| 功能模块 | 引脚 | 说明 |
|---|---|---|
| 数码管段选 a~g,dp | P0.0~P0.7 | 共阴数码管,输出高电平点亮 |
| 数码管位选 1~6 | P2.0~P2.5 | 低电平选中,配合三极管驱动 |
| 矩阵键盘行 R1~R4 | P1.0~P1.3 | 行扫描输出,默认高电平 |
| 矩阵键盘列 C1~C4 | P1.4~P1.7 | 列检测输入,按下拉低 |
| 蜂鸣器 | P3.5 | 24 秒到时报警 |
| 复位按键 | RST | 传统上电复位电路 |
这里有一个需要提前说明的坑:P0 口内部没有上拉电阻,驱动数码管时必须外接上拉排阻(常用 10kΩ 或 4.7kΩ),否则段码输出高电平时驱动能力不足,数码管亮度不均匀。Proteus 里很多人忘记画上拉电阻,仿真也能跑,但实物必出问题。所以原理图里 P0 口的排阻不是可选项。
2.3 Proteus 元件选型:AT89C51、7SEG-MPX6-CA 还是 CC
Proteus 元件库里常用的 51 单片机是 AT89C51 或 AT89C52,数码管模型常见的是 7SEG-MPX6-CA(共阳六位一体)和 7SEG-MPX6-CC(共阴六位一体)。选哪个直接影响段码表和驱动电路。
我建议用 7SEG-MPX6-CC 共阴数码管,配合 PNP 三极管做位选驱动。原因有两个:一是共阴数码管段码表是「高电平点亮」,跟 P0 口直接输出逻辑一致,调试时用逻辑探针看 P0 的值更直观;二是 Proteus 里共阴数码管的仿真模型对灌电流的限制没那么敏感,初学者不容易被「数码管不亮但代码没错」这种问题卡住。如果选共阳,段码表要全部取反,而且位选要用 NPN 三极管,逻辑上多一层反相,容易乱。
矩阵键盘在 Proteus 里直接用 KEYPAD-SMALLCALC 元件就能拖出来,4×4 布局,A~D 是行,1~4 是列。注意它的引脚顺序和实际物理键盘不完全一致,连线时对照元件引脚图,不要凭印象接。否则仿真死活按不出来,查半天发现是行和列接反了。
3. 数码管动态扫描与 24 秒倒计时的代码实现
3.1 动态扫描原理:为什么 6 个数码管只用一组段选线
6 个数码管如果每个都独立接段选,需要 8×6 = 48 根线,51 单片机根本不可能直接驱动。动态扫描的思路是:所有数码管的段选线并联,位选线分开控制,同一时刻只点亮一位,轮流点亮每一位,利用人眼视觉暂留形成「6 位同时显示」的错觉。
扫描频率是关键参数。6 位数码管轮流扫一圈,每位的刷新率至少要有 50Hz 才不会闪烁,也就是整圈扫描周期要小于 20ms。常见做法是放在定时器中断里,每 2ms 切换一位,6 位扫完一圈 12ms,刷新率约 83Hz,效果稳定。如果写在主循环里用 delay 控制,一旦按键扫描或倒计时占用时间过长,刷新率会掉到 30Hz 以下,数码管就开始闪。
代码上通常维护一个显示缓冲区数组,比如unsigned char disp_buf[6],主程序只负责往缓冲区里写要显示的数字,定时器中断里只做扫描显示。这样把「显示什么」和「怎么显示」解耦,24 秒倒计时在更新数字时不需要关心位选逻辑。
3.2 Keil C51 下动态扫描和定时器 0 的完整代码
下面给出一段可以在 Proteus 8 里直接跑的动态扫描核心代码,使用定时器 0 方式 1,12MHz 晶振。先看代码,再解释参数。
#include <reg51.h> // 共阴数码管段码:0~9 unsigned char code seg_code[10] = { 0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F }; // 显示缓冲区:A队比分(2位),B队比分(2位),24秒(2位) unsigned char disp_buf[6] = {0, 0, 0, 0, 0, 0}; unsigned char scan_pos = 0; // 当前扫描的位 // 位选控制:P2.0~P2.5,低电平选中 void scan_display(void) interrupt 1 { static unsigned char pos = 0; // 关闭所有位选,消除拖影 P2 = 0xFF; // 输出当前位的段码 P0 = seg_code[disp_buf[pos]]; // 打开当前位的位选 switch (pos) { case 0: P2_0 = 0; break; case 1: P2_1 = 0; break; case 2: P2_2 = 0; break; case 3: P2_3 = 0; break; case 4: P2_4 = 0; break; case 5: P2_5 = 0; break; } pos++; if (pos >= 6) pos = 0; // 重装定时器初值,2ms 中断一次 TH0 = 0xF8; TL0 = 0x30; } void timer0_init(void) { TMOD = 0x01; // 定时器0,方式1,16位 TH0 = 0xF8; // 初值:2ms @12MHz TL0 = 0x30; ET0 = 1; // 开定时器0中断 EA = 1; // 开总中断 TR0 = 1; // 启动定时器0 }定时器初值的计算逻辑:12MHz 晶振下机器周期是 1μs,方式 1 是 16 位定时器,最大计数值 65536。要定时 2ms,需要计数 2000 个机器周期,初值就是 65536 - 2000 = 63536 = 0xF830。代码里写TH0 = 0xF8; TL0 = 0x30;,正好对应 0xF830。如果你换了晶振频率,这个初值必须重新算,否则扫描频率会变,数码管要么闪要么拖影。
中断里先关位选再输出段码,这个顺序不能反。如果先输出段码再关位选,切换瞬间会出现短暂的重影——上一位的残影在换位时被显示出来。P2 口其他引脚如果还接了矩阵键盘的列线,这里直接把 P2 整个赋值 0xFF 可能会影响键盘,所以更稳妥的是只操作 P2.0~P2.5 这几位。实际项目中我会用一个位选掩码变量来控制。
3.3 24 秒倒计时的递减逻辑和到时报警
24 秒倒计时本质上就是定时器中断里做秒计数。用定时器 0 做 2ms 中断,累计 500 次就是 1 秒。倒计时到 0 时停止递减,并触发蜂鸣器报警——注意是「停止递减」而不是「自动回 24」,比赛规则里 24 秒违例后需要裁判手动复位,所以代码里要做到:计时到 0 后只报警,不复位。
unsigned int ms_counter = 0; unsigned char second_24 = 24; bit count_running = 0; // 0:暂停 1:运行 bit timeout_flag = 0; // 24秒到时标志 void timer0_isr(void) interrupt 1 { // 动态扫描由原中断处理,这里只写倒计时逻辑 ms_counter++; if (ms_counter >= 500) { // 500 * 2ms = 1s ms_counter = 0; if (count_running && second_24 > 0) { second_24--; if (second_24 == 0) { count_running = 0; timeout_flag = 1; Beep = 0; // 蜂鸣器低电平触发 } } } }判断second_24 == 0才停止,可以保证倒计时从 24 走到 1 显示正常,走到 0 时触发报警。蜂鸣器触发后不能一直响,否则比赛没法继续。通常在主循环里检测timeout_flag,响 1~2 秒后自动关掉,或者按任意键关闭。建议做一个beep_off()函数,把 P3.5 拉高即可。
4. 矩阵键盘扫描:独立按键和 4×4 矩阵的代码差异
4.1 行列扫描原理和按键消抖
矩阵键盘省引脚的核心原理是「分时复用」:先把所有行线输出高电平,读列线,如果某列为低,说明该列上有按键按下;然后反过来逐行拉低,配合已检测到的列,确定具体是哪个按键。典型流程是:行线全高 → 读列值 → 判断有键按下 → 延时 10ms 消抖 → 逐行拉低扫描 → 得到键值。
消抖是必须的,机械按键在按下和释放的瞬间会产生 5~10ms 的电平抖动,不做消抖会出现一次按键触发多次。Proteus 里的按键模型同样会抖动,不消抖在仿真里也能看到重复触发。最常见的做法是软件延时消抖:检测到按键后 delay 10ms,再次确认电平,如果还是按下状态才认为是有效按键。
这里要提一个和数码管扫描的冲突点:如果你在按键消抖时用delay(10),而数码管扫描依赖定时器中断,那么 10ms 的阻塞对动态扫描的影响可以接受,因为扫描在中断里,不受主循环 delay 影响。但如果你的数码管扫描也是写在主循环里的,按键消抖的 delay 会让显示明显卡顿。所以本题的正确做法是:数码管扫描放定时器中断,主循环只处理按键和逻辑。
4.2 4×4 矩阵键盘扫描函数和键值映射
下面是一个标准的 4×4 行列扫描函数,返回键值 0~15,没有按键按下时返回 0xFF。使用 P1.0~P1.3 做行输出,P1.4~P1.7 做列输入。
unsigned char key_scan(void) { unsigned char row, col; unsigned char key_value = 0xFF; // 列线置低,行线读:检测哪一行被拉低 P1 = 0x0F; // 低4位(列)输出0,高4位(行)输入 col = P1 & 0x0F; // 读取行线状态 if (col != 0x0F) { // 有按键按下 // 注意:这里判断的是行还是列取决于你怎么定义扫描方向 // 本实现:P1.0~P1.3为行,P1.4~P1.7为列 P1 = 0x0F; col = P1 & 0x0F; // 此时读的是行状态 // 逐列拉低,扫描是哪一列 for (col = 0; col < 4; col++) { P1 = ~(0x10 << col); // 依次把P1.4~P1.7拉低 row = P1 & 0x0F; if (row != 0x0F) { // 计算行索引 unsigned char row_index = 0; while (row & 0x01) { row >>= 1; row_index++; } key_value = row_index * 4 + col; break; } } } // 消抖:检到键值后延时10ms,再读一次确认 if (key_value != 0xFF) { delay_ms(10); if ((P1 & 0x0F) == 0x0F) { key_value = 0xFF; // 抖动,不是真实按键 } } return key_value; }这段代码的扫描方向是「先读行,再逐列拉低」——第一次P1 = 0x0F把低 4 位输出 0,高 4 位输入,读回P1 & 0x0F得到的是行状态,只要有任意一行被拉低就说明有键按下。然后逐列拉低,读行状态确定具体行号。行索引的计算用了一个 while 循环找最低的 0 位,这在 Proetus 仿真里完全可行,但如果你熟悉位运算,可以直接用查表法或 switch 来映射,代码会更清晰。
键值映射需要和你的功能对应起来。比如键值 0~3 分配给 A 队加 1、加 2、减 1、加 3,键值 4~7 分配给 B 队对应操作,键值 8 做 24 秒复位,键值 9 做开始/暂停。具体映射可以在主循环的 switch 里写,不要在扫描函数里耦合业务逻辑。
4.3 矩阵键盘长按和连加的处理技巧
比赛中经常出现「加 1 分」连按的情况,比分从 70 加到 73 要按三次。如果按键响应是「按下生效一次」,长按不触发,那么三次按键三次生效,符合规则。但很多人实现时会发现:长按按键,比分连续跳动——这是因为没做「按键释放检测」。
解决方案是维护一个last_key_state变量,记录上一次扫描到的键值。只有「当前键值有效且上一次无效」时才执行功能。这个思路在代码里实现很简单:
unsigned char last_key = 0xFF; // 主循环里 current_key = key_scan(); if (current_key != 0xFF && last_key == 0xFF) { // 只在按下沿触发,长按不重复 handle_key(current_key); } last_key = current_key;注意这里把last_key更新放在判断外,这样当按键一直按住时,current_key始终有效但last_key也一直有效,不会重复触发。只有释放后再按下,last_key变成 0xFF 再次触发。这个技巧对篮球计分这种「比分只允许手动加、不允许误触连加」的场景特别重要。
5. Proteus 仿真搭建、原理图绘制和排错方法
5.1 在 Proteus 8 里从零搭建最小系统
打开 Proteus 8 Professional,新建工程时选择「New Project」,在 Schematic Capture 界面开始放元件。需要从元件库添加的元件清单如下:AT89C51、7SEG-MPX6-CC、KEYPAD-SMALLCALC、RESPACK-8(排阻)、PNP 三极管(2SA1015 或类似)、CRYSTAL、CAP-ELEC 和 CAP(晶振电容)、BUTTON(复位按钮)、BUZZER(蜂鸣器)。
放置元件后,先把 AT89C51 的时钟电路画好:XTAL1 和 XTAL2 之间接 12MHz 晶振,两个引脚分别对地接 30pF 电容。复位电路用经典的 10μF 电解电容加 10kΩ 电阻,接到 RST 引脚。这个最小系统是所有仿真和实物调试的基础,Proteus 里如果不画时钟电路,仿真不会报错但单片机不工作,看波形全是高阻态。
5.1.1 数码管和单片机的连线要点
共阴六位一体数码管有 12 个引脚:6 个位选公共端(每个数码管一个公共阴极)和 8 个段选引脚(a~g, dp,6 个数码管内部并联)。把 8 个段选引脚接到 P0.0~P0.7,中间不需要串电阻吗?实物里通常要串 220Ω~470Ω 限流电阻,Proteus 里不串也能亮,但为了和实物一致,建议加上 220Ω 电阻排。位选公共端接 PNP 三极管的集电极,三极管发射极接 VCC,基极通过 1kΩ 电阻接 P2.0~P2.5。
三极管的接法决定了位选逻辑:PNP 管基极低电平时导通,集电极输出高电平,但共阴数码管需要公共阴极拉低才能点亮——所以这里其实有个反相。如果你用的是共阴数码管,位选应该是「P2 引脚输出低电平 → 三极管基极低电平 → 三极管导通 → 集电极输出高电平 → 数码管公共端接高 → 无法点亮」。这就是最容易踩的坑。
正确的接法有两种,选一种记牢:一是共阳数码管配 NPN 三极管(基极高导通,集电极输出低),二是共阴数码管直接让单片机的 P2 口输出低电平选中,不用三极管。初学者在 Proteus 里仿真时,直接用单片机 P2 口接共阴数码管的公共端最省事,因为仿真不涉及驱动能力问题。等到做实物,再按共阳配 NPN 或加 ULN2003 驱动。我给的代码里位选是「低电平选中」,对应的就是「不用三极管、P2 直连共阴数码管」的 Proteus 接法。
5.1.2 矩阵键盘连线:行接 P1.0~P1.3,列接 P1.4~P1.7
矩阵键盘元件在 Proteus 里的引脚排列是 4 列在一边、4 行在另一边。把 4 个行引脚(通常是 A、B、C、D 标记)接到 P1.0~P1.3,4 个列引脚(1、2、3、4)接到 P1.4~P1.7。
一个小技巧:连完线后,把鼠标放在引脚上按Ctrl可以看到网络标号,确认没有接到同一网络。矩阵键盘和数码管位选在实物里容易互相干扰,原因在于它们共用 P1/P2 口或共用电源线。Proteus 里不会出这个问题,但如果你仿真时发现按键会影响显示,先检查是不是把列线误接到了 P2 口——P2 口同时驱动位选,电平变化会通过内部走线影响 P0 段码输出。
5.2 Keil C51 工程配置和 HEX 文件加载仿真
Proteus 仿真的核心是把编译好的 HEX 文件加载到 AT89C51 模型里。在 Keil 里新建工程时,芯片选择 AT89C51 或 AT89C52——两者寄存器兼容,但 AT89C52 的 RAM 多 128 字节,如果代码里没用到,选哪个都能跑。工程配置里注意 Output 选项卡勾选Create HEX File,否则编译后只有 .obj 文件,Proteus 加载不了。
在 Proteus 里双击 AT89C51 芯片,在Program File一栏选择 Keil 输出的 .hex 文件,Clock Frequency 改成 12MHz,与 Keil 里定时器初值的设计保持一致。这是最常见的仿真踩坑点:代码里按 12MHz 算的初值,Proteus 里芯片默认频率可能是 11.0592MHz,导致 2ms 定时变成约 2.17ms,倒计时看起来「慢了一点点」。如果发现仿真中 24 秒实际走了 26 秒,先检查时钟频率而不是代码。
晶振频率的另一个影响在串口通信上,本题不涉及串口,所以 12MHz 完全没有问题。但如果你后续要扩展为「通过串口把比分上报到上位机」,建议统一用 11.0592MHz——这个频率下波特率误差最小。现在不用改,记着这个权衡即可。
5.3 仿真排错:数码管不亮、按键无响应、倒计时不走
仿真跑不通的时候,先分模块排查,不要从头到尾看代码。三个最常见的问题各有套路:
**数码管不亮。**先看 P0 口有没有输出段码。用 Proteus 的 Logic Probe 挂在 P0.0 上,运行仿真,如果探针显示高电平但数码管不亮,问题在数码管模型或共阴/共阳接法;如果探针一直低电平,问题在代码——定时器中断是否开启,TR0是否置 1。还有一种情况:单片机没跑起来,晶振没接,所有引脚都是高阻态,探针显示灰色,这时先检查时钟电路。
**按键无响应。**在 key_scan 函数里加一个虚拟变量,把键值写到 P3 口的某个引脚上,仿真时用示波器看这个引脚有没有电平跳变。如果确实有跳变,说明扫描逻辑通了,问题在键值映射或主循环的 handle_key 没被调用;如果没有跳变,问题在矩阵键盘的行列连接,最常见的是行和列接反——扫描函数里要求 P1.0~P1.3 是行,实际连线把键盘行接到了 P1.4~P1.7。
**倒计时不准。**用second_24的值和现实时间对比。Proteus 仿真会模拟 MCU 的指令执行周期,所以 12MHz 下 1 秒定时应该基本准确。如果偏差明显,检查ms_counter >= 500这个阈值——它是和 2ms 中断配套的,如果你把定时器初值改成了 1ms 中断,这里应该是 1000。两块参数要一起改。
6. 原理图、流程图和物料清单:从仿真到实物的最后一公里
6.1 原理图的关键设计:数码管驱动、电源去耦和按键上拉
如果你需要交付原理图(课程设计通常要求),Proteus 的 ISIS 原理图可以直接导出为图片或 PDF。但要注意:Proteus 的原理图偏「仿真逻辑」,硬件上还得补充三个东西。第一是电源去耦电容,在单片机 VCC 和 GND 之间加 0.1μF 瓷片电容,靠近芯片引脚放置;第二是数码管段选限流电阻,前面提过的 220Ω 排在实物里必须有,否则段码电流过大可能损坏 P0 口;第三是矩阵键盘的行线不需要额外上拉——因为行线由单片机输出,列线需要内部上拉或外部 10kΩ 上拉,51 单片机 P1 口内部有上拉,直接读列即可。
原理图里还有一个容易画错的元件是蜂鸣器。51 单片机引脚驱动能力不足,蜂鸣器不能直接接在 P3.5 和 GND 之间,需要加一个 NPN 三极管(如 8050)做开关,基极通过 1kΩ 电阻接 P3.5,集电极接蜂鸣器负极,蜂鸣器正极接 VCC,发射极接地。Proteus 里直接用 BUZZER 元件也能响,但如果实物和原理图不一致,老师问起来回答不上就尴尬了。
6.2 流程图怎么画:主程序、定时器中断、按键处理的层次
课程设计报告里的流程图建议按三个层次画:主程序流程图、定时器中断服务程序流程图、矩阵键盘扫描程序流程图。不要画成一张大而全的图,那样看不出程序结构。
主程序流程:初始化定时器和变量 → 进入死循环 → 扫描矩阵键盘 → 有按键则更新比分/倒计时状态 → 刷新显示缓冲区。这里要强调「显示缓冲区在主循环更新,显示动作在中断里完成」的层次关系,流程图里应该体现为两个并行块。
定时器中断流程:重装初值 → 位选切换 → 输出段码 → 毫秒计数 → 满 1 秒执行倒计时递减 → 为零则报警。这张图要画出「扫描显示」和「倒计时」两个分支,说明为什么显示和计时都挂在中断里。
矩阵键盘流程图:行扫描判断是否按下 → 延时消抖 → 逐列扫描确定键值 → 返回。流程图的判断框要标明是「列线检测」还是「行线检测」,避免画成循环套循环的迷宫。
6.3 物料清单:照着买不会缺件的完整列表
物料清单要区分 Proteus 仿真元件和实物采购件。仿真元件可以在原理图里直接导 BOM,但实物清单我列一份常用配置,价格区间参考普通电子市场零售价,不含邮费。
| 序号 | 元件名称 | 规格/型号 | 数量 | 备注 |
|---|---|---|---|---|
| 1 | 单片机 | AT89C51 或 STC89C52 | 1 | 可用 DIP40 封装 |
| 2 | 晶振 | 12MHz | 1 | 与代码定时初值匹配 |
| 3 | 瓷片电容 | 30pF | 2 | 晶振负载电容 |
| 4 | 电解电容 | 10μF/16V | 1 | 复位电路 |
| 5 | 电阻 | 10kΩ | 2 | 复位、上拉 |
| 6 | 排阻 | 10kΩ × 8(SIP-8) | 1 | P0 口上拉 |
| 7 | 电阻 | 220Ω | 8 | 数码管段选限流 |
| 8 | 数码管 | 共阴六位一体 | 1 | 或 6 个独立共阴数码管 |
| 9 | 三极管 | PNP 2SA1015 或 8550 | 6 | 位选驱动 |
| 10 | 三极管 | NPN 8050 | 1 | 蜂鸣器驱动 |
| 11 | 蜂鸣器 | 5V 有源 | 1 | 到时报数 |
| 12 | 矩阵键盘 | 4×4 薄膜键盘 | 1 | 16 按键 |
| 13 | 按键 | 轻触开关 | 1 | 复位键 |
| 14 | 电源 | 5V/1A 适配器 | 1 | 或 USB 供电 |
采购时有两点建议:第一,单片机可以直接买 STC89C52,它和 AT89C51 引脚兼容、下载程序用 USB-TTL 即可,不需要编程器;第二,独立数码管比一体数码管好买,但接线多 8 根,如果焊接没把握,还是一体管省事。Proteus 仿真时元件型号必须和原理图一致,实物则允许等值代换。
6.4 用 Proteus 的 BOM 导出功能核对清单
Proteus 原理图里可以从菜单Tools→Bill of Materials导出当前设计的元件清单,格式可以选择 HTML 或 CSV。导出的 BOM 默认包含元件名称、位号(如 R1、C1)、数量和封装,但不会标注「这个是干什么的」——所以导出后要和上表核对一遍,重点检查电阻阻值和电容容值是否选对。
仿真转实物时,我习惯在导出的 BOM 基础上加一列「用途备注」,比如「R3~R10:数码管段选限流」。这个过程能帮你发现原理图里漏画的元件——如果某组电阻在 BOM 里没有,说明一开始就没画进原理图。课程设计的物料清单通常要求包含每个元件的单价和总价,Proteus 导出的 BOM 没有价格列,需要手动填,别直接用网上的模板,那跟你的原理图对不上。
6.5 扩展:加一个 16 段数码管显示字母还是换 LCD1602
做完基础版后,很多人想加点功能拉开差距。两个方向常见:一是把节次显示从数码管改成一个独立的 16 段数码管,可以显示「PER」或「Q1」这种带字母的信息;二是换掉节次数码管,增加一个 LCD1602 显示「A: 72 B: 68 TIME: 24」这样的完整文本。第二个方向改动更小——LCD1602 用 P0 口做数据线、P2.7 做 RS、P2.6 做 EN,原先的节次数码管直接去掉,显示缓冲区从 6 位变 5 位,扫描中断里只扫 5 位,代码量增加约 30 行。
如果你愿意改矩阵键盘的按键映射,还可以把 4×4 键盘的剩余按键做成「节次加一」和「比赛结束」功能。这些都是锦上添花,核心的三种能力——动态扫描、矩阵键盘、定时器中断——已经通过 24 秒倒计时完整训练到了。最后提一个我反复强调的验证方法:把仿真里的倒计时和手机秒表对一下,跑 3 次 24 秒,误差超过 0.3 秒就要检查晶振频率和定时器初值,因为这种误差在比赛计时场景里是致命的,而它往往不是代码问题而是时钟源配置问题。
本文还有配套的精品资源,点击获取