这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » STM32H7S78-DK网络收音机

共2条 1/1 1 跳转至页

STM32H7S78-DK网络收音机

高工
2026-11-11 21:21:36     打赏
STM32H7S78-DK 网络收音机:以太网 + MP3 解码 + I2S 音频 + LVGL

本文记录在 STM32H7S78-DK 上实现完整网络收音机的过程:以太网 DHCP 联网 → HTTP 拉取 MP3 直播流 → minimp3 软解码 → I2S6 输出到 WM8904 codec 出声,800×480 LVGL 界面(电台列表/播放控制/音量/实时频谱/网络状态栏)。

1. 架构

电台服务器 ──HTTP/TCP──► net_stream(接收线程,24KB pipe)
                              │
                              ▼
                    net_radio(解码线程): minimp3 组帧解码
                     + 线性插值重采样到 48117Hz + Goertzel 频谱
                              │ (pcm_q, 阻塞反压)
                              ▼
                    audio_sai(发送线程): 音量缩放/静音填补
                              │
                    GPDMA1 循环链表(双半区, 永不停止)
                              │
                    I2S6(主机模式, MCK 供给 codec FLL)
                              │
                    WM8904 codec → 耳机口

复用自 EK-RA6M5 收音机工程:net_stream.c(socket 流)、net_radio.c(解码+重采样+频谱)、minimp3.h 原样可用;音频后端 audio_sai.c 和界面 main.c 为新写。

2. 关键实现

自研音频输出驱动(绕开 Zephyr i2s 驱动的逐块 DMA 重载模型——在 GPDMA 上会周期性掉链):

/* GPDMA 循环链表模式: DMA 永不停止,半完成/全完成中断回填对应半区 */
static void dma_tx_callback(const struct device *dev, void *user_data,
                uint32_t channel, int status)
{
    if (status == DMA_STATUS_BLOCK) {
        k_event_post(&refill_evt, 0x1); /* 前半播完 */
    } else if (status == DMA_STATUS_COMPLETE) {
        k_event_post(&refill_evt, 0x2); /* 后半播完(回卷) */
    }
}

blk_cfg.source_reload_en = 1;   /* dma_stm32u5 用链表模拟循环模式的关键 */
blk_cfg.dest_reload_en = 1;

反压流控:解码线程投递用阻塞写,速率自动对齐播放速率;网络抖动由 24KB pipe 吸收:

/* 队列满就阻塞等——丢弃会造成音频空洞(杂音),这是实测教训 */
k_msgq_put(&pcm_q, &cur_blk, K_FOREVER);

codec 先于 I2S 配置:实测 I2S 时钟跑起来后 i2c1 上 WM8904 事务会 NACK(I2S 引脚与 I2C1 相邻引脚疑似串扰),所以寄存器写在 I2S 启动前的安静期完成。

3. 踩坑记录

坑现象解法
i2s_buf_write API 误用发送线程 100% 空转(300 万次/秒),日志线程饿死、控制台假死该 API 内部自己从 slab 取块拷贝,调用方不要再分配
START 前队列必须非空首启 queue_get FAILED触发前垫 4 块静音
垫块后等了 50ms 才放馈数线程垫片播完欠载,驱动进入 ERROR 态触发 START 后立刻放开馈数线程
解码无反压解码比播放快 1/3,PCM 被静默丢弃,声音"不成形"投递改阻塞(K_FOREVER)
Zephyr i2s 驱动 + GPDMA播几秒后 TC 中断丢失,队列满但 DMA 停摆弃用,自研循环 DMA 驱动
k_event 没初始化MPU FAULT,空指针用 K_EVENT_DEFINE 静态定义
主线程优先级过高800×480 软件渲染饿死解码线程主线程降到 prio 10,音频链路 5/6
采样率失配约每 8 秒一次缓冲抽空实测驱动分频:271MHz/22/256=48117Hz,重采样目标对齐它

4. 实测数据

播放稳定后的健康指标(每 10 秒打印):

stats: pcm_q=4 silence=615 drop=0 pipe_empty=0

pcm_q=4(反压生效)、drop=0(无丢弃)、pipe_empty=0(网络无断粮)、silence 不增长(无欠载)。

5. 电台表与验证方法

蜻蜓 FM 免费流(64k)国内稳定,添加新台前先验证可达性:

curl -s -m 5 -o /dev/null -w "%{http_code} %{content_type}\n" \
  -r 0-1023 "http://lhttp.qingting.fm/live/<ID>/64k.mp3"

返回 200 audio/mpeg 即可用。蜻蜓免费流没有 128k 档,高码率需换源。

6. 硬件与构建

  • 板载 WM8904 codec(I2C 地址 0x1a),I2S6 引脚 MCK=PA3/WS=PA4/CK=PA5/SDO=PB5

  • 注意板级 dts 里 timers2/pwm2 默认占用 PA3,与 I2S6 MCK 冲突,overlay 里已禁用

  • 必须有 sram1 NOCACHE overlay(第五篇的以太网修复),否则网络必挂

west build -b stm32h7s78_dk/stm32h7s7xx/ext_flash_app --sysbuild -s app\net_radio -d app\net_radio\build -p
west flash -d app\net_radio\build

7. 效果

b03de098694871c092395a928bdd3cbd.jpg





关键词: STM32H7S78-DK     网络     收音机    

专家
2026-11-12 08:19:28     打赏
2楼

谢谢分享


共2条 1/1 1 跳转至页

回复

匿名不能发帖!请先 [ 登陆 注册 ]