Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
AUDIO
I2S音频接口
STM32F407ZGT6音频I2S对接audio框架
发布于 2023-07-27 00:12:43 浏览:609
订阅该版
各位大佬们,有I2S对接audio框架的例程参考吗,我自己移植的用wavplayer这个软件包播放音频文件串口打印是这种情况,而且没声音。 ![1.png](https://oss-club.rt-thread.org/uploads/20230727/9a59c8ec9155651d064cdccdc64ffe7b.png.webp) 我自己的代码如下 ```c #include
#include "drv_sound.h" #include "drv_wm8978.h" #define DBG_TAG "drv.sound" #define DBG_LVL DBG_INFO #include
#define CODEC_I2C_NAME ("i2c1") #define TX_DMA_FIFO_SIZE (2048) I2S_HandleTypeDef hi2s2; DMA_HandleTypeDef hdma_spi2_tx; /** * @brief I2S MSP Initialization * This function configures the hardware resources used in this example * @param hi2s: I2S handle pointer * @retval None */ void HAL_I2S_MspInit(I2S_HandleTypeDef *hi2s) { GPIO_InitTypeDef GPIO_InitStruct = {0}; RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0}; if (hi2s->Instance == SPI2) { /* USER CODE BEGIN SPI2_MspInit 0 */ /* USER CODE END SPI2_MspInit 0 */ /** Initializes the peripherals clock */ PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2S; PeriphClkInitStruct.PLLI2S.PLLI2SN = 132; PeriphClkInitStruct.PLLI2S.PLLI2SR = 5; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { Error_Handler(); } /* Peripheral clock enable */ __HAL_RCC_SPI2_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); /**I2S2 GPIO Configuration PB12 ------> I2S2_WS PB13 ------> I2S2_CK PB14 ------> I2S2_ext_SD PB15 ------> I2S2_SD PC6 ------> I2S2_MCK */ GPIO_InitStruct.Pin = GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF5_SPI2; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_14; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF6_I2S2ext; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_6; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF5_SPI2; HAL_GPIO_Init(GPIOC, &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_NORMAL; hdma_spi2_tx.Init.Priority = DMA_PRIORITY_LOW; hdma_spi2_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; if (HAL_DMA_Init(&hdma_spi2_tx) != HAL_OK) { Error_Handler(); } __HAL_LINKDMA(hi2s, hdmatx, hdma_spi2_tx); /* USER CODE BEGIN SPI2_MspInit 1 */ /* USER CODE END SPI2_MspInit 1 */ } } /** * @brief I2S MSP De-Initialization * This function freeze the hardware resources used in this example * @param hi2s: I2S handle pointer * @retval None */ void HAL_I2S_MspDeInit(I2S_HandleTypeDef *hi2s) { if (hi2s->Instance == SPI2) { /* USER CODE BEGIN SPI2_MspDeInit 0 */ /* USER CODE END SPI2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI2_CLK_DISABLE(); /**I2S2 GPIO Configuration PB12 ------> I2S2_WS PB13 ------> I2S2_CK PB14 ------> I2S2_ext_SD PB15 ------> I2S2_SD PC6 ------> I2S2_MCK */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15); HAL_GPIO_DeInit(GPIOC, GPIO_PIN_6); /* I2S2 DMA DeInit */ HAL_DMA_DeInit(hi2s->hdmatx); /* USER CODE BEGIN SPI2_MspDeInit 1 */ /* USER CODE END SPI2_MspDeInit 1 */ } } struct stm32_audio { struct rt_i2c_bus_device *i2c_bus; struct rt_audio_device audio; struct rt_audio_configure replay_config; int replay_volume; rt_uint8_t *tx_fifo; rt_bool_t startup; }; struct stm32_audio _stm32_audio_play = {0}; void i2s_samplerate_set(rt_uint32_t freq) { if (freq == I2S_AUDIOFREQ_8K || freq == I2S_AUDIOFREQ_11K || freq == I2S_AUDIOFREQ_16K || freq == I2S_AUDIOFREQ_22K || freq == I2S_AUDIOFREQ_32K || freq == I2S_AUDIOFREQ_44K || freq == I2S_AUDIOFREQ_48K || freq == I2S_AUDIOFREQ_96K) { hi2s2.Init.AudioFreq = freq; } else { return; } __HAL_I2S_DISABLE(&hi2s2); HAL_I2S_Init(&hi2s2); __HAL_I2S_ENABLE(&hi2s2); } void i2s_channels_set(rt_uint16_t channels) {} void i2s_samplebits_set(rt_uint16_t samplebits) { switch (samplebits) { case 16: hi2s2.Init.DataFormat = I2S_DATAFORMAT_16B; break; case 24: hi2s2.Init.DataFormat = I2S_DATAFORMAT_24B; break; case 32: hi2s2.Init.DataFormat = I2S_DATAFORMAT_32B; break; default: hi2s2.Init.DataFormat = I2S_DATAFORMAT_16B; break; } __HAL_I2S_DISABLE(&hi2s2); HAL_I2S_Init(&hi2s2); __HAL_I2S_ENABLE(&hi2s2); } void i2s_config_set(struct rt_audio_configure config) { i2s_channels_set(config.channels); i2s_samplerate_set(config.samplerate); i2s_samplebits_set(config.samplebits); } rt_err_t I2S_config_init(void) { 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_ENABLE; hi2s2.Init.AudioFreq = I2S_AUDIOFREQ_8K; hi2s2.Init.CPOL = I2S_CPOL_LOW; hi2s2.Init.ClockSource = I2S_CLOCK_PLL; hi2s2.Init.FullDuplexMode = I2S_FULLDUPLEXMODE_ENABLE; if (HAL_I2S_Init(&hi2s2) != HAL_OK) { rt_kprintf("HAL_I2S_Init error\n"); } return RT_EOK; } void I2S_DMAConvCplt(DMA_HandleTypeDef *hdma) { rt_audio_tx_complete(&_stm32_audio_play.audio); } void I2S_DMAError(DMA_HandleTypeDef *hdma) { rt_kprintf("DMAError\n"); } void DMA1_Stream4_IRQHandler(void) { rt_interrupt_enter(); HAL_DMA_IRQHandler(&hdma_spi2_tx); rt_interrupt_leave(); } void HAL_I2S_TxHalfCpltCallback(I2S_HandleTypeDef *hi2s) { rt_kprintf("HAL_I2S_TxHalfCpltCallback pk 1\n"); rt_audio_tx_complete(&_stm32_audio_play.audio); } void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hi2s) { rt_kprintf("HAL_I2S_TxCpltCallback pk 2\n"); rt_audio_tx_complete(&_stm32_audio_play.audio); } rt_err_t I2S_tx_dma(void) { HAL_DMA_DeInit(&hdma_spi2_tx); HAL_DMA_Init(&hdma_spi2_tx); __HAL_DMA_DISABLE(&hdma_spi2_tx); __HAL_DMA_ENABLE_IT(&hdma_spi2_tx, DMA_IT_TC); // 开启DMA传输完成中断 __HAL_DMA_ENABLE_IT(&hdma_spi2_tx, DMA_IT_HT); // 开启DMA半传输传输完成中断 __HAL_DMA_CLEAR_FLAG(&hdma_spi2_tx, DMA_FLAG_TCIF0_4); __HAL_RCC_DMA1_CLK_ENABLE(); // DMA1时钟使能 // 注册回调函数,读取数据等操作在这里面处理 hdma_spi2_tx.XferCpltCallback = I2S_DMAConvCplt; hdma_spi2_tx.XferM1CpltCallback = I2S_DMAConvCplt; hdma_spi2_tx.XferErrorCallback = I2S_DMAError; HAL_NVIC_SetPriority(DMA1_Stream4_IRQn, 0, 0); HAL_NVIC_EnableIRQ(DMA1_Stream4_IRQn); return RT_EOK; } rt_err_t i2s_tx_init() { /* set I2S_TX DMA */ I2S_config_init(); I2S_tx_dma(); return RT_EOK; } static rt_err_t stm32_player_getcaps(struct rt_audio_device *audio, struct rt_audio_caps *caps) { rt_err_t result = RT_EOK; struct stm32_audio *st_audio = (struct stm32_audio *)audio->parent.user_data; LOG_D("%s:main_type: %d, sub_type: %d", __FUNCTION__, caps->main_type, caps->sub_type); switch (caps->main_type) { case AUDIO_TYPE_QUERY: /* query the types of hw_codec device */ { switch (caps->sub_type) { case AUDIO_TYPE_QUERY: caps->udata.mask = AUDIO_TYPE_OUTPUT | AUDIO_TYPE_MIXER; break; default: result = -RT_ERROR; break; } break; } case AUDIO_TYPE_OUTPUT: /* Provide capabilities of OUTPUT unit */ { switch (caps->sub_type) { case AUDIO_DSP_PARAM: caps->udata.config.channels = st_audio->replay_config.channels; caps->udata.config.samplebits = st_audio->replay_config.samplebits; caps->udata.config.samplerate = st_audio->replay_config.samplerate; break; case AUDIO_DSP_SAMPLERATE: caps->udata.config.samplerate = st_audio->replay_config.samplerate; break; case AUDIO_DSP_CHANNELS: caps->udata.config.channels = st_audio->replay_config.channels; break; case AUDIO_DSP_SAMPLEBITS: caps->udata.config.samplebits = st_audio->replay_config.samplebits; break; default: result = -RT_ERROR; break; } break; } case AUDIO_TYPE_MIXER: /* report the Mixer Units */ { 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 = st_audio->replay_volume; break; case AUDIO_MIXER_LINE: break; default: result = -RT_ERROR; break; } break; } default: result = -RT_ERROR; break; } return result; } static rt_err_t stm32_player_configure(struct rt_audio_device *audio, struct rt_audio_caps *caps) { rt_err_t result = RT_EOK; struct stm32_audio *st_audio = (struct stm32_audio *)audio->parent.user_data; LOG_D("%s:main_type: %d, sub_type: %d", __FUNCTION__, caps->main_type, caps->sub_type); switch (caps->main_type) { case AUDIO_TYPE_MIXER: { switch (caps->sub_type) { case AUDIO_MIXER_MUTE: { /* set mute mode */ wm8978_mute_enabled(_stm32_audio_play.i2c_bus, RT_FALSE); break; } case AUDIO_MIXER_VOLUME: { int volume = caps->udata.value; st_audio->replay_volume = volume; /* set mixer volume */ wm8978_set_volume(_stm32_audio_play.i2c_bus, volume); break; } default: result = -RT_ERROR; break; } break; } case AUDIO_TYPE_OUTPUT: { switch (caps->sub_type) { case AUDIO_DSP_PARAM: { struct rt_audio_configure config = caps->udata.config; st_audio->replay_config.samplerate = config.samplerate; st_audio->replay_config.samplebits = config.samplebits; st_audio->replay_config.channels = config.channels; i2s_config_set(config); break; } case AUDIO_DSP_SAMPLERATE: { st_audio->replay_config.samplerate = caps->udata.config.samplerate; i2s_samplerate_set(caps->udata.config.samplerate); break; } case AUDIO_DSP_CHANNELS: { st_audio->replay_config.channels = caps->udata.config.channels; i2s_channels_set(caps->udata.config.channels); break; } case AUDIO_DSP_SAMPLEBITS: { st_audio->replay_config.samplebits = caps->udata.config.samplebits; i2s_samplebits_set(caps->udata.config.samplebits); break; } default: result = -RT_ERROR; break; } break; } default: break; } return result; } static rt_err_t stm32_player_init(struct rt_audio_device *audio) { /* initialize wm8978 */ _stm32_audio_play.i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(CODEC_I2C_NAME); i2s_tx_init(); wm8978_init(_stm32_audio_play.i2c_bus); return RT_EOK; } void I2S_Play_Start(void) { hi2s2.Instance->CR2 |= SPI_CR2_TXDMAEN; } static rt_err_t stm32_player_start(struct rt_audio_device *audio, int stream) { if (stream == AUDIO_STREAM_REPLAY) { rt_kprintf("HAL_I2S_Transmit_DMA start\n"); HAL_DMAEx_MultiBufferStart_IT( &hdma_spi2_tx, (uint32_t)_stm32_audio_play.tx_fifo, (uint32_t) & (SPI2->DR), (uint32_t)(_stm32_audio_play.tx_fifo + TX_DMA_FIFO_SIZE / 2), TX_DMA_FIFO_SIZE / 4); I2S_Play_Start(); wm8978_player_start(_stm32_audio_play.i2c_bus); } return RT_EOK; } static rt_err_t stm32_player_stop(struct rt_audio_device *audio, int stream) { if (stream == AUDIO_STREAM_REPLAY) { HAL_I2S_DMAStop(&hi2s2); } return RT_EOK; } static void stm32_player_buffer_info(struct rt_audio_device *audio, struct rt_audio_buf_info *info) { /** * TX_FIFO * +----------------+----------------+ * | block1 | block2 | * +----------------+----------------+ * \ block_size / */ info->buffer = _stm32_audio_play.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 _p_audio_ops = { .getcaps = stm32_player_getcaps, .configure = stm32_player_configure, .init = stm32_player_init, .start = stm32_player_start, .stop = stm32_player_stop, .transmit = NULL, .buffer_info = stm32_player_buffer_info, }; int rt_hw_sound_init(void) { rt_uint8_t *tx_fifo; /* player */ tx_fifo = rt_malloc(TX_DMA_FIFO_SIZE); if (tx_fifo == RT_NULL) { return -RT_ENOMEM; } rt_memset(tx_fifo, 0, TX_DMA_FIFO_SIZE); //_stm32_audio_play.tx_fifo = tx_fifo; _stm32_audio_play.tx_fifo = tx_fifo; /* init default configuration */ { _stm32_audio_play.replay_config.samplerate = 44100; _stm32_audio_play.replay_config.channels = 2; _stm32_audio_play.replay_config.samplebits = 16; _stm32_audio_play.replay_volume = 30; } /* register sound device */ _stm32_audio_play.audio.ops = &_p_audio_ops; rt_audio_register(&_stm32_audio_play.audio, "sound0", RT_DEVICE_FLAG_WRONLY, &_stm32_audio_play); return RT_EOK; } INIT_DEVICE_EXPORT(rt_hw_sound_init); ``` 请各位看看有什么问题,我自己卡了好久了。
查看更多
2
个回答
默认排序
按发布时间排序
张世争
2023-07-27
学以致用
codec 配置对吗?
StackYuan
认证专家
2023-07-27
这家伙很懒,什么也没写!
I2S驱动这部分可以参考下星火1号的驱动,I2C部分建议按照你自己codec型号来定
撰写答案
登录
注册新账号
关注者
0
被浏览
609
关于作者
lixiangcm
这家伙很懒,什么也没写!
提问
3
回答
0
被采纳
0
关注TA
发私信
相关问题
1
I2S WM8978 DMA没中断问题,参考SAI驱动改写
2
rtthread 中没有stm32的i2s(不是sai)的驱动?
3
rt-thread 官方可以对stm32系列添加i2s的驱动么?
4
求参考I2S 驱动与音频例程
5
咨询大家一个问题,单纯的I2S能调节音量吗?
6
STM32F407+PCM5102APWR+SD卡内播放wav或mp3音乐如何实现?
7
how to send i2s data from rk2108?
8
I2S WM8978 播放速度慢,有哒哒哒的噪声求助
9
audio的replay模式播放时是先发一段0来启动吗?
10
audio的replay模式不能播放长度小于内存块大小的数据吗?
推荐文章
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
ota在线升级
UART
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
at_device
ulog
C++_cpp
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
张世争
8
个答案
2
次被采纳
rv666
5
个答案
2
次被采纳
用户名由3_15位
11
个答案
1
次被采纳
KunYi
6
个答案
1
次被采纳
本月文章贡献
程序员阿伟
6
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
大龄码农
1
篇文章
2
次点赞
ThinkCode
1
篇文章
1
次点赞
Betrayer
1
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部