
1. 项目背景与硬件选型解析这个项目本质上是一个基于Si4731收音机芯片和MK20DX128VFM5微控制器的DIY收音机开发方案。作为一名电子爱好者我最初是被Si4731这颗芯片的全频段接收能力所吸引——它能覆盖从150kHz到108MHz的调幅/调频广播频段甚至支持短波接收。而选择MK20DX128VFM5这款ARM Cortex-M4内核的MCU则是因为它具备足够的处理能力来驱动Si4731同时价格亲民且开发资源丰富。Si4731是Silicon Labs推出的一款数字收音机芯片采用I2C接口控制内部集成了从射频接收到音频输出的完整信号链。相比传统模拟收音机方案它的优势在于支持全球所有广播频段FM/AM/LW/SW数字信号处理带来更好的抗干扰能力自动搜台和存储功能单芯片解决方案减少外围电路MK20DX128VFM5则是NXP Kinetis K20系列中的一款MCU主要特性包括72MHz主频的Cortex-M4内核128KB Flash 16KB RAM丰富的外设接口I2C/SPI/UART等3.3V工作电压与Si4731完美匹配2. 硬件电路设计与搭建2.1 核心电路连接Si4731与MK20DX128VFM5的连接非常简单主要依靠I2C总线Si4731 MK20DX128VFM5 SCL → PTB0(I2C0_SCL) SDA → PTB1(I2C0_SDA) RST → PTA4(GPIO)音频输出部分Si4731的LINE_OUT引脚需要通过一个10uF耦合电容连接到音频功放芯片如PAM8403。如果只是调试也可以直接接耳机需串联100Ω电阻保护听力。2.2 电源设计要点Si4731需要3.3V供电典型工作电流约25mAMK20DX128VFM5也工作在3.3V推荐使用AMS1117-3.3稳压芯片输入5V可从USB取电在每颗芯片的电源引脚附近放置0.1uF去耦电容2.3 天线设计技巧FM接收效果很大程度上取决于天线最简单的方案使用20cm左右的导线作为天线优化方案制作1/4波长FM天线约75cm铜线专业方案加装FM专用有源天线如TEA5767模块配套天线3. 软件开发环境搭建3.1 工具链准备推荐使用以下开发工具IDE: Arduino IDE需安装Teensyduino插件编译器: ARM-GCC调试器: J-Link或板载OpenSDA安装步骤下载并安装Arduino IDE添加Teensyduino支持包含MK20DX128VFM5的工具链在IDE中选择板卡类型Teensy 3.2与MK20DX128VFM5兼容3.2 关键库文件需要以下两个核心库Si4731 Arduino Library控制收音机芯片Wire LibraryI2C通信库安装方法通过Arduino Library Manager搜索安装或手动下载后放入libraries文件夹4. 核心功能代码实现4.1 初始化设置#include Wire.h #include SI4731.h SI4731 radio; void setup() { Serial.begin(9600); Wire.begin(); if (!radio.begin()) { Serial.println(Si4731初始化失败!); while(1); } radio.setVolume(10); // 设置音量(0-15) radio.setFM(); // 设置为FM模式 radio.setFrequency(1017); // 设置初始频率101.7MHz }4.2 自动搜台功能实现void scanStations() { uint16_t freq radio.getMinFrequencyFM(); // 获取最低频率 while(freq radio.getMaxFrequencyFM()) { radio.setFrequency(freq); if(radio.getSNR() 15) { // 信噪比大于15视为有效电台 Serial.print(找到电台: ); Serial.print(freq/10.0); Serial.println(MHz); delay(2000); // 停留2秒试听 } freq 10; // 以100kHz为步进 } }4.3 添加按键控制实际使用时需要物理按键#define BTN_UP 2 #define BTN_DOWN 3 #define BTN_SCAN 4 void setup() { // ...其他初始化代码... pinMode(BTN_UP, INPUT_PULLUP); pinMode(BTN_DOWN, INPUT_PULLUP); pinMode(BTN_SCAN, INPUT_PULLUP); } void loop() { if(digitalRead(BTN_UP) LOW) { radio.frequencyUp(); delay(200); // 防抖 } if(digitalRead(BTN_DOWN) LOW) { radio.frequencyDown(); delay(200); } if(digitalRead(BTN_SCAN) LOW) { scanStations(); delay(200); } }5. 常见问题与调试技巧5.1 收不到任何电台排查步骤检查天线连接是否可靠用示波器查看I2C信号SCL/SDA应有400kHz方波测量Si4731的3.3V供电是否稳定尝试不同的初始频率如本地强信号频率5.2 音频有杂音可能原因及解决电源干扰增加电源滤波电容接地不良检查地线走线推荐星型接地天线匹配不佳调整天线长度或加装匹配电路5.3 I2C通信失败调试方法使用逻辑分析仪抓取I2C数据检查上拉电阻通常4.7kΩ确认设备地址正确Si4731默认0x116. 项目进阶与扩展6.1 添加LCD显示使用I2C OLED显示当前频率和信号强度#include Adafruit_SSD1306.h Adafruit_SSD1306 display(128, 64, Wire); void updateDisplay() { display.clearDisplay(); display.setTextSize(2); display.setCursor(0,0); display.print(radio.getFrequency()/10.0); display.println(MHz); // 绘制信号强度条 int rssi radio.getRSSI(); display.fillRect(0, 30, map(rssi, 0, 127, 0, 128), 10, WHITE); display.display(); }6.2 实现电台存储利用MK20的内部EEPROM存储预设电台#include EEPROM.h #define PRESET_NUM 5 uint16_t presets[PRESET_NUM]; void savePreset(int index) { EEPROM.put(index*sizeof(uint16_t), radio.getFrequency()); } void loadPreset(int index) { uint16_t freq; EEPROM.get(index*sizeof(uint16_t), freq); radio.setFrequency(freq); }6.3 添加蓝牙控制通过HC-05模块实现手机控制#include SoftwareSerial.h SoftwareSerial bt(8, 9); // RX,TX void handleBluetooth() { if(bt.available()) { char cmd bt.read(); switch(cmd) { case U: radio.frequencyUp(); break; case D: radio.frequencyDown(); break; case S: scanStations(); break; } } }7. 实际制作建议PCB设计要点将射频部分与其他电路隔离保持天线走线短而直在Si4731附近放置完整的接地平面外壳选择避免使用金属外壳影响信号接收预留足够的散热空间考虑旋钮和按键的布局人体工学功耗优化在待机时降低MCU时钟频率添加电源开关控制Si4731供电考虑锂电池供电方案这个项目最让我惊喜的是Si4731出色的接收性能——在我实测中用简单导线天线就能清晰接收30公里外的电台。而MK20DX128VFM5的处理能力也完全够用甚至还有余力添加各种扩展功能。如果你也想重温模拟收音机的乐趣或者想学习嵌入式开发中的硬件控制技巧这个方案会是个很好的起点。