1. 项目概述从旧货堆里“复活”一个全频段接收机几年前我在一家旧货商店里以极低的价格淘到了一台数字电视机顶盒和一台老旧的索尼音响发射器又在另一台报废的CRT电视里拆出了它的模拟高频头。看着这些来自不同时代的射频“遗物”一个想法冒了出来能不能把它们整合起来用我们熟悉的Arduino去“驯服”这些复杂的射频电路做一个既能收数字电视、又能听FM广播甚至还能窥探一下其他频段比如那个索尼发射器的915MHz的万能接收机这个想法就是本项目的起点。这不仅仅是一个简单的“连线”项目。它的核心挑战在于如何让一个8位的微控制器去理解和控制那些专为模拟或专用芯片设计的射频前端。答案就是相位锁定环PLL。PLL是现代无线通信的基石它就像一个极其聪明的“频率锁”能够使一个可变的本地振荡器LO紧紧“跟随”一个非常稳定的参考频率。通过微控制器这里用了Arduino Nano和Seeeduino XIAO经由I2C总线向PLL芯片发送指令我们就能精确地设定接收机要“倾听”的频率从而实现频道调谐。整个系统的“大脑”是Arduino它负责与PLL通信、处理红外遥控指令、管理频道列表。“眼睛”则是两块从老旧设备上拆下的真空荧光显示屏VFD它们负责显示频率、频道等信息那种泛着绿光的复古味道是液晶屏无法替代的。“耳朵”是那个模拟电视高频头和数字电视调谐器模块。“喉咙”则是一台老索尼卡座改造的音频放大器。本文将详细拆解如何将这些看似不相关的部件通过硬件连接和软件编程整合成一个功能完整、可玩性极高的射频接收平台。无论你是对射频技术感兴趣的硬件爱好者还是喜欢用Arduino“折腾”旧硬件的创客都能从中获得从理论到实践的全流程参考。2. 核心思路与系统架构设计2.1 为什么选择PLL作为调谐核心在射频接收领域调谐的本质就是“选择”。从空中无数混杂的电磁波中精准地选出我们想要的那个频率点。早期收音机采用可变电容或变容二极管进行模拟调谐精度和稳定性都较差。而现代接收设备几乎清一色使用基于PLL的频率合成器。PLL的工作原理可以类比为一个智能化的“速度跟随系统”。假设你的目标是让一辆车VCO压控振荡器输出的速度严格等于一个参考速度参考时钟。你有一个速度表相位检测器不断比较两辆车的速度差并将这个差值转换成油门或刹车的控制信号电荷泵输出经环路滤波后成为VCO控制电压去调整目标车的速度直到两者完全同步。在锁定时VCO的输出频率就是参考频率的精确整数倍N倍这个倍数N正是由微控制器通过数据总线设定的。因此我们只需通过Arduino改变N值就能以极高的频率分辨率和稳定性将VCO锁定在任何想要的频率上从而为混频器提供精准的本振信号完成频道选择。对于本项目数字电视调谐器模块和模拟电视高频头内部都集成了PLL芯片。我们的任务不是从头设计PLL电路而是“逆向工程”其控制协议用Arduino模拟原主板上的微控制器通过I2C总线向这些PLL芯片发送正确的数据命令它们锁定到特定频率。2.2 整体系统架构与信号流整个项目的信号流和控制流可以清晰地分为几条主线射频信号通路天线接收空中的射频信号。对于弱信号如遥远的FM电台我额外加装了一个宽带放大器天线。调谐器前端信号分别进入数字DVB-T调谐器和模拟PAL/NTSC高频头。它们内部的低噪声放大器LNA对信号进行初步放大。频率变换两个调谐器内部的混频器在PLL生成的本振信号作用下将接收的高频射频信号下变频至固定的中频IF。数字调谐器通常输出零中频或低中频的I/Q数字信号而模拟高频头输出的是38MHz或类似频率的模拟中频信号。解调与输出数字调谐器模块通常通过并行或串行接口如TS流输出解调后的数字音视频数据本项目主要利用其音频部分。模拟高频头输出的中频信号需要进一步解调我利用其内部或外部的鉴频器解调出FM广播的音频信号。音频切换与放大使用一颗从旧电视上拆下的模拟音频多路复用器芯片如CD4052在Arduino控制下选择数字电视音频或模拟FM音频。选中的音频信号送入老索尼卡座的自带功放电路进行放大驱动扬声器。控制与显示系统主控Arduino Nano负责核心业务逻辑。它读取红外遥控器的指令根据指令计算对应的频率和PLL分频比N通过I2C总线控制两个调谐器。同时它通过另一个I2C通道将需要显示的信息如频率、频道号发送给显示控制器。显示控制器Seeeduino XIAO专司VFD驱动。它通过I2C从主控接收显示数据然后通过高速GPIO模拟时序控制多片SN75518 VFD驱动移位寄存器动态扫描点亮两块VFD屏的所有段码和网格。人机交互一个旧电视遥控器被重新利用其红外编码被Arduino接收和解码用于实现频道切换、音量调节、信号源选择等功能。注意安全第一。本项目涉及从旧设备拆解高压部件如VFD的灯丝和阳极电压、CRT电视高频头。在操作前务必确保设备已完全断电并放电。特别是为VFD供电的32V电源接线时需格外小心避免短路。建议在通电调试时使用电流限流电源。3. 硬件拆解、选型与接口逆向工程3.1 关键部件来源与特性分析项目的硬件核心是几个淘来的旧货它们的选型直接决定了系统的能力和复杂度。数字电视调谐器Goodwill商店$6这是一个完整的DVB-T接收模块通常包含硅调谐器如Rafael Micro R820T和解调器芯片。其优势是集成度高通常通过I2C控制并直接输出数字音频流方便处理。难点在于找到其数据手册以了解其I2C地址、寄存器映射和控制命令序列。模拟电视高频头废旧CRT电视这是一个典型的“罐头”式高频头内部包含VHF/UHF波段切换、PLL频率合成器常见芯片如TDA5736, LA7530等和混频器。其输出是模拟中频信号。控制接口通常是I2C总线或三线总线时钟、数据、使能。需要根据型号查找资料确定其控制协议。索尼915MHz发射器音响系统$7这是一个有趣的部件。它工作在915MHz ISM频段本意是无线音频传输。在本项目中我尝试将其作为接收前端去接收该频段附近的信号如一些民用对讲设备。这需要对它的接收模式如果有或电路进行改造极具实验性。VFD显示屏旧设备拆机显示屏A14位复合显示。第一排是5x7点阵可用于显示字符或简单图形第二排混合了图标、2位7段码和9位14段码非常适合显示频率数字如“108.5 MHz”和状态图标如FM立体声标志。显示屏B13段9位数字加图标屏更专注于数字显示。 它们的驱动逻辑复杂需要动态扫描且需要较高的驱动电压通常段压为12-50V灯丝交流或直流3-5V。这就是为什么需要专用的SN75518驱动芯片和独立的32V电源。SN75518 VFD驱动芯片这是本项目的显示驱动核心。每片SN75518是一个32位移位寄存器带锁存和高压输出驱动。通过级联可以控制海量的段和网格。编程的关键在于精确的时序控制以实现稳定无闪烁的扫描。3.2 PLL控制接口的逆向与连接这是项目的第一个技术难关。通常没有原设备的原理图我们需要通过观察原电路板、测量和查阅芯片资料来破解。物理接口识别在调谐器模块或高频头上找到一组连接主板的排针或焊点。通常会有VCC、GND、SCL时钟、SDA数据四根线这就是I2C接口。有时还会有一条“使能”或“地址选择”线。逻辑分析仪抓包这是最有效的方法。将逻辑分析仪的通道连接到疑似I2C的线上给原设备上电并操作如用原遥控器换台捕获总线上的数据流。通过分析数据包可以确定I2C地址、写入寄存器的数据以及这些数据与显示频率之间的关系。例如你可能会发现每次换台都会向地址0xC0写入一组数据其中两个字节与频道频率呈线性关系。计算分频比N根据捕获的数据和已知的参考频率通常为4MHz或更精确的晶体可以反推出PLL的分频比N的计算公式。公式通常为频率 (N * 参考频率) / R其中R是参考分频比通常是固定的。Arduino的程序就需要根据目标频率实时计算出对应的N值并组装成符合芯片格式的数据帧发送出去。Arduino连接将Arduino Nano的A4SDA、A5SCL引脚通过上拉电阻通常4.7kΩ连接到调谐器的I2C总线。务必共地。如果调谐器需要3.3V电平而Arduino是5V则需要使用电平转换器。3.3 VFD驱动电路设计与布线心得驱动VFD是另一个挑战涉及高压和复杂的多路复用扫描。电源分离VFD需要三组电源灯丝电压AC 3.5V、栅极/阳极驱动高压DC 32V、逻辑电源DC 5V。我使用了一个旧的打印机电源提供32V高压一个单独的变压器提供灯丝交流电压Arduino的5V为SN75518的逻辑部分供电。务必确保这些电源的地线在一点共地否则会导致显示混乱或驱动芯片损坏。SN75518级联策略对于显示屏A段码和网格数量众多。我采用了两片SN75518一片专门驱动所有段码包括点阵、7段、14段的所有段另一片专门驱动所有网格点阵的行、各位数字的网格。这种“段-栅分离”的驱动方式简化了扫描逻辑。对于显示屏B由于段和栅数量较少我用一片SN75518同时驱动段和栅通过分时复用数据来实现。布线注意事项高压走线32V走线要尽量粗短远离逻辑信号线避免噪声耦合。灯丝连接灯丝通常有两根引脚直接接入交流电压即可。有时为了显示均匀会在灯丝两端对地接一个偏置电阻。限流电阻在每个段码的输出引脚上建议串联一个限流电阻如2kΩ以保护VFD和驱动芯片防止过流。驱动电流SN75518的高压输出驱动能力有限通常几十mA。在设计扫描逻辑时必须确保同一时刻点亮的段码总电流不超过芯片极限。这需要通过软件限制同时点亮的段数即降低占空比来实现。4. 软件框架与核心驱动实现4.1 开发环境与项目配置我选择了PlatformIO Visual Studio Code作为开发环境而非传统的Arduino IDE。PlatformIO提供了更专业的库管理、构建系统和调试体验特别适合这种多文件、多板卡的项目。platformio.ini配置示例[env:seeed_xiao] platform atmelsam board seeed_xiao framework arduino monitor_speed 115200 [env:nanoatmega328] platform atmelavr board nanoatmega328 framework arduino monitor_speed 115200这个配置文件定义了两个环境一个用于Seeeduino XIAO显示控制器一个用于Arduino Nano主控制器。可以方便地分别编译和烧录。4.2 主控制器Arduino Nano软件设计主程序的逻辑围绕状态机展开核心文件是main.cpp。红外遥控解码#include IRremote.h IRrecv irrecv(RECV_PIN); decode_results results; void setup() { irrecv.enableIRIn(); } void loop() { if (irrecv.decode(results)) { uint32_t command results.value; switch(command) { case 0xFFA25D: // CH 按钮 currentChannel; tuneToChannel(currentChannel); updateDisplayFrequency(); break; // ... 处理其他按钮 } irrecv.resume(); } }使用IRremote库将旧遥控器的每个按键编码映射到具体的功能换台、音量、切换TV/FM。PLL控制函数 这是最核心的函数。需要为每个调谐器编写独立的控制函数。void tuneSi4703(uint16_t frequencyKHz) { // 1. 计算分频比N (以10kHz为步进参考频率为32.768kHz为例) uint16_t N (frequencyKHz * 100) / 32768; // 假设PLL结构 // 2. 组装I2C数据帧 (根据芯片手册) uint8_t data[4]; data[0] 0x20; // I2C地址 写命令 data[1] (N 8) 0x3F; // N的高位保留控制位 data[2] N 0xFF; // N的低位 data[3] 0x10; // 其他控制位如开启振荡器 // 3. 通过I2C发送 Wire.beginTransmission(SI4703_ADDR); Wire.write(data, 4); Wire.endTransmission(); delay(50); // 等待PLL锁定 }关键点每个芯片的数据格式、字节顺序、控制位含义都不同必须严格参照数据手册或逆向工程的结果。delay(50)是必要的给PLL电路足够的时间锁定到新频率。频道管理与音频切换 在EEPROM或数组中存储一个频道列表包含频率、信号源TV/FM、名称等信息。tuneToChannel函数根据频道号索引这个列表调用对应的PLL控制函数并控制模拟多路复用器芯片如CD4052选择正确的音频源。void selectAudioSource(bool isFM) { digitalWrite(MUX_SEL_A, isFM ? HIGH : LOW); digitalWrite(MUX_SEL_B, isFM ? LOW : HIGH); // 具体逻辑取决于CD4052真值表 }4.3 显示控制器Seeeduino XIAO与VFD驱动显示控制器被设计为一个I2C从设备它等待主控发送显示数据然后负责繁重的扫描刷新工作。我将显示逻辑封装成了几个库文件如Display.h,DisplayData.h。数据结构设计(DisplayData.h)struct DisplayFrame { uint8_t vfdId; // 标识是哪块屏 uint8_t digitPos[14]; // 每个位置显示的字符编码 bool icons[8]; // 图标开关状态 uint32_t segmentMap; // 对于点阵屏可能需要位图 };主控通过I2C发送这个结构体的数据。SN75518驱动底层函数void shiftOutSN75518(uint32_t segmentData, uint32_t gridData) { // 确保时钟初始为低 digitalWrite(CLK_PIN, LOW); // 先移入段数据32位 for (int i 31; i 0; i--) { digitalWrite(DATA_PIN, (segmentData i) 0x01); digitalWrite(CLK_PIN, HIGH); delayMicroseconds(1); // 关键SN75518需要一定的建立时间 digitalWrite(CLK_PIN, LOW); } // 再移入栅数据如果使用独立芯片 for (int i 31; i 0; i--) { digitalWrite(DATA_PIN, (gridData i) 0x01); digitalWrite(CLK_PIN, HIGH); delayMicroseconds(1); digitalWrite(CLK_PIN, LOW); } // 锁存信号将移位寄存器的数据输出到驱动级 digitalWrite(LATCH_PIN, HIGH); delayMicroseconds(1); digitalWrite(LATCH_PIN, LOW); }delayMicroseconds(1)是调试出来的关键延时太快会导致数据采样错误显示乱码。动态扫描引擎 VFD采用多路复用驱动以节省引脚。例如14位数字屏每次只点亮一位数字对应的栅极为高电平并点亮该数字上需要亮起的段。然后快速切换到下一位利用人眼视觉暂留形成稳定显示。void refreshDisplay() { for (int grid 0; grid TOTAL_GRIDS; grid) { uint32_t gridPattern 1UL grid; // 只有当前栅极为高 uint32_t segmentPattern getSegmentPatternForGrid(grid); // 获取该位应显示的段码 shiftOutSN75518(segmentPattern, gridPattern); delayMicroseconds(SCAN_DELAY); // 扫描延时影响亮度 // 在切换到下一位前先关闭所有段防止“鬼影” shiftOutSN75518(0, 0); } }SCAN_DELAY需要调整太短亮度低太长会闪烁。通常控制在1-3ms之间。关闭所有段再切换网格是消除“鬼影”上一个数字的残影的关键技巧。5. 系统集成、调试与问题排查实录5.1 分模块调试流程不要试图一次性连接所有部件。务必分步进行Arduino与PLL调谐器先单独连接一个调谐器如模拟高频头。编写一个简单的测试程序循环发送几个已知的频率值如FM 98.1MHz。用一台收音机或频谱仪靠近调谐器本振泄露点确认频率是否变化。这是验证I2C通信和控制逻辑是否正确的基础。音频通路暂时抛开调谐器用函数信号发生器或手机音频线直接向音频多路复用器和功放输入信号测试音频切换和放大功能是否正常。VFD显示单独测试显示控制器。编写一个静态显示测试程序如让所有段全亮检查硬件连接和电源。然后测试动态扫描观察是否有数字缺划、亮度不均或鬼影。红外遥控单独测试红外接收在串口监视器中打印解码出的按键码建立按键码与功能的映射表。逐步集成将调试好的PLL控制、音频切换集成到主控。然后加入红外控制。最后将主控与显示控制器通过I2C连接测试完整的“按键-换台-显示”流程。5.2 典型问题与解决方案速查表在集成过程中我遇到了许多问题以下是其中一些典型问题及其解决方法问题现象可能原因排查步骤与解决方案PLL不锁定收不到信号1. I2C地址错误。2. 数据格式或字节顺序错误。3. 参考频率不匹配。4. 环路滤波器元件问题对拆机高频头。1. 用逻辑分析仪确认I2C通信是否发生地址是否正确。2. 仔细核对芯片数据手册或逆向工程数据确认控制字每一位的含义。3. 测量调谐器上的晶振频率确保计算N值时使用的参考频率正确。4. 检查高频头上PLL芯片周围的电容电阻特别是环路滤波器的电容老化或损坏会导致无法锁定。VFD显示暗淡或有鬼影1. 扫描延时(SCAN_DELAY)设置不当。2. 段码关闭不彻底。3. 驱动电压不足。4. 灯丝电压偏低。1. 调整SCAN_DELAY找到亮度与稳定性的平衡点。2. 确保在切换网格前有语句将段码数据清零 (shiftOutSN75518(0, ...))。3. 测量驱动芯片输出脚电压是否接近32V。检查高压电源的负载能力。4. 测量灯丝电压交流应在3.0-3.5VAC左右。显示乱码或部分段常亮1. SN75518移位时序错误。2. 级联顺序错误。3. 硬件连接有虚焊或短路。4. 电源噪声干扰。1.最关键检查shiftOutSN75518函数中的时钟和数据时序特别是delayMicroseconds(1)是否必要且足够。2. 确认段和栅的数据送入顺序与硬件级联顺序匹配。3. 用万用表蜂鸣档仔细检查所有连接。4. 在VFD逻辑电源5V和高压电源32V入口处并联一个10-100uF的电解电容和一个0.1uF的瓷片电容进行滤波。红外遥控不响应或误触发1. 红外接收头型号不对38kHz载波。2. 接收头电源不稳。3. 环境光干扰如日光灯。4. 解码库配置错误。1. 确认接收头是VS1838B等常见38kHz型号。2. 在接收头VCC和GND之间加一个10uF电容。3. 用深色热缩管或胶带包裹接收头避免直射光。4. 检查IRrecv初始化时指定的引脚是否正确尝试使用不同的解码协议。音频噪声大嘶嘶声或嗡嗡声1. 地线环路。2. 电源噪声耦合到音频线。3. 调谐器解调不良或信号弱。1.最重要确保所有设备Arduino、调谐器、功放的“地”在一点连接形成星型接地。2. 使用屏蔽音频线屏蔽层单端接地通常在功放端。3. 检查天线连接尝试调整天线位置。对于模拟高频头微调其中周变压器如果有可能改善解调效果。5.3 关于“收听卡车司机通话”的说明在项目描述中我提到通过模拟高频头和放大器天线收听到了附近高速公路卡车司机的通话。这涉及到民用对讲机频段如CB Radio 27MHz或商用对讲频段如VHF 150-170MHz。模拟电视高频头通常覆盖VHF低波段48-92MHz和高波段175-230MHz部分覆盖UHF470-860MHz。卡车司机常用的频段可能落在VHF高波段内。重要提示收听这些信号仅出于技术学习和实验目的。你必须了解并严格遵守所在国家/地区关于无线电监听的法律法规。绝对禁止干扰任何正常通信也严禁将设备用于非法目的。本项目所有内容仅限于技术探讨和合法范围内的业余无线电实验。6. 项目总结与扩展思考经过数周的调试和改进这个由旧货拼凑而成的接收机终于稳定工作。数字电视能清晰解码出电台FM广播的音质也令人满意VFD显示屏泛出的柔和绿光赋予了它独特的复古科技美感。最重要的是通过亲手实现从I2C指令到射频调谐再到动态显示的全过程对PLL原理、射频前端和嵌入式系统协同工作的理解变得无比真切。回顾整个过程有几点心得尤为深刻首先逆向工程需要耐心和工具。没有逻辑分析仪破解PLL的I2C协议几乎寸步难行。在动手写代码前花时间用仪器观察和理解原始信号流能节省大量盲目试错的时间。其次电源和地线是模拟-数字混合系统的生命线。最初的版本音频噪声很大显示也不稳定最终都是通过优化电源布局、加强滤波和重构单点接地来解决的。在面包板或洞洞板上搭建复杂系统时要有意识地将数字部分和模拟/高压部分在物理上和电源上隔离开。最后模块化编程至关重要。将显示驱动、PLL控制、红外解码分别封装成独立的库或头文件使得代码结构清晰调试时能快速定位问题。PlatformIO的环境管理功能也让同时管理主控和显示控制器两个固件变得轻松。这个项目还有很大的扩展空间。例如可以加入一个软件定义的无线电SDR前端如RTL-SDR用电脑进行更复杂的信号分析和解码可以为VFD增加频谱瀑布图显示甚至可以尝试用ESP32替换Arduino Nano增加网络流媒体推送功能。它不仅仅是一个接收机更是一个开放的射频实验平台。每一次对频率的探索都像是在电磁波的海洋中进行一次小小的航行而手中的Arduino和这些老旧的硬件就是你的罗盘与帆船。
基于Arduino与PLL的旧硬件改造:打造全频段射频接收机
发布时间:2026/6/2 14:27:04
1. 项目概述从旧货堆里“复活”一个全频段接收机几年前我在一家旧货商店里以极低的价格淘到了一台数字电视机顶盒和一台老旧的索尼音响发射器又在另一台报废的CRT电视里拆出了它的模拟高频头。看着这些来自不同时代的射频“遗物”一个想法冒了出来能不能把它们整合起来用我们熟悉的Arduino去“驯服”这些复杂的射频电路做一个既能收数字电视、又能听FM广播甚至还能窥探一下其他频段比如那个索尼发射器的915MHz的万能接收机这个想法就是本项目的起点。这不仅仅是一个简单的“连线”项目。它的核心挑战在于如何让一个8位的微控制器去理解和控制那些专为模拟或专用芯片设计的射频前端。答案就是相位锁定环PLL。PLL是现代无线通信的基石它就像一个极其聪明的“频率锁”能够使一个可变的本地振荡器LO紧紧“跟随”一个非常稳定的参考频率。通过微控制器这里用了Arduino Nano和Seeeduino XIAO经由I2C总线向PLL芯片发送指令我们就能精确地设定接收机要“倾听”的频率从而实现频道调谐。整个系统的“大脑”是Arduino它负责与PLL通信、处理红外遥控指令、管理频道列表。“眼睛”则是两块从老旧设备上拆下的真空荧光显示屏VFD它们负责显示频率、频道等信息那种泛着绿光的复古味道是液晶屏无法替代的。“耳朵”是那个模拟电视高频头和数字电视调谐器模块。“喉咙”则是一台老索尼卡座改造的音频放大器。本文将详细拆解如何将这些看似不相关的部件通过硬件连接和软件编程整合成一个功能完整、可玩性极高的射频接收平台。无论你是对射频技术感兴趣的硬件爱好者还是喜欢用Arduino“折腾”旧硬件的创客都能从中获得从理论到实践的全流程参考。2. 核心思路与系统架构设计2.1 为什么选择PLL作为调谐核心在射频接收领域调谐的本质就是“选择”。从空中无数混杂的电磁波中精准地选出我们想要的那个频率点。早期收音机采用可变电容或变容二极管进行模拟调谐精度和稳定性都较差。而现代接收设备几乎清一色使用基于PLL的频率合成器。PLL的工作原理可以类比为一个智能化的“速度跟随系统”。假设你的目标是让一辆车VCO压控振荡器输出的速度严格等于一个参考速度参考时钟。你有一个速度表相位检测器不断比较两辆车的速度差并将这个差值转换成油门或刹车的控制信号电荷泵输出经环路滤波后成为VCO控制电压去调整目标车的速度直到两者完全同步。在锁定时VCO的输出频率就是参考频率的精确整数倍N倍这个倍数N正是由微控制器通过数据总线设定的。因此我们只需通过Arduino改变N值就能以极高的频率分辨率和稳定性将VCO锁定在任何想要的频率上从而为混频器提供精准的本振信号完成频道选择。对于本项目数字电视调谐器模块和模拟电视高频头内部都集成了PLL芯片。我们的任务不是从头设计PLL电路而是“逆向工程”其控制协议用Arduino模拟原主板上的微控制器通过I2C总线向这些PLL芯片发送正确的数据命令它们锁定到特定频率。2.2 整体系统架构与信号流整个项目的信号流和控制流可以清晰地分为几条主线射频信号通路天线接收空中的射频信号。对于弱信号如遥远的FM电台我额外加装了一个宽带放大器天线。调谐器前端信号分别进入数字DVB-T调谐器和模拟PAL/NTSC高频头。它们内部的低噪声放大器LNA对信号进行初步放大。频率变换两个调谐器内部的混频器在PLL生成的本振信号作用下将接收的高频射频信号下变频至固定的中频IF。数字调谐器通常输出零中频或低中频的I/Q数字信号而模拟高频头输出的是38MHz或类似频率的模拟中频信号。解调与输出数字调谐器模块通常通过并行或串行接口如TS流输出解调后的数字音视频数据本项目主要利用其音频部分。模拟高频头输出的中频信号需要进一步解调我利用其内部或外部的鉴频器解调出FM广播的音频信号。音频切换与放大使用一颗从旧电视上拆下的模拟音频多路复用器芯片如CD4052在Arduino控制下选择数字电视音频或模拟FM音频。选中的音频信号送入老索尼卡座的自带功放电路进行放大驱动扬声器。控制与显示系统主控Arduino Nano负责核心业务逻辑。它读取红外遥控器的指令根据指令计算对应的频率和PLL分频比N通过I2C总线控制两个调谐器。同时它通过另一个I2C通道将需要显示的信息如频率、频道号发送给显示控制器。显示控制器Seeeduino XIAO专司VFD驱动。它通过I2C从主控接收显示数据然后通过高速GPIO模拟时序控制多片SN75518 VFD驱动移位寄存器动态扫描点亮两块VFD屏的所有段码和网格。人机交互一个旧电视遥控器被重新利用其红外编码被Arduino接收和解码用于实现频道切换、音量调节、信号源选择等功能。注意安全第一。本项目涉及从旧设备拆解高压部件如VFD的灯丝和阳极电压、CRT电视高频头。在操作前务必确保设备已完全断电并放电。特别是为VFD供电的32V电源接线时需格外小心避免短路。建议在通电调试时使用电流限流电源。3. 硬件拆解、选型与接口逆向工程3.1 关键部件来源与特性分析项目的硬件核心是几个淘来的旧货它们的选型直接决定了系统的能力和复杂度。数字电视调谐器Goodwill商店$6这是一个完整的DVB-T接收模块通常包含硅调谐器如Rafael Micro R820T和解调器芯片。其优势是集成度高通常通过I2C控制并直接输出数字音频流方便处理。难点在于找到其数据手册以了解其I2C地址、寄存器映射和控制命令序列。模拟电视高频头废旧CRT电视这是一个典型的“罐头”式高频头内部包含VHF/UHF波段切换、PLL频率合成器常见芯片如TDA5736, LA7530等和混频器。其输出是模拟中频信号。控制接口通常是I2C总线或三线总线时钟、数据、使能。需要根据型号查找资料确定其控制协议。索尼915MHz发射器音响系统$7这是一个有趣的部件。它工作在915MHz ISM频段本意是无线音频传输。在本项目中我尝试将其作为接收前端去接收该频段附近的信号如一些民用对讲设备。这需要对它的接收模式如果有或电路进行改造极具实验性。VFD显示屏旧设备拆机显示屏A14位复合显示。第一排是5x7点阵可用于显示字符或简单图形第二排混合了图标、2位7段码和9位14段码非常适合显示频率数字如“108.5 MHz”和状态图标如FM立体声标志。显示屏B13段9位数字加图标屏更专注于数字显示。 它们的驱动逻辑复杂需要动态扫描且需要较高的驱动电压通常段压为12-50V灯丝交流或直流3-5V。这就是为什么需要专用的SN75518驱动芯片和独立的32V电源。SN75518 VFD驱动芯片这是本项目的显示驱动核心。每片SN75518是一个32位移位寄存器带锁存和高压输出驱动。通过级联可以控制海量的段和网格。编程的关键在于精确的时序控制以实现稳定无闪烁的扫描。3.2 PLL控制接口的逆向与连接这是项目的第一个技术难关。通常没有原设备的原理图我们需要通过观察原电路板、测量和查阅芯片资料来破解。物理接口识别在调谐器模块或高频头上找到一组连接主板的排针或焊点。通常会有VCC、GND、SCL时钟、SDA数据四根线这就是I2C接口。有时还会有一条“使能”或“地址选择”线。逻辑分析仪抓包这是最有效的方法。将逻辑分析仪的通道连接到疑似I2C的线上给原设备上电并操作如用原遥控器换台捕获总线上的数据流。通过分析数据包可以确定I2C地址、写入寄存器的数据以及这些数据与显示频率之间的关系。例如你可能会发现每次换台都会向地址0xC0写入一组数据其中两个字节与频道频率呈线性关系。计算分频比N根据捕获的数据和已知的参考频率通常为4MHz或更精确的晶体可以反推出PLL的分频比N的计算公式。公式通常为频率 (N * 参考频率) / R其中R是参考分频比通常是固定的。Arduino的程序就需要根据目标频率实时计算出对应的N值并组装成符合芯片格式的数据帧发送出去。Arduino连接将Arduino Nano的A4SDA、A5SCL引脚通过上拉电阻通常4.7kΩ连接到调谐器的I2C总线。务必共地。如果调谐器需要3.3V电平而Arduino是5V则需要使用电平转换器。3.3 VFD驱动电路设计与布线心得驱动VFD是另一个挑战涉及高压和复杂的多路复用扫描。电源分离VFD需要三组电源灯丝电压AC 3.5V、栅极/阳极驱动高压DC 32V、逻辑电源DC 5V。我使用了一个旧的打印机电源提供32V高压一个单独的变压器提供灯丝交流电压Arduino的5V为SN75518的逻辑部分供电。务必确保这些电源的地线在一点共地否则会导致显示混乱或驱动芯片损坏。SN75518级联策略对于显示屏A段码和网格数量众多。我采用了两片SN75518一片专门驱动所有段码包括点阵、7段、14段的所有段另一片专门驱动所有网格点阵的行、各位数字的网格。这种“段-栅分离”的驱动方式简化了扫描逻辑。对于显示屏B由于段和栅数量较少我用一片SN75518同时驱动段和栅通过分时复用数据来实现。布线注意事项高压走线32V走线要尽量粗短远离逻辑信号线避免噪声耦合。灯丝连接灯丝通常有两根引脚直接接入交流电压即可。有时为了显示均匀会在灯丝两端对地接一个偏置电阻。限流电阻在每个段码的输出引脚上建议串联一个限流电阻如2kΩ以保护VFD和驱动芯片防止过流。驱动电流SN75518的高压输出驱动能力有限通常几十mA。在设计扫描逻辑时必须确保同一时刻点亮的段码总电流不超过芯片极限。这需要通过软件限制同时点亮的段数即降低占空比来实现。4. 软件框架与核心驱动实现4.1 开发环境与项目配置我选择了PlatformIO Visual Studio Code作为开发环境而非传统的Arduino IDE。PlatformIO提供了更专业的库管理、构建系统和调试体验特别适合这种多文件、多板卡的项目。platformio.ini配置示例[env:seeed_xiao] platform atmelsam board seeed_xiao framework arduino monitor_speed 115200 [env:nanoatmega328] platform atmelavr board nanoatmega328 framework arduino monitor_speed 115200这个配置文件定义了两个环境一个用于Seeeduino XIAO显示控制器一个用于Arduino Nano主控制器。可以方便地分别编译和烧录。4.2 主控制器Arduino Nano软件设计主程序的逻辑围绕状态机展开核心文件是main.cpp。红外遥控解码#include IRremote.h IRrecv irrecv(RECV_PIN); decode_results results; void setup() { irrecv.enableIRIn(); } void loop() { if (irrecv.decode(results)) { uint32_t command results.value; switch(command) { case 0xFFA25D: // CH 按钮 currentChannel; tuneToChannel(currentChannel); updateDisplayFrequency(); break; // ... 处理其他按钮 } irrecv.resume(); } }使用IRremote库将旧遥控器的每个按键编码映射到具体的功能换台、音量、切换TV/FM。PLL控制函数 这是最核心的函数。需要为每个调谐器编写独立的控制函数。void tuneSi4703(uint16_t frequencyKHz) { // 1. 计算分频比N (以10kHz为步进参考频率为32.768kHz为例) uint16_t N (frequencyKHz * 100) / 32768; // 假设PLL结构 // 2. 组装I2C数据帧 (根据芯片手册) uint8_t data[4]; data[0] 0x20; // I2C地址 写命令 data[1] (N 8) 0x3F; // N的高位保留控制位 data[2] N 0xFF; // N的低位 data[3] 0x10; // 其他控制位如开启振荡器 // 3. 通过I2C发送 Wire.beginTransmission(SI4703_ADDR); Wire.write(data, 4); Wire.endTransmission(); delay(50); // 等待PLL锁定 }关键点每个芯片的数据格式、字节顺序、控制位含义都不同必须严格参照数据手册或逆向工程的结果。delay(50)是必要的给PLL电路足够的时间锁定到新频率。频道管理与音频切换 在EEPROM或数组中存储一个频道列表包含频率、信号源TV/FM、名称等信息。tuneToChannel函数根据频道号索引这个列表调用对应的PLL控制函数并控制模拟多路复用器芯片如CD4052选择正确的音频源。void selectAudioSource(bool isFM) { digitalWrite(MUX_SEL_A, isFM ? HIGH : LOW); digitalWrite(MUX_SEL_B, isFM ? LOW : HIGH); // 具体逻辑取决于CD4052真值表 }4.3 显示控制器Seeeduino XIAO与VFD驱动显示控制器被设计为一个I2C从设备它等待主控发送显示数据然后负责繁重的扫描刷新工作。我将显示逻辑封装成了几个库文件如Display.h,DisplayData.h。数据结构设计(DisplayData.h)struct DisplayFrame { uint8_t vfdId; // 标识是哪块屏 uint8_t digitPos[14]; // 每个位置显示的字符编码 bool icons[8]; // 图标开关状态 uint32_t segmentMap; // 对于点阵屏可能需要位图 };主控通过I2C发送这个结构体的数据。SN75518驱动底层函数void shiftOutSN75518(uint32_t segmentData, uint32_t gridData) { // 确保时钟初始为低 digitalWrite(CLK_PIN, LOW); // 先移入段数据32位 for (int i 31; i 0; i--) { digitalWrite(DATA_PIN, (segmentData i) 0x01); digitalWrite(CLK_PIN, HIGH); delayMicroseconds(1); // 关键SN75518需要一定的建立时间 digitalWrite(CLK_PIN, LOW); } // 再移入栅数据如果使用独立芯片 for (int i 31; i 0; i--) { digitalWrite(DATA_PIN, (gridData i) 0x01); digitalWrite(CLK_PIN, HIGH); delayMicroseconds(1); digitalWrite(CLK_PIN, LOW); } // 锁存信号将移位寄存器的数据输出到驱动级 digitalWrite(LATCH_PIN, HIGH); delayMicroseconds(1); digitalWrite(LATCH_PIN, LOW); }delayMicroseconds(1)是调试出来的关键延时太快会导致数据采样错误显示乱码。动态扫描引擎 VFD采用多路复用驱动以节省引脚。例如14位数字屏每次只点亮一位数字对应的栅极为高电平并点亮该数字上需要亮起的段。然后快速切换到下一位利用人眼视觉暂留形成稳定显示。void refreshDisplay() { for (int grid 0; grid TOTAL_GRIDS; grid) { uint32_t gridPattern 1UL grid; // 只有当前栅极为高 uint32_t segmentPattern getSegmentPatternForGrid(grid); // 获取该位应显示的段码 shiftOutSN75518(segmentPattern, gridPattern); delayMicroseconds(SCAN_DELAY); // 扫描延时影响亮度 // 在切换到下一位前先关闭所有段防止“鬼影” shiftOutSN75518(0, 0); } }SCAN_DELAY需要调整太短亮度低太长会闪烁。通常控制在1-3ms之间。关闭所有段再切换网格是消除“鬼影”上一个数字的残影的关键技巧。5. 系统集成、调试与问题排查实录5.1 分模块调试流程不要试图一次性连接所有部件。务必分步进行Arduino与PLL调谐器先单独连接一个调谐器如模拟高频头。编写一个简单的测试程序循环发送几个已知的频率值如FM 98.1MHz。用一台收音机或频谱仪靠近调谐器本振泄露点确认频率是否变化。这是验证I2C通信和控制逻辑是否正确的基础。音频通路暂时抛开调谐器用函数信号发生器或手机音频线直接向音频多路复用器和功放输入信号测试音频切换和放大功能是否正常。VFD显示单独测试显示控制器。编写一个静态显示测试程序如让所有段全亮检查硬件连接和电源。然后测试动态扫描观察是否有数字缺划、亮度不均或鬼影。红外遥控单独测试红外接收在串口监视器中打印解码出的按键码建立按键码与功能的映射表。逐步集成将调试好的PLL控制、音频切换集成到主控。然后加入红外控制。最后将主控与显示控制器通过I2C连接测试完整的“按键-换台-显示”流程。5.2 典型问题与解决方案速查表在集成过程中我遇到了许多问题以下是其中一些典型问题及其解决方法问题现象可能原因排查步骤与解决方案PLL不锁定收不到信号1. I2C地址错误。2. 数据格式或字节顺序错误。3. 参考频率不匹配。4. 环路滤波器元件问题对拆机高频头。1. 用逻辑分析仪确认I2C通信是否发生地址是否正确。2. 仔细核对芯片数据手册或逆向工程数据确认控制字每一位的含义。3. 测量调谐器上的晶振频率确保计算N值时使用的参考频率正确。4. 检查高频头上PLL芯片周围的电容电阻特别是环路滤波器的电容老化或损坏会导致无法锁定。VFD显示暗淡或有鬼影1. 扫描延时(SCAN_DELAY)设置不当。2. 段码关闭不彻底。3. 驱动电压不足。4. 灯丝电压偏低。1. 调整SCAN_DELAY找到亮度与稳定性的平衡点。2. 确保在切换网格前有语句将段码数据清零 (shiftOutSN75518(0, ...))。3. 测量驱动芯片输出脚电压是否接近32V。检查高压电源的负载能力。4. 测量灯丝电压交流应在3.0-3.5VAC左右。显示乱码或部分段常亮1. SN75518移位时序错误。2. 级联顺序错误。3. 硬件连接有虚焊或短路。4. 电源噪声干扰。1.最关键检查shiftOutSN75518函数中的时钟和数据时序特别是delayMicroseconds(1)是否必要且足够。2. 确认段和栅的数据送入顺序与硬件级联顺序匹配。3. 用万用表蜂鸣档仔细检查所有连接。4. 在VFD逻辑电源5V和高压电源32V入口处并联一个10-100uF的电解电容和一个0.1uF的瓷片电容进行滤波。红外遥控不响应或误触发1. 红外接收头型号不对38kHz载波。2. 接收头电源不稳。3. 环境光干扰如日光灯。4. 解码库配置错误。1. 确认接收头是VS1838B等常见38kHz型号。2. 在接收头VCC和GND之间加一个10uF电容。3. 用深色热缩管或胶带包裹接收头避免直射光。4. 检查IRrecv初始化时指定的引脚是否正确尝试使用不同的解码协议。音频噪声大嘶嘶声或嗡嗡声1. 地线环路。2. 电源噪声耦合到音频线。3. 调谐器解调不良或信号弱。1.最重要确保所有设备Arduino、调谐器、功放的“地”在一点连接形成星型接地。2. 使用屏蔽音频线屏蔽层单端接地通常在功放端。3. 检查天线连接尝试调整天线位置。对于模拟高频头微调其中周变压器如果有可能改善解调效果。5.3 关于“收听卡车司机通话”的说明在项目描述中我提到通过模拟高频头和放大器天线收听到了附近高速公路卡车司机的通话。这涉及到民用对讲机频段如CB Radio 27MHz或商用对讲频段如VHF 150-170MHz。模拟电视高频头通常覆盖VHF低波段48-92MHz和高波段175-230MHz部分覆盖UHF470-860MHz。卡车司机常用的频段可能落在VHF高波段内。重要提示收听这些信号仅出于技术学习和实验目的。你必须了解并严格遵守所在国家/地区关于无线电监听的法律法规。绝对禁止干扰任何正常通信也严禁将设备用于非法目的。本项目所有内容仅限于技术探讨和合法范围内的业余无线电实验。6. 项目总结与扩展思考经过数周的调试和改进这个由旧货拼凑而成的接收机终于稳定工作。数字电视能清晰解码出电台FM广播的音质也令人满意VFD显示屏泛出的柔和绿光赋予了它独特的复古科技美感。最重要的是通过亲手实现从I2C指令到射频调谐再到动态显示的全过程对PLL原理、射频前端和嵌入式系统协同工作的理解变得无比真切。回顾整个过程有几点心得尤为深刻首先逆向工程需要耐心和工具。没有逻辑分析仪破解PLL的I2C协议几乎寸步难行。在动手写代码前花时间用仪器观察和理解原始信号流能节省大量盲目试错的时间。其次电源和地线是模拟-数字混合系统的生命线。最初的版本音频噪声很大显示也不稳定最终都是通过优化电源布局、加强滤波和重构单点接地来解决的。在面包板或洞洞板上搭建复杂系统时要有意识地将数字部分和模拟/高压部分在物理上和电源上隔离开。最后模块化编程至关重要。将显示驱动、PLL控制、红外解码分别封装成独立的库或头文件使得代码结构清晰调试时能快速定位问题。PlatformIO的环境管理功能也让同时管理主控和显示控制器两个固件变得轻松。这个项目还有很大的扩展空间。例如可以加入一个软件定义的无线电SDR前端如RTL-SDR用电脑进行更复杂的信号分析和解码可以为VFD增加频谱瀑布图显示甚至可以尝试用ESP32替换Arduino Nano增加网络流媒体推送功能。它不仅仅是一个接收机更是一个开放的射频实验平台。每一次对频率的探索都像是在电磁波的海洋中进行一次小小的航行而手中的Arduino和这些老旧的硬件就是你的罗盘与帆船。