当前位置: 首页 > news >正文

STM32 I2S 输入输出切换功能 - 修改总结

一、问题背景
使用 STM32F4 的 I2S 接口实现音频输入(录音)和输出(播放)切换。原始代码 HAL_I2S_Receive_DMA() 能正常接收数据,但自定义的 I2S_Start_RX() 函数切换到输入模式后数据全为0。

二、修改文件清单 1. MY_I2S.c - I2S 切换逻辑核心实现
修改内容 :

- 添加 extern DMA_HandleTypeDef hdma_spi2_rx; 和 extern DMA_HandleTypeDef hdma_spi2_tx; 声明
- 重写 I2S_Start_RX() 函数:
- 添加 HAL_I2S_DeInit() 防止重复初始化冲突
- 添加 __HAL_LINKDMA() 链接 DMA 句柄
- 添加 HAL_I2S_Receive_DMA() 启动 DMA 接收
- 重写 I2S_Start_TX() 函数:
- 支持参数传入采样率(44/48)和数据格式(16/24bit)
- 添加 PLL 时钟动态配置
- 添加 __HAL_LINKDMA() 链接 DMA 句柄

void I2S_Start_RX(uint16_t *pData, uint16_t Size) { HAL_I2S_DMAStop(&hi2s2); __HAL_I2S_DISABLE(&hi2s2); hi2s2.Instance = SPI2; hi2s2.Init.Mode = I2S_MODE_MASTER_RX; // ... 其他配置 ... HAL_I2S_DeInit(&hi2s2); HAL_I2S_Init(&hi2s2); __HAL_LINKDMA(&hi2s2, hdmarx, hdma_spi2_rx); HAL_I2S_Receive_DMA(&hi2s2, pData, Size); } void I2S_Start_TX(uint8_t hz, uint32_t dataformat) { // 根据采样率配置 PLL if (hz == 48) { plli2sn = 159; plli2sr = 2; } else if (hz == 44) { plli2sn = 158; plli2sr = 2; } // ... I2S 配置 ... __HAL_LINKDMA(&hi2s2, hdmatx, hdma_spi2_tx); }

i2s.c - 添加 TX 的 DMA 配置
修改内容 :

- 添加 DMA_HandleTypeDef hdma_spi2_tx; 定义
- 在 HAL_I2S_MspInit() 中添加 TX DMA 初始化:

hdma_spi2_tx.Instance = DMA1_Stream4; hdma_spi2_tx.Init.Channel = DMA_CHANNEL_0; hdma_spi2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; // ... 其他配置 ... HAL_DMA_Init(&hdma_spi2_tx); __HAL_LINKDMA(i2sHandle, hdmatx, hdma_spi2_tx);

stm32f4xx_it.c - 中断处理函数

extern DMA_HandleTypeDef hdma_spi2_tx; void DMA1_Stream4_IRQHandler(void) { HAL_DMA_IRQHandler(&hdma_spi2_tx); }

添加 void DMA1_Stream4_IRQHandler(void); 声明

添加 DMA1_Stream4_IRQn 的 NVIC 启用:

HAL_NVIC_SetPriority(DMA1_Stream4_IRQn, 0, 0); HAL_NVIC_EnableIRQ(DMA1_Stream4_IRQn);

核心问题与解决方案

I2S_Start_RX() 数据全为0 未链接 DMA 句柄,未启动 DMA 接收 添加 __HAL_LINKDMA() 和 HAL_I2S_Receive_DMA() TX DMA 中断不触发 NVIC 未启用 Stream4 中断 在 dma.c 中添加 HAL_NVIC_EnableIRQ(DMA1_Stream4_IRQn) 播放 24bit WAV 有噪音 I2S 配置 24bit 但数据已转 16bit 统一使用 16bit 模式输出 TX 切换后频率/位深度不对 硬编码参数 添加参数支持动态配置

http://www.jsqmd.com/news/716722/

相关文章:

  • 魔兽争霸III如何在现代电脑上重获新生:WarcraftHelper终极优化指南
  • 为什么92%的AI PoC项目在Docker沙箱中泄露训练数据?:深度解析cgroups v2 + seccomp + no-new-privileges三重失效链及修复checklist
  • C++浮点数“体检”指南:除了std::isfinite,还有哪些标准库函数能帮你诊断NaN和Inf?
  • 别让偏见毁了你的AI产品:从亚马逊招聘工具翻车,到用IBM AIF360和Google What-If Tool给你的模型做个‘公平性体检’
  • 无风扇 AI 服务器成主流:英伟达 NVL72 系统引领静音算力革命
  • 【Linux从入门到精通】第27篇:文本处理三剑客(上)——grep 正则表达式实战
  • 戴尔笔记本风扇管理终极指南:DellFanManagement 完整解决方案详解
  • 告别CGO内存泄漏:手把手教你安全封装LuaJIT给Go调用(Windows/Linux双平台)
  • 分布式量子计算中的光子寿命优化与BDIR算法
  • 【flutter for open harmony】第三方库Flutter 鸿蒙版 贷款计算器 实战指南(适配 1.0.0)✨
  • NVIDIA Profile Inspector终极指南:解锁显卡隐藏性能的5个实用技巧
  • 百度网盘CLI终极指南:从零构建高效命令行文件管理方案
  • 用Logisim从零搭建一个8位CPU的运算器:华科硬件课设实战复盘
  • 别再死记硬背Flink CEP API了!图解‘严格连续’、‘松散连续’到底差在哪?
  • 告别手动抄表!用WinCC用户归档控件打造车间级数据看板与一键打印系统
  • 雷电接口对HTML函数工具有提速作用吗_高速外设方法【方法】
  • 从静态镜像到可执行元神:镜像视界开启数字孪生 3.0 新纪元
  • 轻量化智能体落地 中小厂程序员的转型最优解
  • 慢性变化维度的建模
  • FigmaCN:专业级中文界面优化方案的设计工具适配器
  • 告别选药误区:新型宠物药成分解析,科学用药更安心
  • 【限时公开】微软内部未文档化Copilot Next配置密钥:启用LLM上下文预加载、指令流管道并行化与GPU卸载开关
  • 不完备数据滚动轴承深度故障诊断【附代码】
  • 什么是视图,大白话说清楚
  • 【深度实战】CVE-2026-20122 Cisco vManage 特权 API 滥用与 RCE 全解析
  • 2026AI服装商拍工具推荐:FD+凭什么成为电商首选?
  • 戴尔笔记本风扇终极管理指南:3步掌握DellFanManagement智能散热解决方案
  • 【收藏备用】2026年程序员转型大模型指南!从传统开发到AI应用工程师,踩坑经验全拆解
  • 六个典型热门AI记忆架构对比:Mem0,Letta,MemoryLake,ZenBrain,MIA,MSA 助你快速选型
  • 如何用PotplayerPanVideo解决网盘视频播放三大痛点:终极配置指南