Arduino打地鼠游戏机:从74HC595矩阵驱动到状态机编程全解析

news2026/5/25 12:33:13
1. 项目概述用Arduino复刻经典打地鼠游戏作为一个电子爱好者我总想把手头的Arduino和各种元器件玩出点新花样。这次我决定挑战一个经典街机项目——电子打地鼠。市面上虽然有现成的玩具但自己从头设计、画板、编程把一堆零散的LED、按钮和芯片变成一个能玩的游戏机那种成就感是完全不同的。这个项目不仅考验硬件设计能力比如如何用有限的I/O口驱动大量LED和数码管也考验软件上的逻辑和时序控制。最终我完成了一个双人竞技版的Arduino打地鼠游戏机它拥有25个“地鼠洞”LED、8位数码管显示分数和时间以及完整的游戏逻辑。整个系统的核心是一块自主设计的L形主控PCB它通过4片74HC595移位寄存器扩展出32路输出巧妙地驱动了一个25x8的LED矩阵并将8个数码管集成其中。这篇文章我将详细拆解从电路设计、PCB布局到Arduino代码编写的全过程无论你是刚接触Arduino的新手还是想深入了解数字电路和矩阵扫描的爱好者都能从中找到可复现的细节和避坑指南。2. 核心硬件设计与思路解析2.1 系统架构与芯片选型考量项目的核心矛盾在于Arduino Uno有限的I/O口通常仅14个数字口与众多外设需求之间的矛盾。我们需要控制25个LED地鼠、8个7段数码管每段需要7个笔画加1个小数点共8段但通过动态扫描可大幅减少引脚还要读取9个按钮8个地鼠按钮1个开始按钮以及其他输入。直接连接需要数十个I/O显然不现实。我的解决方案是采用“串行转并行”的思路。输出方面选择了经典的74HC595移位寄存器。每片595有8个并行输出通过3根线数据、时钟、锁存即可串联控制多片理论上可以无限扩展。本项目使用了4片595提供了32路输出。为什么是4片这是经过精确计算的8个数码管采用动态扫描每个数码管的8个段选a-gdp需要8路信号阴极或阳极控制而位选信号选择点亮哪个数码管也需要8路。如果采用更常见的1片595控制段选另用一片595或直接使用Arduino口进行位选需要8816路输出。但本项目还将25个LED集成了一个8x9的矩阵中实际用了25个所以是8行x?列具体行列划分后文详述驱动这个矩阵又需要行、列控制线。经过对LED布局和扫描算法的优化最终将数码管段选、位选以及LED矩阵的行、列控制信号全部整合到了这32路输出上做到了“物尽其用”。输入方面按钮则直接利用Arduino的模拟口和数字口并搭配电阻网络做上拉或下拉简化电路。2.2 PCB布局的巧妙构思L形主板与模块化设计为了让整个装置更整洁、可靠我决定设计定制PCB而不是在洞洞板上飞线。PCB分为两大模块L形主控板这是系统的大脑承载Arduino Nano或Uno通过排针连接、4片74HC595、所有必要的电阻、晶体管以及输入输出的接口插座。数码管显示板一块独立的PCB上面焊接8个共阴极CC7段数码管和它们的限流电阻。这块板通过8pin排座与主控板连接。为什么主控板要设计成L形这是本设计的一个亮点。当L形主控板与长方形的数码管显示板拼合时它们能组合成一个更大的规整矩形。这样做有两个巨大优势生产省钱在工厂制板时PCB通常是拼版后一起生产的。L形矩形的组合可以像拼图一样紧密排列最大限度地利用整块覆铜板面积减少了板材浪费对于小批量生产或自己打样能有效降低成本。结构稳固这种拼合方式使得两块PCB在物理上可以互相支撑更容易固定在游戏机的外壳上整体性更强。主控板上使用了大量的排针插座9PIN、8PIN、5PIN等目的是将所有外部连接按钮、LED矩阵、数码管板、电源都通过排线连接便于后续的组装、调试和维护也使得主板看起来非常清爽。3. 电路原理深度剖析3.1 输出驱动移位寄存器矩阵与晶体管扩流4片74HC595串联形成一条32位的串行移位寄存器链。Arduino只需3个数字引脚就能按位送入32个控制信号然后通过一个锁存信号同时更新所有595的输出效率极高。这32路输出被分配用于驱动LED矩阵和数码管LED矩阵驱动25个地鼠灯我将25个LED布置成了一个8行x 4列的矩阵实际用了8x432个位置但只焊接25个对应地鼠洞布局。这样驱动一个8x4的矩阵本来需要8412根线现在通过595的输出可以控制行选通和列数据。行驱动阴极矩阵的8行共用阴极每行的阴极通过一个BC547 NPN晶体管接地。595的输出口直接驱动晶体管基极。这里必须用晶体管因为当一行中多个LED同时点亮时该行阴极的总电流可能超过100mA远超74HC595单个输出口20-35mA的驱动能力。晶体管在这里起到了电流放大和开关的作用。列驱动阳极矩阵的4列对应阳极。每个LED的阳极都串联了一个100Ω的限流电阻然后连接到595的输出上。100Ω的阻值是基于红色LED典型压降2V电源5V期望电流约20mA计算得出的(5V - 2V) / 0.02A ≈ 150Ω选用100Ω可获得稍亮且安全的电流。数码管驱动8个共阴极数码管也采用动态扫描。32路输出中的一部分被分配为8个位选信号通过晶体管控制每个数码管的阴极接地另一部分被分配为8个段选信号控制a-g dp段。动态扫描的原理是在极短的时间内如每秒扫描60帧以上依次快速点亮每一个数码管利用人眼的视觉暂留效应看起来就像是8个数码管同时稳定显示。3.2 输入电路按钮与电阻网络游戏有9个关键按钮8个对应地鼠洞的打击按钮1个游戏开始/复位按钮。此外还预留了玩家选择、难度调节电位器等输入接口。所有按钮都采用下拉电阻的设计。按钮一端接5V另一端通过一个10kΩ电阻接地同时这个连接点也接到Arduino的输入引脚。当按钮未按下时输入引脚通过电阻被拉低到GNDArduino读到LOW当按钮按下时5V直接连接到输入引脚Arduino读到HIGH。这种设计可以有效避免引脚悬空时产生不确定的电平。为了节省空间和焊接工序我没有使用9个独立的10kΩ电阻而是选用了一个SIL-1010联贴片排阻。这个排阻就像一个集成了10个电阻的芯片只有一个公共端。我将公共端接地排阻的另外9个引脚分别连接9个按钮和Arduino的9个输入口完美实现了下拉功能。同样的原理也用在其他输入上使用了SIL-6排阻。注意原计划中还有一个“传感器”输入但因为物料原因最终取消了。这在PCB上留下了一个空置的5pin接口和相应的排阻位置。在你自己设计时如果不确定某个功能是否必要可以像这样预留位置但最好在最终版本中注明或移除避免混淆。4. 软件逻辑与Arduino代码实现4.1 核心状态机与游戏逻辑游戏软件的核心是一个状态机它定义了游戏的不同阶段如“待机”、“进行中”、“游戏结束”等。状态机使程序逻辑清晰易于管理和扩展。enum GameState { IDLE, PLAYING, GAME_OVER }; GameState currentState IDLE; unsigned long gameStartTime; const unsigned long GAME_DURATION 60000; // 游戏时长60秒 int score 0; int currentMole -1; // 当前出现地鼠的位置编号 unsigned long moleTimer; // 地鼠出现/消失的计时器在主循环loop()中通过判断currentState来执行不同的代码块IDLE状态显示欢迎信息等待玩家按下“开始”按钮。PLAYING状态检查游戏时间是否用完用完则切换到GAME_OVER。运行“地鼠生成算法”随机选择一个LED位置作为地鼠并控制其点亮。设置一个随机生存时间如0.5秒到2秒时间到则地鼠消失。实时扫描所有按钮。如果在地鼠存活期间对应的按钮被按下则加分并立即让该地鼠消失给予击中反馈然后快速生成下一个。实时更新数码管显示展示剩余时间和当前分数。GAME_OVER状态显示最终分数等待重启。4.2 底层驱动移位寄存器发送与矩阵扫描这是项目中最关键、最需要精细时序控制的部分。我们需要一个函数能够将代表32个LED和数码管状态的32个比特bit发送到595链中并且还要实现动态扫描。// 假设我们有一个32位的全局变量 shiftRegisterData 来存储所有输出状态 uint32_t shiftRegisterData 0; void updateShiftRegisters() { digitalWrite(LATCH_PIN, LOW); // 由于是32位需要分4次发送每次8位一个字节 // 注意发送顺序最后一片595输出QH的数据最先被送入因为它位于链的末端 shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, (shiftRegisterData 24) 0xFF); // 发送第4片的数据 shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, (shiftRegisterData 16) 0xFF); // 发送第3片的数据 shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, (shiftRegisterData 8) 0xFF); // 发送第2片的数据 shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, shiftRegisterData 0xFF); // 发送第1片的数据 digitalWrite(LATCH_PIN, HIGH); // 锁存数据所有595同时更新输出 }对于LED矩阵和数码管的动态扫描我们需要一个定时中断。Arduino的Timer1库非常适合做这件事。在中断服务程序ISR中关闭当前正在显示的行和数码管位选防止鬼影。根据shiftRegisterData中对应的位计算并设置下一行/下一个数码管需要点亮的LED段或列。打开下一行/下一个数码管的位选导通对应的晶体管。循环进行扫描频率通常设置在100Hz以上画面才会稳定无闪烁。实操心得动态扫描的时序一定要精确。关闭上一帧和开启下一帧之间的间隔要尽可能短否则会出现“鬼影”不该亮的LED微微发亮。确保你的晶体管开关速度足够快BC547没问题并且digitalWrite操作在中断里要高效。可以考虑直接操作Arduino的端口寄存器如PORTB、PORTD来获得极速的引脚控制但这需要对硬件寄存器有了解。4.3 防抖与响应优化按钮输入必须进行软件防抖。机械按钮在按下和弹起的瞬间会产生一段时间的电平抖动可能被Arduino误读为多次按下。const int DEBOUNCE_DELAY 50; // 防抖延时50毫秒 unsigned long lastDebounceTime 0; int lastButtonState LOW; int reading; void checkButton() { reading digitalRead(BUTTON_PIN); if (reading ! lastButtonState) { lastDebounceTime millis(); // 重置防抖计时器 } if ((millis() - lastDebounceTime) DEBOUNCE_DELAY) { // 此时状态稳定进行业务逻辑判断 if (reading HIGH lastButtonState LOW) { // 检测到上升沿按钮被按下 hitMole(); } } lastButtonState reading; }为了游戏体验地鼠的生成算法需要一点“智能”。完全随机可能让地鼠出现在刚被打过的洞里或者长时间不出现在某个角落。可以加入一些权重机制让一段时间未出现的地鼠位置有更高的概率被选中让游戏节奏更均衡。5. 组装、调试与问题排查实录5.1 PCB焊接与组装顺序先贴片后直插首先焊接主控板上的贴片元件如电阻网络SIL。使用烙铁和镊子注意不要连锡。焊接芯片底座务必使用IC插座千万不要把74HC595直接焊死在板上。这样万一芯片损坏静电或接反电源很容易烧更换起来会非常方便。焊接接口排针、排母是连接的核心要确保焊接垂直、牢固。焊接完成后可以用万用表通断档检查是否有虚焊。分模块测试不要等全部焊完再上电。可以先焊接主控板的电源部分和Arduino接口通电测试5V和3.3V是否正常。然后插上一片595写一个简单的测试程序如让它的8个输出依次闪烁验证焊接和芯片是否正常。连接显示板将数码管显示板通过排线连接到主控板。单独测试数码管写一个显示“8.8.8.8.”的程序检查所有段和所有位是否都能正常点亮。连接LED矩阵这部分最繁琐。25个LED是直接安装在外壳上的需要用长脚杜邦线或导线逐个连接到主控板的对应接口。务必做好标记建议先点亮单个再测试一行一列最后用程序扫描整个矩阵。5.2 常见问题与解决方案速查表问题现象可能原因排查步骤与解决方案整个系统无反应电源指示灯不亮1. 电源接反或电压不对2. 主电源线路有短路1. 检查电源适配器极性中心正极常见用万用表测量输出电压是否为5V。2. 断开电源用万用表蜂鸣档测量5V与GND之间的电阻如果接近0欧姆说明存在严重短路需仔细检查焊接。Arduino程序上传失败1. 板卡型号选错2. 串口被占用3. USB线或芯片问题1. 在IDE中正确选择板型如Arduino Nano w/ ATmega328P。2. 关闭可能占用串口的软件如串口监视器、其他IDE。3. 尝试按一下复位键再上传或换一条数据线。部分LED或数码管段不亮1. 该路限流电阻虚焊或阻值错误2. LED本身损坏或极性焊反3. 对应的595输出位损坏1. 用万用表测量电阻两端是否导通阻值是否为100Ω。2. 用万用表二极管档单独测试LED或短接一个已知好的LED到该点位测试。3. 写一个简单程序单独测试该595芯片的每一个输出位看是否都能正常拉高/拉低。显示闪烁、抖动或鬼影严重1. 动态扫描频率太低2. 晶体管开关速度慢或驱动不足3. 中断被长时间关闭1. 提高定时器中断的频率尝试从100Hz提高到200Hz或更高。2. 检查晶体管基极电阻是否合适通常1k-10k确保能提供足够基极电流使其饱和导通。3. 确保在中断服务程序ISR中执行最少的代码避免在loop()或其它地方长时间关闭全局中断。按钮响应不灵或连击1. 软件防抖参数设置不当2. 下拉电阻未接或虚焊3. 按钮本身接触不良1. 调整防抖延时DEBOUNCE_DELAY通常在20-50ms之间寻找最佳值。2. 用万用表测量按钮未按下时输入引脚电压是否接近0VLOW。3. 更换一个按钮测试。游戏运行一段时间后死机或复位1. 电源功率不足2. 程序内存泄漏或堆栈溢出3. 芯片过热1. 所有LED和数码管全亮时电流最大。估算峰值电流如25个LED20mA 8个数码管8段*10mA确保你的5V电源适配器能提供至少1.5A以上的电流。2. 检查代码中是否不当使用了String类或动态内存分配尽量使用静态数组。使用Serial.print(freeMemory())监控内存变化。3. 触摸74HC595和晶体管如果烫手说明电流过大或散热不良检查负载是否有短路。5.3 最终整合与外壳设计当所有电路测试无误后就可以进行总装。将主控板、数码管板固定到自制或改造的外壳内。25个LED作为“地鼠洞”均匀分布在外壳面板上按钮则安装在每个LED旁边。排线整理好并用扎带固定。外壳材料可以选择亚克力、木材或3D打印。设计时务必考虑散热孔虽然功耗不大、按钮手感以及整体的美观度。一个建议是将数码管显示部分稍微抬高让玩家在击打时能轻松看到分数和时间变化。完成所有硬件组装后烧录最终的游戏程序。第一次按下开始按钮看到地鼠随机亮起奋力敲击得分数码管数字飞快跳动——那一刻所有调试的辛苦都值了。这个项目不仅仅是一个游戏机更是一个融合了数字电路、微控制器编程、硬件设计和动手能力的综合实践它带给你的乐趣和知识远超一个成品玩具。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2643906.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…