当前位置: 首页 > news >正文

基于51单片机的篮球计分器设计

一、系统总体设计

1.1 系统架构

┌─────────────────────────────────────────────────────────┐
│                    篮球计分器系统架构                  │
├─────────────────────────────────────────────────────────┤
│  ┌──────────┐   ┌──────────┐   ┌──────────┐       │
│  │  按键模块 │   │  显示模块 │   │  报警模块 │       │
│  │ 4×4矩阵  │◄──┤ 4位LED  │◄──┤ 蜂鸣器  │       │
│  │ 键盘输入 │   │ 数码管显示 │   │ 声音提示 │       │
│  └────┬─────┘   └────┬─────┘   └────┬─────┘       │
│       │                │                │                  │
│  ┌────▼────────────────▼────────────────▼─────┐       │
│  │              AT89C51 主控芯片              │       │
│  │  • 按键扫描处理      • 分数计算逻辑          │       │
│  │  • 显示刷新控制      • 24秒计时管理         │       │
│  │  • 比赛时间管理      • 报警控制             │       │
│  └─────────────────────────────────────────────┘       │
└─────────────────────────────────────────────────────────┘

1.2 功能需求

功能模块 具体功能 说明
计分功能 A队/B队加分/减分 支持1分、2分、3分
计时功能 比赛时间、24秒计时 精确到秒
显示功能 分数、时间、节次显示 4位LED数码管
控制功能 开始/暂停/复位 比赛流程控制
报警功能 24秒违例提示 蜂鸣器报警

二、硬件设计

2.1 核心元件选型

模块 型号 数量 说明
主控 AT89C51 1 8位单片机,4KB Flash
显示 4位共阳数码管 2组 A队/B队分数显示
按键 轻触按键 16个 功能按键输入
驱动 74HC245 2片 数码管段选驱动
锁存 74HC573 2片 数码管位选锁存
晶振 11.0592MHz 1 系统时钟
复位 10uF电容+10K电阻 1 上电复位
报警 有源蜂鸣器 1 声音提示

2.2 硬件连接表

/* 51单片机篮球计分器引脚定义 */
#include <reg52.h>
#include <intrins.h>// 系统时钟定义
#define FOSC 11059200L   // 晶振频率11.0592MHz// 数码管段选定义(P0口)
#define SEG_PORT P0        // 段选数据端口// 数码管位选定义(P2口低4位)
sbit BIT1 = P2^0;        // 第1位数码管(A队十位)
sbit BIT2 = P2^1;        // 第2位数码管(A队个位)
sbit BIT3 = P2^2;        // 第3位数码管(B队十位)
sbit BIT4 = P2^3;        // 第4位数码管(B队个位)// 按键定义(P1口)
#define KEY_PORT P1        // 按键端口// 控制引脚定义(P3口)
sbit START_PAUSE = P3^0;  // 开始/暂停按键
sbit RESET = P3^1;        // 复位按键
sbit BEEP = P3^2;         // 蜂鸣器控制
sbit LED_A = P3^3;        // A队得分指示灯
sbit LED_B = P3^4;        // B队得分指示灯// 数码管显示缓冲区
unsigned char disp_buf[4] = {0, 0, 0, 0};  // 显示数据缓存// 系统变量
unsigned char team_a_score = 0;    // A队分数
unsigned char team_b_score = 0;    // B队分数
unsigned char game_time_min = 10;   // 比赛时间(分钟)
unsigned char game_time_sec = 0;    // 比赛时间(秒)
unsigned char shot_clock = 24;      // 24秒计时
bit game_running = 0;              // 比赛进行标志
bit shot_clock_running = 0;        // 24秒计时运行标志
unsigned long system_tick = 0;     // 系统节拍

三、软件系统设计

3.1 延时函数

/* 延时函数 */
void DelayMs(unsigned int ms) {unsigned int i, j;for(i = 0; i < ms; i++)for(j = 0; j < 110; j++);
}void DelayUs(unsigned int us) {while(us--) {_nop_(); _nop_(); _nop_(); _nop_();}
}/* 定时器0初始化(1ms中断) */
void Timer0_Init(void) {TMOD &= 0xF0;    // 清除T0控制位TMOD |= 0x01;    // 设置T0为模式1(16位定时器)TH0 = 0xFC;      // 装载初值(1ms@11.0592MHz)TL0 = 0x66;ET0 = 1;         // 允许T0中断EA = 1;          // 允许总中断TR0 = 1;         // 启动T0
}/* 定时器0中断服务函数 */
void Timer0_ISR(void) interrupt 1 {TH0 = 0xFC;     // 重装初值TL0 = 0x66;system_tick++;    // 系统节拍递增// 比赛时间计时if(game_running) {if(system_tick % 1000 == 0) {  // 每秒更新一次if(game_time_sec > 0) {game_time_sec--;} else {if(game_time_min > 0) {game_time_min--;game_time_sec = 59;} else {game_running = 0;  // 比赛结束BEEP = 0;           // 蜂鸣器报警DelayMs(500);BEEP = 1;}}}}// 24秒计时if(shot_clock_running) {if(system_tick % 1000 == 0) {  // 每秒更新一次if(shot_clock > 0) {shot_clock--;if(shot_clock == 0) {shot_clock_running = 0;BEEP = 0;           // 24秒违例报警DelayMs(1000);BEEP = 1;}}}}
}

3.2 数码管显示驱动

/* 数码管显示驱动 */
// 数码管字形码(共阳极)
unsigned char code seg_tab[10] = {0xC0,  // "0" - 110000000xF9,  // "1" - 111110010xA4,  // "2" - 101001000xB0,  // "3" - 101100000x99,  // "4" - 100110010x92,  // "5" - 100100100x82,  // "6" - 100000100xF8,  // "7" - 111110000x80,  // "8" - 100000000x90   // "9" - 10010000
};// 显示扫描函数
void Display_Scan(void) {static unsigned char scan_bit = 0;// 关闭所有位选BIT1 = 1; BIT2 = 1; BIT3 = 1; BIT4 = 1;switch(scan_bit) {case 0:SEG_PORT = seg_tab[disp_buf[0]];  // A队十位BIT1 = 0;  // 选中第1位scan_bit = 1;break;case 1:SEG_PORT = seg_tab[disp_buf[1]];  // A队个位BIT2 = 0;  // 选中第2位scan_bit = 2;break;case 2:SEG_PORT = seg_tab[disp_buf[2]];  // B队十位BIT3 = 0;  // 选中第3位scan_bit = 3;break;case 3:SEG_PORT = seg_tab[disp_buf[3]];  // B队个位BIT4 = 0;  // 选中第4位scan_bit = 0;break;}
}/* 更新显示缓冲区 */
void Update_Display_Buffer(void) {disp_buf[0] = team_a_score / 10;    // A队十位disp_buf[1] = team_a_score % 10;    // A队个位disp_buf[2] = team_b_score / 10;    // B队十位disp_buf[3] = team_b_score % 10;    // B队个位
}/* 显示比分 */
void Display_Score(void) {Update_Display_Buffer();
}/* 显示时间 */
void Display_Time(void) {disp_buf[0] = game_time_min / 10;   // 分钟十位disp_buf[1] = game_time_min % 10;   // 分钟个位disp_buf[2] = game_time_sec / 10;   // 秒钟十位disp_buf[3] = game_time_sec % 10;   // 秒钟个位
}

3.3 按键扫描程序

/* 按键扫描程序 */
unsigned char Key_Scan(void) {unsigned char key_value = 0xFF;  // 无按键unsigned char temp;// 扫描第1行(P1.0-P1.3)KEY_PORT = 0xFE;  // 11111110temp = KEY_PORT & 0x0F;if(temp != 0x0F) {DelayMs(10);  // 消抖temp = KEY_PORT & 0x0F;if(temp != 0x0F) {switch(temp) {case 0x0E: key_value = 0x01; break;  // 第1行第1列 - A队+1分case 0x0D: key_value = 0x02; break;  // 第1行第2列 - A队+2分case 0x0B: key_value = 0x03; break;  // 第1行第3列 - A队+3分case 0x07: key_value = 0x04; break;  // 第1行第4列 - A队-1分}while((KEY_PORT & 0x0F) != 0x0F);  // 等待按键释放return key_value;}}// 扫描第2行(P1.4-P1.7)KEY_PORT = 0xFD;  // 11111101temp = KEY_PORT & 0x0F;if(temp != 0x0F) {DelayMs(10);temp = KEY_PORT & 0x0F;if(temp != 0x0F) {switch(temp) {case 0x0E: key_value = 0x05; break;  // 第2行第1列 - B队+1分case 0x0D: key_value = 0x06; break;  // 第2行第2列 - B队+2分case 0x0B: key_value = 0x07; break;  // 第2行第3列 - B队+3分case 0x07: key_value = 0x08; break;  // 第2行第4列 - B队-1分}while((KEY_PORT & 0x0F) != 0x0F);return key_value;}}// 扫描第3行KEY_PORT = 0xFB;  // 11111011temp = KEY_PORT & 0x0F;if(temp != 0x0F) {DelayMs(10);temp = KEY_PORT & 0x0F;if(temp != 0x0F) {switch(temp) {case 0x0E: key_value = 0x09; break;  // 开始/暂停case 0x0D: key_value = 0x0A; break;  // 复位case 0x0B: key_value = 0x0B; break;  // 24秒复位case 0x07: key_value = 0x0C; break;  // 节次切换}while((KEY_PORT & 0x0F) != 0x0F);return key_value;}}// 扫描第4行KEY_PORT = 0xF7;  // 11110111temp = KEY_PORT & 0x0F;if(temp != 0x0F) {DelayMs(10);temp = KEY_PORT & 0x0F;if(temp != 0x0F) {switch(temp) {case 0x0E: key_value = 0x0D; break;  // 显示切换(比分/时间)case 0x0D: key_value = 0x0E; break;  // 保留功能case 0x0B: key_value = 0x0F; break;  // 保留功能case 0x07: key_value = 0x10; break;  // 蜂鸣器测试}while((KEY_PORT & 0x0F) != 0x0F);return key_value;}}return 0xFF;  // 无按键
}

3.4 计分逻辑处理

/* 计分逻辑处理 */
void Score_Process(unsigned char key) {switch(key) {case 0x01:  // A队+1分if(team_a_score < 99) {team_a_score++;LED_A = 0;  // A队指示灯亮BEEP = 0;   // 蜂鸣器响DelayMs(100);LED_A = 1;BEEP = 1;}break;case 0x02:  // A队+2分if(team_a_score <= 97) {team_a_score += 2;LED_A = 0;BEEP = 0;DelayMs(200);LED_A = 1;BEEP = 1;}break;case 0x03:  // A队+3分if(team_a_score <= 96) {team_a_score += 3;LED_A = 0;BEEP = 0;DelayMs(300);LED_A = 1;BEEP = 1;}break;case 0x04:  // A队-1分if(team_a_score > 0) {team_a_score--;}break;case 0x05:  // B队+1分if(team_b_score < 99) {team_b_score++;LED_B = 0;  // B队指示灯亮BEEP = 0;DelayMs(100);LED_B = 1;BEEP = 1;}break;case 0x06:  // B队+2分if(team_b_score <= 97) {team_b_score += 2;LED_B = 0;BEEP = 0;DelayMs(200);LED_B = 1;BEEP = 1;}break;case 0x07:  // B队+3分if(team_b_score <= 96) {team_b_score += 3;LED_B = 0;BEEP = 0;DelayMs(300);LED_B = 1;BEEP = 1;}break;case 0x08:  // B队-1分if(team_b_score > 0) {team_b_score--;}break;}Display_Score();  // 更新显示
}/* 比赛控制处理 */
void Game_Control(unsigned char key) {switch(key) {case 0x09:  // 开始/暂停if(game_time_min > 0 || game_time_sec > 0) {game_running = !game_running;shot_clock_running = game_running;if(game_running) {BEEP = 0;DelayMs(50);BEEP = 1;}}break;case 0x0A:  // 复位team_a_score = 0;team_b_score = 0;game_time_min = 10;game_time_sec = 0;shot_clock = 24;game_running = 0;shot_clock_running = 0;Display_Score();break;case 0x0B:  // 24秒复位shot_clock = 24;shot_clock_running = 1;break;case 0x0D:  // 显示切换static bit show_time = 0;show_time = !show_time;if(show_time) {Display_Time();} else {Display_Score();}break;case 0x10:  // 蜂鸣器测试BEEP = 0;DelayMs(500);BEEP = 1;break;}
}

四、主程序

4.1 完整主程序

/* 篮球计分器主程序 */
#include <reg52.h>
#include <intrins.h>// 函数声明
void Timer0_Init(void);
void Display_Scan(void);
void Display_Score(void);
void Update_Display_Buffer(void);
unsigned char Key_Scan(void);
void Score_Process(unsigned char key);
void Game_Control(unsigned char key);/* 系统初始化 */
void System_Init(void) {// 初始化端口P0 = 0xFF;    // P0口上拉P1 = 0xFF;    // P1口上拉(按键输入)P2 = 0xFF;    // P2口输出高电平P3 = 0xFF;    // P3口上拉// 初始化变量team_a_score = 0;team_b_score = 0;game_time_min = 10;game_time_sec = 0;shot_clock = 24;game_running = 0;shot_clock_running = 0;// 初始化定时器Timer0_Init();// 初始化显示Display_Score();// 开机提示音BEEP = 0;DelayMs(200);BEEP = 1;
}/* 主程序 */
void main(void) {unsigned char key_value;// 系统初始化System_Init();while(1) {// 按键扫描key_value = Key_Scan();if(key_value != 0xFF) {// 处理计分按键if(key_value <= 0x08) {Score_Process(key_value);}// 处理控制按键else if(key_value >= 0x09 && key_value <= 0x0D) {Game_Control(key_value);}// 处理其他功能按键else {Game_Control(key_value);}}// 显示扫描(放在主循环中持续刷新)Display_Scan();// 短暂延时,防止刷新过快DelayMs(1);}
}

五、功能扩展

5.1 节次管理功能

/* 节次管理 */
unsigned char quarter = 1;  // 当前节次(1-4节)void Quarter_Control(void) {if(quarter < 4) {quarter++;} else {quarter = 1;  // 回到第一节}// 重置比赛时间game_time_min = 10;game_time_sec = 0;team_a_score = 0;team_b_score = 0;// 显示节次disp_buf[0] = 0xBF;  // 显示"Q"(自定义字符)disp_buf[1] = quarter;disp_buf[2] = 0x00;  // 熄灭disp_buf[3] = 0x00;  // 熄灭
}

5.2 暂停时间管理

/* 暂停时间管理 */
unsigned char timeout_count = 0;  // 暂停次数
bit timeout_active = 0;           // 暂停状态void Timeout_Control(void) {if(!game_running && !timeout_active) {timeout_active = 1;game_running = 0;  // 停止比赛计时shot_clock_running = 0;  // 停止24秒计时// 显示暂停时间(30秒)game_time_min = 0;game_time_sec = 30;Display_Time();} else if(timeout_active) {timeout_active = 0;game_running = 1;  // 恢复比赛shot_clock_running = 1;  // 恢复24秒计时Display_Score();}
}

5.3 犯规次数统计

/* 犯规次数统计 */
unsigned char foul_a = 0;  // A队犯规次数
unsigned char foul_b = 0;  // B队犯规次数void Foul_Process(unsigned char team) {if(team == 0) {  // A队犯规if(foul_a < 5) {foul_a++;} else {// A队犯规满5次,对方罚球BEEP = 0;DelayMs(1000);BEEP = 1;}} else {  // B队犯规if(foul_b < 5) {foul_b++;} else {// B队犯规满5次,对方罚球BEEP = 0;DelayMs(1000);BEEP = 1;}}
}

参考代码 基于51单片机的篮球计分器 www.youwenfan.com/contentcnu/133192.html

六、调试与测试

6.1 测试程序

/* 系统测试程序 */
void System_Test(void) {unsigned char test_step = 0;while(1) {switch(test_step) {case 0:  // 数码管测试disp_buf[0] = 0x88;  // 显示"8."(带小数点)disp_buf[1] = 0x88;disp_buf[2] = 0x88;disp_buf[3] = 0x88;DelayMs(1000);test_step = 1;break;case 1:  // 按键测试disp_buf[0] = 0x86;  // 显示"E."disp_buf[1] = 0x86;disp_buf[2] = 0x86;disp_buf[3] = 0x86;if(Key_Scan() != 0xFF) {BEEP = 0;DelayMs(100);BEEP = 1;test_step = 2;}break;case 2:  // 计时器测试game_time_min = 0;game_time_sec = 5;game_running = 1;shot_clock = 5;shot_clock_running = 1;Display_Time();test_step = 3;break;case 3:  // 等待计时结束if(game_time_min == 0 && game_time_sec == 0) {test_step = 4;}break;case 4:  // 测试完成disp_buf[0] = 0x8C;  // 显示"P."disp_buf[1] = 0x8C;disp_buf[2] = 0x8C;disp_buf[3] = 0x8C;BEEP = 0;DelayMs(500);BEEP = 1;DelayMs(500);test_step = 0;  // 循环测试break;}Display_Scan();DelayMs(1);}
}

七、总结

基于51单片机的篮球计分器实现了以下功能:

核心功能:

  1. 实时计分:支持A/B两队1分、2分、3分加减
  2. 比赛计时:10分钟比赛倒计时,精确到秒
  3. 24秒计时:进攻时间管理,违例报警
  4. 显示控制:4位LED数码管显示比分和时间
  5. 声音提示:蜂鸣器提供操作反馈和报警

技术亮点:

  1. 矩阵按键扫描:16键键盘,功能齐全
  2. 动态显示扫描:4位数码管分时显示,节省I/O口
  3. 精确定时:定时器中断实现精确的时间管理
  4. 低功耗设计:合理使用延时和资源
  5. 扩展性强:预留节次、犯规、暂停等功能接口

应用场景:

  • 校园篮球赛:班级联赛、校际比赛
  • 社区篮球赛:业余联赛、友谊赛
  • 训练比赛:球队训练、技能考核
  • 娱乐活动:公司团建、生日派对
  • 教学演示:单片机课程设计、电子竞赛

改进建议:

  1. 增加LCD显示:显示更多信息(节次、犯规、暂停)
  2. 无线遥控:添加红外遥控功能
  3. 数据存储:记录比赛数据到EEPROM
  4. 语音播报:添加ISD1820语音模块
  5. LED大屏:驱动更大尺寸的LED显示屏

这个篮球计分器系统成本低、功能实用、操作简单,非常适合学校、社区等场所的篮球比赛使用!

http://www.jsqmd.com/news/719839/

相关文章:

  • 单片机仿真电流电压检测系统:电网参数监测、显示、报警设定、远程通信与控制及声光报警功能全面解析
  • GLM-OCR在办公场景的妙用:快速提取图片文字,告别手动打字
  • 【收藏备用|2026年版】35+程序员转型AI全攻略,小白也能快速上手,告别年龄焦虑
  • 浏览器P2P文件传输革命:FilePizza如何让文件分享告别云端中转站
  • 5个实战技巧:如何高效定制你的AI视频生成工作流
  • 静音风机哪家做得好?优质实力品牌与售后靠谱厂家清单 - 品牌推荐大师
  • Albion与Tecnotree合作,为TELUS提供面向北美市场的下一代增值服务平台
  • 不同.NET版本中的WPF新增功能
  • 中亿英才消防设施操作员培训靠谱吗?全面解析培训质量与证书前景 - 速递信息
  • 如何在5分钟内完成DbGate与MySQL数据库的完整连接配置
  • 三步快速优化:Win11Debloat让你的Windows 11系统运行效率提升50%
  • 2026年乌鲁木齐旧房翻新与家装全案深度横评:透明报价、气候适配、不转包的本地标杆之选 - 企业名录优选推荐
  • 2026年最强B站资源下载神器:BiliTools跨平台工具箱终极指南
  • 10分钟搞定黑苹果配置:OpCore Simplify智能图形化工具终极指南
  • 公司网站建设完整流程 - 码云数智
  • 2026年乌鲁木齐旧房翻新、家装全案与工装工程深度横评:源头直采透明报价 本地气候适配工艺 98%转介绍率标杆 - 企业名录优选推荐
  • 2026年江浙沪工业夹爪供应商推荐,适配重载与精密抓取 - 品牌2026
  • 从供应链协同到数字化经营|千匠网络钢材钢筋S2B电商系统搭建,解锁钢贸全新商业模式
  • 【收藏备用】2026年大模型转型必看!小白/程序员零踩坑入门指南,附全套免费资料
  • 别光会编译!用Python和Notepad++手动解析.hex文件,彻底搞懂每一行数据
  • 安徽阜阳六安黄山池州铜陵马鞍山淮南淮北宿州亳州PLC培训机构学校 - 速递信息
  • 2026高效之选:专业的厢式压滤机厂家推荐 - 品牌2025
  • 终极免费ASIO驱动解决方案:如何在Windows上实现专业级音频低延迟
  • 厦门黄金回收六家机构排行实测 避坑指南与本地优选全解析 - 福正美黄金回收
  • 如何轻松将网页HTML转换为可编辑的Figma设计稿?
  • 2026年为什么越来越多的程序员转行网络安全?怎么转?
  • 别再被微信官方文档坑了!手把手教你用Spring Boot实现Token验证接口
  • 2026年乌鲁木齐旧房翻新与家装全案设计:5大本土装修公司深度横评 - 企业名录优选推荐
  • VSCode里装个Baidu Comate插件,AI写代码到底香不香?我用Python和Java实测给你看
  • VS Code Remote-Containers 插件突然失效(v0.312+ 版本特有),官方未文档化的 breaking change 及向下兼容降级路径