你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

用 NUCLEO-H5E5ZJ 打造一台网络收音机(Zephyr 4.4 全网首发移植)

[复制链接]
作者:lugl 2026-10-17 19:30:57 0 16

项目名称

用 NUCLEO-H5E5ZJ 打造一台网络收音机

项目主题

人机界面(GUI) 物联网 

项目简介

一块刚上市的新 Nucleo_H5E5ZJ 板 + 一块 LCD 扩展板 + 一个 10 块钱的 I2S 功放模块 = 一台能听新闻和音乐的 WiFi…不对,**有线网络**收音机!

项目图片

软硬件框图

演示视频

项目代码仓库

https://gitee.com/lugl/nucleo-h5e5zj-zephyr/tree/master/apps/net_radio
用 NUCLEO-H5E5ZJ 打造一台网络收音机(Zephyr 4.4 全网首发移植 + 踩坑全记录)
一块刚上市的新 Nucleo 板 + 一块 LCD 扩展板 + 一个 10 块钱的 I2S 功放模块 = 一台能听新闻和音乐的 WiFi…不对,有线网络收音机!


一、前言:为什么做这个项目
NUCLEO-H5E5ZJ 是 ST 新出的 Nucleo-144 板子,搭载 STM32H5E5ZJ(Cortex-M33 @250MHz、4MB Flash、1.5MB SRAM、板载以太网)。拿到手第一件事当然是跑 Zephyr——结果发现 Zephyr 官方还没有这块板子的支持(SoC 支持刚进 4.4,板级没人做)。
那就自己移植呗。既然板子有以太网、手里又有 LCD 扩展板和 MAX98357A 功放模块,干脆做个网络收音机:插网线、摇杆选台、喇叭出声,一次把 GPIO/UART/以太网/SPI/I2S/ADC/LVGL/TLS 全部点亮。
先上效果(音频解码 CPU 占用 19%,播放流畅):
网络收音机.jpg
二、系统架构设计
整体设计原则:网络缓冲与音频缓冲分离、生产者永远快于消费者、丢比堵好(流媒体的血泪经验,后面调试篇细说)。
net_radio_arch.png
数据通路:
互联网电台 ──HTTP/TLS──► 以太网(RMII) ──► net_stream 接收线程 ──► mp3_pipe(24KB 抖动缓冲)
      ──► minimp3 软解 + 重采样(48.225kHz) ──► PCM 播放队列(8 块≈190ms)
      ──► audio_i2s(音量/静音兜底) ──► I2S3+GPDMA ──► MAX98357A ──► 喇叭
控制通路:五向摇杆 ──► ADC1 ──► adc-keys ──► LVGL keypad ──► 选台 UI ──► 播放控制。
线程模型(4 线程各司其职):
线程职责优先级
net_rxsocket 接收灌管道抢占 6
net_radioMP3 解码 + 重采样抢占 6
audio_i2sI2S 投喂 + 静音兜底协作 -2(原因见调试篇)
mainLVGL UI抢占 0三、硬件连接模块信号接到哪说明
MAX98357ABCKCN7 pin1(PC10,I2S3_SCK)I2S 位时钟
DINCN7 pin3(PC12,I2S3_SDO)I2S 数据
LRCKCN7 pin17(PA15,I2S3_WS)I2S 帧时钟
Vin / GND3V3~5V / GNDCN7 上有 3V3(pin16)/5V(pin18)/GND
SD3V3关断脚,接高使能
喇叭OUT+/OUT−4~8Ω,BTL 差分,两端都不能接地!
LCD 扩展板整板Arduino 排针(CN5/6/8/9)SPI4=PE12/13/14,CS=PE11(D10),DC=PA9(D8),摇杆=A3(PB0)
网线RJ45CN14板载 LAN8742A,路由器需能上网
USB-CCN1电脑供电 + 调试 + ST-LINK VCP 串口(115200)
原理图依据(MB2129 第 5 页连接器部分,I2S3 的三个脚在 CN7 上都标着):
mb2129_cn7_i2s.png
四、项目创建
Zephyr 4.4 + 板外板(BOARD_ROOT)方式,不动 Zephyr 官方树:
NUCLEO_H5E5ZJ/
├── boards/st/nucleo_h5e5zj/        # 自移植的板级支持包(本次的主角之一)
│   ├── nucleo_h5e5zj.dts           # LED/按键/USART3/以太网/时钟/分区
│   ├── board.yml / Kconfig.* / *_defconfig / board.cmake
│   └── nucleo_h5e5zj.yaml
└── apps/net_radio/                 # 网络收音机应用
    ├── boards/nucleo_h5e5zj.overlay  # LCD/摇杆/I2S3 的板级接线
    ├── dts/bindings/display/         # 自定义显示绑定
    └── src/
        ├── main.c          # LVGL 选台 UI
        ├── net_stream.c    # HTTP/TLS 拉流层(socket 接收线程 → mp3_pipe)
        ├── net_radio.c     # minimp3 解码 + 重采样 + 电台表
        ├── audio_i2s.c     # I2S 输出层(播放队列/音量/静音兜底)
        ├── lcd_bare.c      # ST7735 裸 SPI 驱动
        ├── display_bare.c  # Zephyr display API shim(LVGL 显示后端)
        └── minimp3.h       # 纯 C MP3 解码器
构建烧录一条龙:
cd /d/luglZephyrproject
export ZEPHYR_SDK_INSTALL_DIR=/d/luglZephyrproject/zephyr-sdk-1.0.1/zephyr-sdk-1.0.1
west build -b nucleo_h5e5zj apps/net_radio -d build_h5e5_radio -p always \
  -- -DBOARD_ROOT=D:/STM32/STM32H5E5/NUCLEO_H5E5ZJ
west flash -d build_h5e5_radio五、Zephyr 关键实现5.1 板级移植(从 0 到有)
Zephyr 4.4 只有 STM32H5E5 的 SoC 级支持,板级文件自己写。几个要点:
  • 时钟:板载 48MHz 晶振(X3)经 0Ω 电阻接 PH0/PH1 → PLL(÷12×125÷2) → 250MHz 满速;
  • 控制台:USART3(PD8/PD9)接 ST-LINK VCP,115200 8N1;
  • 以太网:LAN8742A(RMII),PHY 自带 25MHz 晶振供 50MHz REF_CLK,PHY 地址 0;Kconfig.defconfig 里 configdefault NET_L2_ETHERNET = y(这里有个版本坑,见调试篇);
  • FPU:CONFIG_FPU=y + FPU_SHARING=y(这板子最重要的两行,见调试篇)。

5.2 I2S 音频输出(MAX98357A)
H5E5 没有 SAI,I2S 由 SPI3 复用(I2S3)。Zephyr 的 i2s_stm32 驱动 + GPDMA 直推:
/* H5 的 pinctrl 没有单独的 i2s*_sd 节点——数据脚与 SPI_MOSI 同脚同复用,
* 直接用 spi3_mosi_pc12 */
&i2s3 {
    pinctrl-0 = <&i2s3_ck_pc10 &spi3_mosi_pc12 &i2s3_ws_pa15>;
    status = "okay";
};
应用层 8 块播放队列(≈190ms),音频线程协作式优先级保证永不断粮:
/* i2s_stm32 的纪律:先写数据再 START;队列排空即 ERROR,DROP 后才能重来 */
i2s_configure(i2s_dev, I2S_DIR_TX, &cfg);
for (int i = 0; i < 2; i++) i2s_write(i2s_dev, blk, BLOCK_SIZE);
i2s_trigger(i2s_dev, I2S_DIR_TX, I2S_TRIGGER_START);5.3 网络流与 MP3 解码
  • net_stream.c:原生 socket,Icy-MetaData: 0 拿裸 MP3 流,24KB 管道做抖动缓冲(丢比堵好:管道满就丢,阻塞写会让服务器停发);
  • net_radio.c:minimp3 解码,跨帧线性插值重采样到 48225Hz(必须与硬件实际播放速率一致:125MHz÷81÷32=48225.3Hz,差一点缓冲就会被慢慢掏空)。

5.4 HTTPS(能听更多台的关键)
TLS 1.2 socket + mbedTLS,电台表加 tls 标志即可混用 HTTP/HTTPS:
fd = zsock_socket(AF_INET, SOCK_STREAM, IPPROTO_TLS_1_2);
int verify = TLS_PEER_VERIFY_NONE;   /* 公开电台流不校验证书 */
zsock_setsockopt(fd, SOL_TLS, TLS_PEER_VERIFY, &verify, sizeof(verify));
zsock_setsockopt(fd, SOL_TLS, TLS_HOSTNAME, host, strlen(host) + 1);
配套要点:CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y(不开的话 MBEDTLS_SSL_CLI_C 都不编进来)、板级 dts 的 chosen { zephyr,entropy = &rng; }(PSA 加密库的熵源,漏了握手直接报 INVALID_ARGUMENT)、密码套件要开 GCM 的(现在主流服务器都用 GCM)。
5.5 摇杆与 LVGL
五向摇杆是电阻分压式(Arduino A3=PB0=ADC1_IN9),Zephyr 自带 adc-keys 输入驱动直接搞定(阈值 + 消抖全在 dts 里),再经 zephyr,lvgl-keypad-input 映射成 LVGL 按键:
lvgl-codes = <LV_KEY_PREV LV_KEY_NEXT LV_KEY_LEFT LV_KEY_RIGHT LV_KEY_ENTER>;
/* 注意:LVGL 焦点导航用 PREV/NEXT,方向键是发给焦点控件自用的 */六、调试过程(踩坑全记录,都是真金白银)坑 1:UM 文档的"HSE 默认不使用"和实物不符
UM3601 文字说默认焊桥下 HSE 不接,按它配了 HSI——结果串口只吐一个乱码字符就死。实物上 R3/R4 明明贴着 0Ω!教训:以实物和原理图为准,文档的"默认配置"可能和出货状态不一致。
坑 2:ST Cube 头文件缺 typedef
stm32h5e5xx.h 里用了 CCB_TypeDef 却没定义它(H5F5 的头文件里是有的)——上游没有任何板子编译过 H5E5,这个 bug 一直没暴露。从 H5F5 头文件抄上那段 typedef 解决。
坑 3:LVGL 焦点导航用 LV_KEY_PREV/NEXT,不是方向键
摇杆方向键事件明明产生了(上=103/下=108…全对),焦点就是不动。翻 LVGL 文档:LV_KEY_UP/DOWN/LEFT/RIGHT 是派发给焦点控件的,组导航只有 PREV/NEXT。改映射,秒好。
坑 4:播放卡顿 + 整机假死 —— FPU 没开!(本次最大BOSS)
症状:开播后声音慢、一顿一顿,然后控制台静默、摇杆失灵,像整机死机。
排查链:加 [stats] 计数器打印 → 打印到一半消失 → pyOCD 挂 ST-LINK 采样 PC → 发现系统其实在正常跑解码,只是控制台死了 → 控制台死因是 printk 走了 logging 线程而该线程卡死(改 LOG_PRINTK=n+LOG_MODE_IMMEDIATE=y 直出)→ 控制台恢复后看到真凶:CPU 100%,解码只有实时的 63%。
根因:Zephyr 的 H5 dtsi 把 CPU 声明为 arm,cortex-m33(没 f 后缀),CONFIG_FPU 又没默认值——上游所有 H5 板子都没开硬件 FPU,浮点全走软件库,minimp3+重采样+频谱直接吃满 CPU。开了 FPU 后 CPU 降到 20%,解码 41.8 帧/s 跑赢实时 38.3 帧/s,丝般顺滑。
坑 5:I2S 欠载中断风暴
i2s_stm32 驱动的 UDR(欠载)中断在欠载期间按帧率(~48kHz)持续触发——中断风暴直接饿死所有线程。打了个小补丁:UDR 触发一次后关闭该中断(START 时会重新使能)。
坑 6:示波器骗了我半天
量 BCK 发现"三个脚都是 48.1kHz"差点怀疑人生——1.5MHz 的位时钟在低采样率设备上混叠成了低频假象。寄存器回读 + 实际发声才是最终判据。
坑 7:LVGL 内存池小了直接 Bus Fault
电台列表从 5 项加到 13 项后,滚动到底就崩(lv_draw_unit_draw_letter 空指针)。LVGL 池 10KB→32KB;顺便把 24KB 网络管道 + 37KB 音频缓冲挪到 SRAM2(H5E5 有 5 块 SRAM 共 1.5MB,别都挤在 SRAM1)。
七、工程效果与展示
最终电台表(4 台精选 + Stop,全部 HTTPS 国内源):
菜单项内容
CNR-1.ZhongGuoZS中国之声(新闻联播 19:00 转播)
BJ.News339北京新闻广播
HJ.Music4804怀集音乐之声
QC.Music4915清晨音乐台
实测串口日志:
*** Booting Zephyr OS build v4.4.0 ***
audio: i2s started 48000Hz 16bit stereo
[00:00:01.652] <inf> phy_mii: PHY (0) Link speed 100 Mb, full duplex
[00:00:05.744] <inf> net_dhcpv4: Received: 192.168.3.15
radio: online, ready
nst: streaming lhttp.qtfm.cn:443/live/15318317/64k.mp3   ← HTTPS 开播!八、总结与展望
一次把新板的 GPIO/UART/ETH/SPI/I2S/ADC/LVGL/TLS 全部打通,最大的收获是三个可以推给上游的修复(H5E5 头文件缺 typedef、H5 全系没开 FPU、I2S 欠载中断风暴)。H5E5 的 4MB Flash + 1.5MB SRAM 在这个项目里只用了 14%/85%——余量还很足。

2个附件

赞 收藏 评论0 发布时间:2026-10-17 19:30

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版