Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
I2S音频接口
wavplayer
STM32F407+PCM5102APWR+SD卡内播放wav或mp3音乐如何实现?
发布于 2024-01-04 13:59:23 浏览:739
订阅该版
控制器芯片:STM32F407VET6 开发软件:RT-Thread studio 电路图: ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240104/c9bcffda0db9e5bb65e08c502f18a4c0.png.webp) board.c文件实现HAL_I2S_MspInit函数I2S接口: ```c I2S_HandleTypeDef hi2s2; DMA_HandleTypeDef hdma_spi2_tx; /* I2S2 init function */ void MX_I2S2_Init(void) { /* USER CODE BEGIN I2S2_Init 0 */ /* USER CODE END I2S2_Init 0 */ /* USER CODE BEGIN I2S2_Init 1 */ /* USER CODE END I2S2_Init 1 */ hi2s2.Instance = SPI2; hi2s2.Init.Mode = I2S_MODE_MASTER_TX; hi2s2.Init.Standard = I2S_STANDARD_PHILIPS; hi2s2.Init.DataFormat = I2S_DATAFORMAT_16B; hi2s2.Init.MCLKOutput = I2S_MCLKOUTPUT_DISABLE; hi2s2.Init.AudioFreq = I2S_AUDIOFREQ_48K; hi2s2.Init.CPOL = I2S_CPOL_LOW; hi2s2.Init.ClockSource = I2S_CLOCK_PLL; hi2s2.Init.FullDuplexMode = I2S_FULLDUPLEXMODE_DISABLE; if (HAL_I2S_Init(&hi2s2) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN I2S2_Init 2 */ /* USER CODE END I2S2_Init 2 */ } void HAL_I2S_MspInit(I2S_HandleTypeDef* i2sHandle) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(i2sHandle->Instance==SPI2) { /* USER CODE BEGIN SPI2_MspInit 0 */ /* USER CODE END SPI2_MspInit 0 */ /* I2S2 clock enable */ __HAL_RCC_SPI2_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); /**I2S2 GPIO Configuration PC3 ------> I2S2_SD PB10 ------> I2S2_CK PB9 ------> I2S2_WS */ GPIO_InitStruct.Pin = GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF5_SPI2; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF5_SPI2; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* I2S2 DMA Init */ /* SPI2_TX Init */ hdma_spi2_tx.Instance = DMA1_Stream4; hdma_spi2_tx.Init.Channel = DMA_CHANNEL_0; hdma_spi2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; hdma_spi2_tx.Init.PeriphInc = DMA_PINC_DISABLE; hdma_spi2_tx.Init.MemInc = DMA_MINC_ENABLE; hdma_spi2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; hdma_spi2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; hdma_spi2_tx.Init.Mode = DMA_CIRCULAR; hdma_spi2_tx.Init.Priority = DMA_PRIORITY_MEDIUM; hdma_spi2_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE; hdma_spi2_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; hdma_spi2_tx.Init.MemBurst = DMA_MBURST_SINGLE; hdma_spi2_tx.Init.PeriphBurst = DMA_PBURST_SINGLE; if (HAL_DMA_Init(&hdma_spi2_tx) != HAL_OK) { Error_Handler(); } __HAL_LINKDMA(i2sHandle,hdmatx,hdma_spi2_tx); /* USER CODE BEGIN SPI2_MspInit 1 */ /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, GPIO_PIN_SET); /*Configure GPIO pin : PC2 */ GPIO_InitStruct.Pin = GPIO_PIN_2; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); /* USER CODE END SPI2_MspInit 1 */ } } ``` 打开HAL_I2S_MODULE_ENABLED注释: ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240104/6276b3c3f03d8e27fcc6e8303143828f.png.webp) 添加软件包wavplayer: ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240104/9b8a3c33e940bd746a66487cf951f83a.png) ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240104/661c93356e0082da4378f864ac8cafae.png) sd卡使用spi挂载已经实现了,这里就不再详细说明 编译下载代码后,播放sd卡内wav文件,提示sound0未发现,这个声卡驱动要怎么对应编写呢?网上也查不到对应的资料,求指教??? ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240104/1096cd248ba1c622a114693b3103c382.png) 后面找到一篇文章,这里贴出来https://zhuanlan.zhihu.com/p/334356821 实现一下文章里的drv_virtual.c文件,这应该是一个模拟的驱动,测试后不会发出声音,怎么对应修改呢? ```c /* * File: drv_virtual.c * * COPYRIGHT (C) 2012-2019, Shanghai Real-Thread Technology Co., Ltd */ //#include "drv_virtual.h" #include "dfs.h" #include
#include
#define DBG_TAG "drv_virtual" #define DBG_LVL DBG_LOG #define DBG_COLOR #include
#define TX_DMA_FIFO_SIZE (2048) struct tina_sound { struct rt_audio_device device; struct rt_audio_configure replay_config; int volume; rt_uint8_t *tx_fifo; int fd; struct rt_thread thread; int endflag; }; static rt_err_t getcaps(struct rt_audio_device *audio, struct rt_audio_caps *caps) { rt_err_t ret = RT_EOK; struct tina_sound *sound = RT_NULL; RT_ASSERT(audio != RT_NULL); sound = (struct tina_sound *)audio->parent.user_data; (void)sound; switch(caps->main_type) { case AUDIO_TYPE_QUERY: { switch (caps->sub_type) { case AUDIO_TYPE_QUERY: caps->udata.mask = AUDIO_TYPE_OUTPUT | AUDIO_TYPE_MIXER; break; default: ret = -RT_ERROR; break; } break; } case AUDIO_TYPE_OUTPUT: { switch(caps->sub_type) { case AUDIO_DSP_PARAM: caps->udata.config.channels = sound->replay_config.channels; caps->udata.config.samplebits = sound->replay_config.samplebits; caps->udata.config.samplerate = sound->replay_config.samplerate; break; default: ret = -RT_ERROR; break; } break; } case AUDIO_TYPE_MIXER: { switch (caps->sub_type) { case AUDIO_MIXER_QUERY: caps->udata.mask = AUDIO_MIXER_VOLUME | AUDIO_MIXER_LINE; break; case AUDIO_MIXER_VOLUME: caps->udata.value = sound->volume; break; case AUDIO_MIXER_LINE: break; default: ret = -RT_ERROR; break; } break; } default: ret = -RT_ERROR; break; } return ret; } static rt_err_t configure(struct rt_audio_device *audio, struct rt_audio_caps *caps) { rt_err_t ret = RT_EOK; struct tina_sound *sound = RT_NULL; RT_ASSERT(audio != RT_NULL); sound = (struct tina_sound *)audio->parent.user_data; (void)sound; switch(caps->main_type) { case AUDIO_TYPE_MIXER: { switch(caps->sub_type) { case AUDIO_MIXER_VOLUME: { int volume = caps->udata.value; sound->volume = volume; break; } default: ret = -RT_ERROR; break; } break; } case AUDIO_TYPE_OUTPUT: { switch(caps->sub_type) { case AUDIO_DSP_PARAM: { int samplerate; samplerate = caps->udata.config.samplerate; sound->replay_config.samplerate = samplerate; LOG_I("set samplerate = %d", samplerate); break; } case AUDIO_DSP_SAMPLERATE: { int samplerate; samplerate = caps->udata.config.samplerate; sound->replay_config.samplerate = samplerate; LOG_I("set samplerate = %d", samplerate); break; } case AUDIO_DSP_CHANNELS: { break; } default: break; } break; } default: break; } return ret; } static void virtualplay(void *p) { struct tina_sound *sound = (struct tina_sound *)p; (void)sound; while(1) { /* tick = TX_DMA_FIFO_SIZE/2 * 1000ms / 44100 / 4 ≈ 5.8 */ rt_thread_mdelay(6); rt_audio_tx_complete(&sound->device); if(sound->endflag == 1) { break; } } } static int thread_stack[1024] = {0}; static rt_err_t init(struct rt_audio_device *audio) { struct tina_sound *sound = RT_NULL; RT_ASSERT(audio != RT_NULL); sound = (struct tina_sound *)audio->parent.user_data; (void)sound; LOG_I("sound init"); return RT_EOK; } static rt_err_t start(struct rt_audio_device *audio, int stream) { struct tina_sound *sound = RT_NULL; rt_err_t ret = RT_EOK; RT_ASSERT(audio != RT_NULL); sound = (struct tina_sound *)audio->parent.user_data; (void)sound; LOG_I("sound start"); ret = rt_thread_init(&sound->thread, "virtual", virtualplay, sound, &thread_stack, sizeof(thread_stack), 1, 10); if(ret != RT_EOK) { LOG_E("virtual play thread init failed"); return (-RT_ERROR); } rt_thread_startup(&sound->thread); sound->endflag = 0; sound->fd = open("/tmp/virtual.pcm", O_CREAT | O_RDWR, 0666); return RT_EOK; } static rt_err_t stop(struct rt_audio_device *audio, int stream) { struct tina_sound *sound = RT_NULL; RT_ASSERT(audio != RT_NULL); sound = (struct tina_sound *)audio->parent.user_data; (void)sound; LOG_I("sound stop"); sound->endflag = 1; close(sound->fd); sound->fd = -1; return RT_EOK; } rt_size_t transmit(struct rt_audio_device *audio, const void *wb, void *rb, rt_size_t size) { struct tina_sound *sound = RT_NULL; RT_ASSERT(audio != RT_NULL); sound = (struct tina_sound *)audio->parent.user_data; (void)sound; return write(sound->fd, wb, size); } static void buffer_info(struct rt_audio_device *audio, struct rt_audio_buf_info *info) { struct tina_sound *sound = RT_NULL; RT_ASSERT(audio != RT_NULL); sound = (struct tina_sound *)audio->parent.user_data; /** * TX_FIFO * +----------------+----------------+ * | block1 | block2 | * +----------------+----------------+ * \ block_size / */ info->buffer = sound->tx_fifo; info->total_size = TX_DMA_FIFO_SIZE; info->block_size = TX_DMA_FIFO_SIZE / 2; info->block_count = 2; } static struct rt_audio_ops ops = { .getcaps = getcaps, .configure = configure, .init = init, .start = start, .stop = stop, .transmit = transmit, .buffer_info = buffer_info, }; static int rt_hw_sound_init(void) { rt_uint8_t *tx_fifo = RT_NULL; static struct tina_sound sound = {0}; /* 分配 DMA 搬运 buffer */ tx_fifo = rt_calloc(1, TX_DMA_FIFO_SIZE); if(tx_fifo == RT_NULL) { return -RT_ENOMEM; } sound.tx_fifo = tx_fifo; /* 配置 DSP 参数 */ { sound.replay_config.samplerate = 44100; sound.replay_config.channels = 2; sound.replay_config.samplebits = 16; sound.volume = 60; sound.fd = -1; sound.endflag = 0; } /* 注册声卡放音驱动 */ sound.device.ops = &ops; rt_audio_register(&sound.device, "sound0", RT_DEVICE_FLAG_WRONLY, &sound); return RT_EOK; } INIT_DEVICE_EXPORT(rt_hw_sound_init); ``` 最后下载代码后,播放wav确实从耳机听不到声音,在sd卡内也没有见/tmp/virtual.pcm这个文件生成,看不太懂,我是新手,请大佬指教,如何使用这个板子从sd卡播放wav或者mp3,使用mp3player软件包也是这样无法播放,求解答??? ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240104/4969438c3ffad59891e89eab2155590d.png)
查看更多
5
个回答
默认排序
按发布时间排序
Lrain
2024-01-05
这家伙很懒,什么也没写!
顶
winfeng
认证专家
2024-01-06
这家伙很懒,什么也没写!
你的问题需要先驱动pcm5102,可以试着先产生一个正弦波;硬件没问题了再解决播放文件。
KunYi
2024-01-06
这家伙很懒,什么也没写!
使用 "模拟的驱动" 修改變成對PCM5102A的操作讓這個 變成真正PCM5102A的驅動 簡單說就是怎樣用I2S把 Audio data 往 PCM5102A 送
kami
2024-01-06
这家伙很懒,什么也没写!
首先你要做的是驱动 你要实现驱动层的这几个函数 ```c //返回音频设备的硬件参数给上层应用 static rt_err_t getcaps(struct rt_audio_device *audio, struct rt_audio_caps *caps) //配置音频设备, 比如音量, eq之类的,纯播放不需要 static rt_err_t configure(struct rt_audio_device *audio, struct rt_audio_caps *caps) //初始化音频设备, 比如DMA初始化, GPIO初始化,时钟之类的 static rt_err_t init(struct rt_audio_device *audio) //开始DMA传输 static rt_err_t start(struct rt_audio_device *audio, int stream) //停止音频设备或者停止DMA搬运 static rt_err_t stop(struct rt_audio_device *audio, int stream) //发送数据给硬件设备, 实际用不到, 因为DMA开启后就会一直搬运缓存数据 static rt_ssize_t transmit(struct rt_audio_device *audio, const void *wb, void *rb, rt_size_t size) //返回Buffer的信息 static void buffer_info(struct rt_audio_device *audio, struct rt_audio_buf_info *info); ``` 通过rt_audio_register注册音频设备 ```c static struct rt_audio_ops ops = { .getcaps = getcaps, .configure = configure, .init = init, .start = start, .stop = stop, .transmit = transmit, .buffer_info = buffer_info }; struct rt_audio_device device; device.ops = ops; rt_audio_register(&device, "sound0", RT_DEVICE_FLAG_WRONLY, user_data); ``` 一般rt_audio_register最后一个参数都是一个自己定义的数据结构, 也就是上面每一个实现函数中的第一个参数struct rt_audio_device *audio 里面的audio->parent.user_data 方便给每一个实现函数传递公共数据. 具体你可以参照这个驱动模板写驱动 https://club.rt-thread.org/ask/question/9fa2967d62af2598.html
用RTT跑流水灯
2024-01-06
这家伙很懒,什么也没写!
要实现sound的驱动适配PCM5102APWR,如果有裸机驱动的代码,移植起来应该也很快的;
撰写答案
登录
注册新账号
关注者
0
被浏览
739
关于作者
Lrain
这家伙很懒,什么也没写!
提问
13
回答
22
被采纳
0
关注TA
发私信
相关问题
1
I2S WM8978 DMA没中断问题,参考SAI驱动改写
2
rtthread 中没有stm32的i2s(不是sai)的驱动?
3
rt-thread 官方可以对stm32系列添加i2s的驱动么?
4
求参考I2S 驱动与音频例程
5
咨询大家一个问题,单纯的I2S能调节音量吗?
6
STM32F407ZGT6音频I2S对接audio框架
7
how to send i2s data from rk2108?
8
I2S WM8978 播放速度慢,有哒哒哒的噪声求助
9
wavplayer使用遇到的问题
10
AB32VG1播放wavmsh下报错
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
使用百度AI助手辅助编写一个rt-thread下的ONVIF设备发现功能的功能代码
2
RT-Thread 发布 EtherKit开源以太网硬件!
3
rt-thread使用cherryusb实现虚拟串口
4
《C++20 图形界面程序:速度与渲染效率的双重优化秘籍》
5
《原子操作:程序世界里的“最小魔法单位”解析》
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
UART
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
ulog
C++_cpp
at_device
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
a1012112796
13
个答案
2
次被采纳
张世争
9
个答案
2
次被采纳
rv666
5
个答案
2
次被采纳
用户名由3_15位
11
个答案
1
次被采纳
本月文章贡献
程序员阿伟
8
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
大龄码农
1
篇文章
5
次点赞
ThinkCode
1
篇文章
1
次点赞
Betrayer
1
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部