基于STM32与VFD屏的复古时钟设计:融合蓝牙游戏与动态显示效果
2026/7/29 13:35:41 网站建设 项目流程

1. 项目概述:一个“不务正业”的复古时钟

最近在工作室折腾,手头攒了几个从旧设备上拆下来的VFD屏,一直琢磨着怎么让它们“复活”。VFD,也就是真空荧光显示屏,那种带着幽幽蓝绿光、字符清晰锐利还带点微微光晕的复古质感,是LED和OLED完全给不了的。光是做个普通时钟,感觉有点浪费这块屏的潜力,也对不起它那份独特的工业美学。

于是就有了这个有点“不正经”的想法:做一个会打呼噜还能玩游戏的VFD时钟。它首先得是个精准、好看的时钟,这是本分。但在此之上,我想给它注入一些“灵魂”和“趣味”。所谓“打呼噜”,其实是利用VFD屏的特性,在特定时间(比如深夜)或通过传感器触发,让屏幕上的字符模拟出呼吸、闪烁、波浪等动态效果,就像设备有了生命在“打盹”一样。而“玩游戏”,则是通过蓝牙连接手机,把时钟变成一个简单的双人游戏终端,比如经典的贪吃蛇、俄罗斯方块,或者一个简单的对战小游戏,让时钟在闲暇时也能成为互动的玩具。

这个项目的核心,就是围绕一块VFD屏,融合了实时时钟(RTC)管理、蓝牙无线通信、3D打印外壳设计以及USB供电与数据通信等多个技术点。它不仅仅是一个电子制作,更像是一次对复古技术与现代互动方式的融合实验。无论你是对VFD显示技术着迷的硬件爱好者,还是喜欢给生活增添趣味的创客,亦或是想找一个综合性的嵌入式项目练手,这个项目都能让你玩得很尽兴。

2. 核心设计思路与方案选型

2.1 显示核心:VFD屏的驱动与美学考量

VFD屏是本项目的绝对主角。我选用的是常见的GP1287兼容屏,128x64点阵,单色蓝绿光。选择它主要是因为资料丰富、驱动IC(通常为UC1701或兼容)成熟,并且点阵分辨率足够显示丰富的信息和简单的图形。

驱动VFD屏,核心在于理解其高压需求。屏需要一组较高的阳极电压(通常20V-50V)和灯丝电压(交流3V左右)。市面上有专门的VFD驱动模块(如HV5812、PT6312等芯片的方案),它们集成了升压电路,可以通过SPI或I2C与单片机通信,大大简化了硬件设计。对于这个项目,我直接选用了一个成品的VFD驱动板,它提供了5V输入,内部升压,并通过标准的4线SPI接口与主控通信。这样,我就能把精力集中在软件和功能逻辑上,而不是复杂的模拟电路调试上。

在显示美学上,VFD的亮度调节(PWM调压)是关键。我们计划实现的“打呼噜”效果,本质上就是程序化地、平滑地改变屏幕的整体或局部亮度,模拟出呼吸般的明暗变化。这需要精细的定时器控制和亮度曲线算法。

2.2 主控大脑:性能与接口的平衡

主控芯片需要满足几个条件:足够的计算性能处理图形和游戏逻辑;具备硬件SPI以高速驱动VFD屏;拥有UART接口连接蓝牙模块;最好内置USB功能,方便供电和未来可能的固件升级(DFU)或调试信息输出。

基于这些,STM32F103C8T6(蓝色药丸板)是一个性价比极高的选择。它基于ARM Cortex-M3内核,72MHz主频,拥有丰富的SPI、USART和USB设备接口,内存和Flash也足够应对本项目。更重要的是,其生态极其完善,Arduino Core(STM32duino)和HAL库支持都很好,降低了开发门槛。当然,如果你追求更极致的性能或更多功能(如硬件图形加速),STM32F4系列或ESP32也是不错的升级选项,但F103对于这个项目已经绰绰有余。

2.3 无线交互:蓝牙模块的选型与协议

“玩游戏”的功能依赖于蓝牙。我们需要一个蓝牙串口模块(BLE或经典蓝牙均可),让手机能够与时钟配对并收发数据。

我选择了HC-05或HC-06这类经典的蓝牙2.0+EDR串口模块。它们价格低廉,使用简单,只需通过UART与主控连接,配对后即可实现透明数据传输。虽然功耗比BLE高,但对于这个一直有USB供电的桌面时钟来说不是问题。其优势在于兼容性极广,几乎任何带蓝牙的手机都能连接,并且传输速率足够用于传输简单的游戏控制指令(如上、下、左、右、开始、暂停等)。

通信协议需要简单定义。例如,我们可以规定手机App发送单个字符:‘U’(上)、‘D’(下)、‘L’(左)、‘R’(右)、‘S’(开始)、‘P’(暂停)。时钟主控收到后解析并执行相应游戏动作,同时将游戏状态(如分数、画面矩阵)编码后回传给手机App进行显示。这样,手机就变成了一个无线手柄和副屏幕。

2.4 结构载体:3D打印外壳的设计哲学

一个好的项目需要一个好的“家”。3D打印为个性化外壳提供了无限可能。设计外壳时,我考虑了以下几点:

  1. 功能性:精确留出VFD屏的开窗、USB接口孔、复位按钮孔、以及可能的传感器(如光敏电阻)开口。内部需要设计电路板固定柱和蓝牙模块的卡槽。
  2. 散热:VFD驱动板上的升压电路和主控芯片在长期工作时会有一定发热,外壳需要设计通风孔。
  3. 美学:采用倾斜角度,使屏幕正对使用者视线。外观风格上,可以偏向复古科技风,加入一些装饰性的条纹或网格,与VFD的质感呼应。
  4. 可维护性:设计为底盖或侧盖螺丝固定,方便后期拆装升级。

使用Fusion 360或SolidWorks进行建模,然后用PLA材料打印。PLA强度足够,打印效果好,且易于后期打磨和喷涂。为了提升质感,打印完成后可以进行打磨、喷补土、再喷哑光黑或深灰色漆,最后贴上一些装饰性的贴纸或铭牌。

2.5 能源与数据:USB的双重角色

USB接口在这里扮演了双重角色:电源输入通信通道

  • 电源:标准的USB 5V/0.5A输出足以驱动整个系统(VFD屏、主控、蓝牙模块)。电路板上需要设计一个Micro-USB或Type-C母座,以及相应的5V稳压和滤波电路(虽然很多模块板载了LDO)。
  • 通信:利用STM32F103内置的USB设备功能,我们可以将其虚拟成一个串口(CDC类)。这样,通过一根USB线连接到电脑,就可以像操作普通串口一样,实时输出调试日志、接收控制命令,甚至进行固件的拖拽式更新(配合DFU引导程序),极大方便了开发和维护。

3. 硬件系统搭建与核心电路解析

3.1 电路框图与模块连接

整个系统的硬件核心是一块自主设计或整合的主控板,它作为“中央枢纽”连接各个模块:

[USB接口] -> [5V电源稳压] -> 为整个系统供电 | v [STM32F103C8T6] | |----------------|----------------| | | | [SPI] [UART1] [USB DM/DP] | | | [VFD驱动板] [蓝牙模块(HC-05)] [USB虚拟串口] | | [VFD显示屏] [手机(无线)]
  • 主控与VFD驱动板:通过SPI(SCK, MOSI, CS, RESET)连接。注意,有些驱动板还需要一个背光/亮度控制引脚,通常用主控的另一个GPIO进行PWM控制。
  • 主控与蓝牙模块:通过UART(TX, RX, VCC, GND)连接。通常只需连接TX/RX和电源,蓝牙模块的KEY引脚用于进入AT指令模式,可以接一个按钮到主控,或者直接通过上拉/下拉电阻固定其工作模式(从模式)。
  • USB接口:直接连接到STM32的USB DM(D-)和DP(D+)引脚,并接入5V和GND。

3.2 电源电路设计要点

虽然各模块可能自带稳压,但一个稳健的全局电源设计是必要的。建议在主控板入口处放置一个AMS1117-3.3V线性稳压芯片,将USB输入的5V转为3.3V,为STM32核心及所有需要3.3V电平的IO口供电。VFD驱动板通常需要5V输入,可以直接从USB 5V取电。

注意:务必在USB电源入口、各稳压芯片的输入输出端并联足够容量的滤波电容(如10uF电解电容+0.1uF陶瓷电容),以抑制电源噪声,这对数字电路和VFD高压电路的稳定工作至关重要。

3.3 时钟与复位

STM32的外部高速晶振(HSE)使用8MHz,这是最常见的选择。配合内部PLL倍频至72MHz。外部低速晶振(LSE)使用32.768kHz,用于驱动内置RTC(实时时钟),确保即使在主电源断开(如果有备用电池)时,时间也能持续走时。复位电路采用经典的RC复位(10k电阻上拉,0.1uF电容到地),也可以再加一个手动复位按钮。

4. 软件架构与核心功能实现

4.1 开发环境与基础工程搭建

我选择使用PlatformIO作为开发环境,它基于VSCode,对STM32的Arduino框架和HAL库支持都很好,库管理也非常方便。工程创建时选择板子为“BluePill F103C8”。

首先需要配置关键的库依赖:

  • U8g2库:这是一个强大的单色图形库,支持海量显示器,包括我们的VFD屏(通常兼容UC1701驱动)。它提供了丰富的绘图API(点、线、矩形、圆、文字)和多种字体,是显示层的基石。
  • SoftwareSerial或HardwareSerial:用于与蓝牙模块通信(如果主UART被USB占用,可能需要软件模拟)。
  • RTClib:用于处理RTC模块(如DS3231)或STM32内部RTC的日期时间读写。本项目优先使用STM32内部RTC。

4.2 核心任务调度:状态机与定时器

系统需要同时处理多种任务:更新显示、读取RTC时间、检测蓝牙数据、处理游戏逻辑、执行“打呼噜”动画等。一个清晰的状态机是必要的。

我采用基于定时器中断的协作式调度。设置一个硬件定时器(如SysTick或TIM2)每1ms产生一次中断。在中断服务程序中更新一个全局的millis()计数器,并设置一些标志位。在主循环loop()中,通过检查millis()的差值来判断是否执行某个周期性任务。

// 伪代码示例 unsigned long lastDisplayUpdate = 0; unsigned long lastClockUpdate = 0; unsigned long lastBreathEffect = 0; void loop() { unsigned long now = millis(); // 任务1:每50ms更新一次显示(20Hz,足够流畅) if (now - lastDisplayUpdate >= 50) { updateDisplay(); lastDisplayUpdate = now; } // 任务2:每1秒更新一次时钟数据 if (now - lastClockUpdate >= 1000) { updateTimeFromRTC(); lastClockUpdate = now; } // 任务3:每20ms处理一次呼吸效果(如果激活) if (breathEffectEnabled && (now - lastBreathEffect >= 20)) { updateBreathEffect(); lastBreathEffect = now; } // 任务4:持续检查蓝牙串口是否有数据 processBluetoothData(); // 其他任务... }

4.3 “打呼噜”效果:动态亮度算法

“打呼噜”效果的核心是平滑的亮度变化。VFD驱动板通常有一个引脚(如BLPWM)用于控制亮度,接受PWM信号。

我们可以用数学函数来生成平滑的亮度曲线。最常用的是正弦波或三角波。

// 使用正弦波模拟呼吸效果 void updateBreathEffect() { // 计算当前时间在周期中的相位 (0 到 2*PI) float phase = (millis() % breathPeriod) * 2.0 * PI / breathPeriod; // 正弦值范围[-1, 1],映射到[0.2, 1.0]的亮度系数,保留最低亮度避免熄灭 float brightnessFactor = (sin(phase) + 1.0) / 2.0 * 0.8 + 0.2; // 计算PWM占空比 (假设PWM分辨率为255) int pwmValue = (int)(brightnessFactor * 255); // 设置PWM输出 analogWrite(VFD_BRIGHTNESS_PIN, pwmValue); }

可以设计多种“呼噜”模式:简单呼吸、随机闪烁、波浪式滚动(通过改变不同屏幕区域的亮度)等,并通过蓝牙指令或按钮切换。

4.4 游戏引擎:简化版贪吃蛇实现

以贪吃蛇为例,在128x64的点阵上实现,每个点作为一个像素。

  1. 数据结构:用数组存储蛇身的每个节点坐标。用一个结构体表示食物坐标。用一个变量表示当前移动方向。
  2. 游戏循环:在特定的游戏状态GAME_PLAYING下,每隔一个固定的时间间隔(如200ms),蛇向当前方向移动一格。
  3. 碰撞检测:检查蛇头是否碰到边界、自身或者吃到食物。
  4. 画面渲染:使用U8g2库的drawPixeldrawBox函数,根据蛇身和食物坐标绘制画面。同时绘制分数和边界。
  5. 蓝牙控制:将接收到的蓝牙字符‘U’, ‘D’, ‘L’, ‘R’映射为改变蛇的方向。游戏状态(开始、暂停、结束)和分数也可以通过蓝牙发送到手机App显示。

4.5 蓝牙通信协议与手机端交互

协议设计追求极简。定义一组单字节命令:

  • 手机 -> 时钟:‘S’开始游戏,‘P’暂停,‘U/D/L/R’方向控制,‘M’切换模式(时钟/游戏/特效)。
  • 时钟 -> 手机:可以定期或事件触发发送数据包。例如,可以定义一个简单的文本协议:“SCORE:123\n”“GAME:OVER\n”

手机端可以开发一个简单的App(使用MIT App Inventor、Flutter或原生开发),也可以先用现成的蓝牙串口调试助手进行测试。后期可以定制一个界面,显示时钟发送过来的游戏画面(简化版)或直接作为虚拟手柄。

5. 3D外壳设计与组装工艺

5.1 建模关键步骤

  1. 精确测量:使用游标卡尺测量VFD屏、驱动板、主控板、蓝牙模块、USB座等所有元件的精确尺寸和安装孔位。
  2. 主体设计:在Fusion 360中,先创建一个倾斜约10-15度的前面板,根据VFD屏的视窗尺寸开出显示窗口。窗口内侧应设计一个台阶,用于从内部卡住屏幕,防止其掉落。
  3. 内部结构:根据电路板尺寸,设计内部的支撑柱和卡槽。支撑柱上要预留螺丝孔(通常用M2或M2.5的自攻螺丝)。为蓝牙模块设计一个带卡扣的固定位,并为其天线区域(通常模块尾部)留出空间,避免金属屏蔽。
  4. 通风与走线:在顶部或背部设计一些格栅状的通风孔。内部预留USB线和其他连接线的走线通道,避免杂乱。
  5. 底盖设计:底盖与主体通过四周的螺丝柱连接。可以在底盖上增加四个橡胶脚垫,增加稳定性和防滑性。

5.2 打印与后处理心得

  • 打印设置:层高0.2mm,填充率15%-20%即可。外壳通常不需要太高强度。对于有悬垂的结构(如内部卡扣),需要启用支撑。建议使用哑光或丝绸质感的PLA,本身就有不错的外观。
  • 后处理
    1. 打磨:用砂纸(从240目到800目)仔细打磨打印件的层纹和毛刺,特别是显示窗口边缘和外壳接缝处。
    2. 喷涂:推荐使用模型用的水补土喷罐打底,可以检查并填补细微的瑕疵。干透后,再喷上2-3层哑光黑或深灰色面漆。哑光漆能更好地隐藏打印痕迹,并凸显VFD屏的亮光。
    3. 组装:先进行内部电路的安装和测试,确保所有功能正常后再合盖。螺丝不要一次性拧得太紧,先对角预紧,再逐步拧紧,防止外壳受力不均开裂。

6. 系统集成、调试与问题排查

6.1 上电顺序与联合调试

  1. 分模块测试:先不组装,用杜邦线连接各模块。单独测试VFD屏能否点亮并显示测试图形;单独测试蓝牙模块能否被手机搜索并配对成功,串口通信是否正常;测试STM32的USB虚拟串口能否被电脑识别。
  2. 逐步集成:先将VFD屏与主控连接,烧写一个简单的显示测试程序。然后接入蓝牙模块,编写一个回显程序(主控将蓝牙收到的数据原样发回)。最后整合所有功能。
  3. 功耗监测:在USB电源入口串联一个万用表,监测整机工作电流。正常情况应在300-500mA左右。如果电流异常大,立即断电检查是否有短路或某个模块异常发热。

6.2 常见问题与解决方案实录

以下是我在制作过程中踩过的坑和解决方法:

问题现象可能原因排查步骤与解决方案
VFD屏不亮或亮度极低1. 电源接反或电压不足。
2. 背光/亮度控制引脚未正确配置。
3. SPI通信失败。
1. 确认VFD驱动板供电为5V,极性正确。
2. 检查亮度控制引脚是否设置为PWM输出模式,并输出一个中等占空比的值。
3. 用逻辑分析仪或示波器检查SPI的CS、SCK、MOSI信号,确认时序和电平正确。
蓝牙模块无法被手机搜索到1. 模块未进入配对模式(指示灯未快闪)。
2. 模块已与其他设备配对并记忆。
1. 检查KEY引脚电平。对于HC-05,上电前将KEY拉高(接VCC)再上电,会进入AT指令模式;拉低或悬空则进入自动连接模式。确保其在正确模式。
2. 在AT指令模式下,发送AT+ORGL恢复出厂设置,AT+RESET重启。
USB虚拟串口无法识别1. 电脑缺少驱动。
2. STM32的USB DP引脚未接1.5k上拉电阻。
3. 代码中USB CDC配置不正确。
1. 安装STM32的USB CDC驱动(如STTinyUSB的驱动)。
2. 检查原理图,DP引脚需要通过一个1.5k电阻上拉到3.3V。
3. 检查PlatformIO的platformio.ini配置,是否包含了正确的USB框架定义(如framework = arduino, build_flags = -D PIO_FRAMEWORK_ARDUINO_ENABLE_CDC)。
游戏操作延迟大1. 蓝牙模块通信速率低。
2. 主控处理游戏逻辑的周期太长。
3. 手机App处理效率低。
1. 将蓝牙模块的串口波特率设置为115200或更高(需双方匹配)。
2. 优化游戏代码,避免在loop()中使用delay(),改用状态机和定时器标志位。
3. 简化手机与时钟之间的通信协议,只传输必要指令,减少数据量。
RTC时间走时不准1. 外部32.768kHz晶振未起振或负载电容不匹配。
2. 未正确初始化RTC时钟源。
1. 检查晶振焊接,负载电容通常为两个6-12pF的贴片电容。晶振外壳应接地。
2. 在STM32CubeMX或代码中,确认RTC时钟源选择为LSE(外部低速晶振),并正确配置了预分频器。

6.3 性能优化与功能扩展

  • 显示优化:U8g2库提供了多种缓冲模式。对于128x64这种分辨率,使用全屏缓冲U8G2_ST7565_..._1会占用1KB内存,但绘制最简单。如果内存紧张,可以使用分页缓冲模式。
  • 低功耗模式:虽然本项目主要USB供电,但可以探索在“深夜模式”下,当检测到环境光很暗且无人操作时,让STM32进入停机(Stop)模式,仅RTC工作,大幅降低功耗,此时VFD屏完全关闭。
  • 更多游戏:除了贪吃蛇,还可以实现打砖块、飞机大战等经典游戏。关键在于设计一个高效的、基于像素的简单图形引擎。
  • 网络校时:可以增加一个ESP-01S WiFi模块,让时钟通过NTP协议从网络获取精确时间,实现自动校时。
  • 传感器互动:增加一个PIR人体感应传感器,当人靠近时自动点亮屏幕或切换显示模式;增加一个麦克风传感器,让“打呼噜”的节奏和音量随环境噪音变化,增加趣味性。

这个项目从构思到实现,最大的乐趣在于将冰冷的硬件赋予了互动的温度和个性的表达。看到那块散发着复古光芒的屏幕,不仅能告诉你时间,还能与你一起游戏,甚至像个小生命一样“呼吸”,所有的调试和打磨都变得值得。它摆在桌面上,不仅仅是一个工具,更是一个充满工程师浪漫的对话者。

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

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

立即咨询