完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
使用STM32F4的I2S接口,直接找的论坛的I2S代码 drv_i2s代码,发现能够正常播放音频,但是播放速度慢,有频率很高的哒哒哒的噪声,求助原因,代码如下:
drv_i2s: I2S_HandleTypeDef hi2s2; DMA_HandleTypeDef hdma_spi2_tx; 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"); } SET_BIT(hi2s2.Instance->CR2, SPI_CR2_TXDMAEN); __HAL_I2S_ENABLE(&hi2s2); 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 I2S_TxHalfCpltCallback(I2S_HandleTypeDef *hi2s) { 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_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); //注册回调函数,读取数据等操作在这里面处理 hdma_spi2_tx.XferCpltCallback = I2S_DMAConvCplt; hdma_spi2_tx.XferM1CpltCallback = I2S_DMAConvCplt; hdma_spi2_tx.XferErrorCallback = I2S_DMAError; hdma_spi2_tx.XferHalfCpltCallback=I2S_TxHalfCpltCallback; 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; } 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"); wm8978_player_start(_stm32_audio_play.i2c_bus); 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 / 2); //HAL_I2S_Transmit_DMA(&hi2s2,(uint16_t *)_stm32_audio_play.tx_fifo,TX_DMA_FIFO_SIZE); } 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); rt_kprintf("HAL_I2S_Transmit_DMA stop\n"); } 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 = 48000; _stm32_audio_play.replay_config.channels = 1; _stm32_audio_play.replay_config.samplebits = 16; _stm32_audio_play.replay_volume = 15; } /* 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); 使用的模拟i2c控制,msp初始化如下: extern DMA_HandleTypeDef hdma_spi2_tx; void HAL_I2S_MspInit(I2S_HandleTypeDef *hi2s) { if (hi2s->Instance == SPI2) { RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0}; PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2S; PeriphClkInitStruct.PLLI2S.PLLI2SN = 271; PeriphClkInitStruct.PLLI2S.PLLI2SR = 2; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { Error_Handler(); } GPIO_InitTypeDef GPIO_InitStruct; /* Peripheral clock enable */ __HAL_RCC_SPI2_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); __HAL_RCC_GPIOI_CLK_ENABLE(); /**I2S2 GPIO Configuration PC2 ------> I2S2_ext_SD PC3 ------> I2S2_SD PB12 ------> I2S2_WS PB13 ------> I2S2_CK PC6 ------> I2S2_MCK */ GPIO_InitStruct.Pin = GPIO_PIN_2; 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(GPIOC, &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); GPIO_InitStruct.Pin = GPIO_PIN_3; 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(GPIOI, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_12; 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_3; 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(GPIOD, &GPIO_InitStruct); __HAL_RCC_DMA1_CLK_ENABLE(); hdma_spi2_tx.Instance = DMA1_Stream4; //DMA1数据流4 hdma_spi2_tx.Init.Channel = DMA_CHANNEL_0; //通道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; //存储器增量模式 /*todo 这里按照道理应该根据数据位宽来配置 ?*/ hdma_spi2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; //外设数据长度:16位 hdma_spi2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; //存储器数据长度:16位 hdma_spi2_tx.Init.Mode = DMA_CIRCULAR; //使用循环模式 hdma_spi2_tx.Init.Priority = DMA_PRIORITY_VERY_HIGH; //高优先级 hdma_spi2_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; //不使用FIFO hdma_spi2_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; // 使用FIFO阈值完全配置 hdma_spi2_tx.Init.MemBurst = DMA_MBURST_SINGLE; //存储器单次突发传输 hdma_spi2_tx.Init.PeriphBurst = DMA_MBURST_SINGLE; //外设突发单次传输 if (HAL_DMA_Init(&hdma_spi2_tx) != HAL_OK) { Error_Handler(); } __HAL_LINKDMA(hi2s,hdmatx,hdma_spi2_tx); } } 其实一开始的播放速度很慢很慢,后面我修改了DMAFIFO的大小,调大了,速度就快了些,但是总的来说还是慢,且噪声非常大 #define TX_DMA_FIFO_SIZE (4096) #define I2S_SOUND_NAME "sound0" #define CODEC_I2C_NAME ("i2c1") 卡了很久了,求助 |
|
相关推荐
1个回答
|
|
根据您提供的信息,播放速度慢和哒哒哒噪声的原因可能有以下几点:
1. 采样率设置不正确:请检查您的音频文件的采样率是否与STM32F4的I2S接口设置的采样率相匹配。如果采样率不匹配,可能导致播放速度变慢。 2. I2S时钟配置问题:请检查I2S时钟配置是否正确。错误的时钟配置可能导致播放速度慢和噪声问题。 3. DMA配置问题:请检查DMA的配置,确保DMA传输速率和数据大小设置正确。错误的DMA配置可能导致播放速度慢和噪声问题。 4. 音频文件格式问题:请检查音频文件的格式是否支持或兼容。某些音频格式可能需要特定的解码器或处理方式。 5. 代码问题:请仔细检查您的代码,确保I2S初始化、配置和数据处理部分没有错误。 解决方案: 1. 检查采样率设置:确保音频文件的采样率与STM32F4的I2S接口设置的采样率相匹配。 2. 检查I2S时钟配置:确保I2S时钟配置正确,可以参考STM32F4的参考手册进行配置。 3. 检查DMA配置:确保DMA的配置正确,包括传输速率和数据大小。 4. 检查音频文件格式:确保音频文件格式支持或兼容,如果需要,可以尝试转换音频文件格式。 5. 检查代码:仔细检查您的代码,确保I2S初始化、配置和数据处理部分没有错误。如果可能,可以参考其他成功的项目或示例代码。 6. 使用示波器或逻辑分析仪检查I2S信号:这可以帮助您确定问题是否出在硬件上,例如I2S接口或连接线。 7. 更新固件和库:确保您使用的STM32F4固件和库是最新版本,以避免已知的问题。 通过以上步骤,您应该能够找到问题的原因并解决播放速度慢和哒哒哒噪声的问题。 |
|
|
|
只有小组成员才能发言,加入小组>>
156个成员聚集在这个小组
加入小组【Vision Board创客营连载体验】基于RA8D1-Vision Board的自动路径规划小车
900 浏览 0 评论
【Vision Board创客营连载体验】基于Vision Board的垃圾分类
1300 浏览 0 评论
【Vision Board创客营连载体验】使用 Vision Board 做一个 UVC Camera
930 浏览 0 评论
【Vision Board创客营连载体验】TinyMaix进行手写数字识别
1196 浏览 0 评论
【Vision Board创客营连载体验】RA8D1-Vision Board使用7寸屏设置为RGB666大端模式模式成功显示摄像头图案
1203 浏览 0 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-22 01:07 , Processed in 0.545194 second(s), Total 51, Slave 43 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号