10925 views|0 replies

28

Posts

0

Resources
The OP

STM32F407 transmission problem about i2s DMA [Copy link]

Recently, I used stm32f407 to make a project of audio transmission after decoding mp3 from sd card. The sound card chip used was VM8978, i2s of SPI3 was adopted, and the DMA used was stream5 channel 0 of DMA1. I used the master transmission mode. In the DMA interrupt, I used an LED to reverse to see if the interrupt was entered. The result was that the interrupt was entered, but why did the i2s pin not output? Logically, there should be waveform output. Why is the BCLk pin always at a low level? Please enlighten me! ! The program is as follows: DMA_InitTypeDef DMA_InitStructure; u32 AudioTotalSize = 0xffff; u32 AudioRemSize = 0; u16 *CurrentPos; extern void AUDIO_TransferComplete(u32 pBuffer, uint32_t Size); void AUDIO_Init(u32 AudioFreq) { Audio_I2S_Init(AudioFreq); I2S_GPIO_Init(); Audio_DMA_Init(); } void I2s_GPIO_DEinit(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; /* I2S3S_WS */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15; GPIO_Init(GPIOA, &GPIO_InitStructure); /* I2S3_CK, I2S3_SD, I2S3ext_SD */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5; GPIO_Init(GPIOB, &GPIO_InitStructure); } void I2S_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; I2s_GPIO_DEinit(); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; /* Connect pins to I2S peripheral */ GPIO_PinAFConfig(GPIOA, GPIO_PinSource15, GPIO_AF_SPI3); GPIO_PinAFConfig(GPIOB, GPIO_PinSource3, GPIO_AF_SPI3); GPIO_PinAFConfig(GPIOB, GPIO_PinSource4, GPIO_AF_I2S3ext); GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_SPI3); /* I2S3S_WS */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15; GPIO_Init(GPIOA, &GPIO_InitStructure); /* I2S3_CK, I2S3_SD, I2S3ext_SD */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5; GPIO_Init(GPIOB, &GPIO_InitStructure); } void Audio_I2S_Init(uint32_t AudioFreq) { I2S_InitTypeDef I2S_InitStructure; SPI_I2S_DeInit(SPI3); RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE); SPI_I2S_DeInit(SPI3); I2S_InitStructure.I2S_AudioFreq = AudioFreq; I2S_InitStructure.I2S_Standard = I2S_Standard_Phillips; I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16b; I2S_InitStructure.I2S_CPOL = I2S_CPOL_Low; I2S_InitStructure.I2S_Mode = I2S_Mode_MasterTx; I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Disable; I2S_Init(SPI3, &I2S_InitStructure); } //DMA transfer configuration void Audio_DMA_Init(void) { NVIC_InitTypeDef NVIC_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE); DMA_Cmd(DMA1_Stream5,DISABLE);
          DMA_DeInit(DMA1_Stream5);
          DMA_InitStructure.DMA_Channel = DMA_Channel_0;  
          DMA_InitStructure.DMA_PeripheralBaseAddr = 0x4000380C;
          DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)0;//该项将在播放函数中进行配置
          DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
          DMA_InitStructure.DMA_BufferSize = (uint32_t)0xFFFE;//该项将在播放函数中进行配置      
          DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
          DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
          DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
          DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
          DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
          DMA_InitStructure.DMA_Priority = DMA_Priority_High;
          DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         
          DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull;
          DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
          DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;  
          DMA_Init(DMA1_Stream5, &DMA_InitStructure);  
          DMA_ITConfig(DMA1_Stream5, DMA_IT_TC, ENABLE);//使能所选DMA的中断
          //I2S DMA中断通道配置
          NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream5_IRQn;
          NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//抢占优先级(0 最高)
          NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//子优先级(0 最高)
          NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
          NVIC_Init(&NVIC_InitStructure);   
          SPI_I2S_DMACmd(SPI3, SPI_I2S_DMAReq_Tx, ENABLE);//中断请求使能  
}


//开始从特定大小(Size)的缓冲区(pBuffer)中播放音频流
uint32_t AUDIO_Play(u16* pBuffer, u32 Size)
{
          AudioTotalSize=Size;
          Audio_MAL_Play((u32)pBuffer,(u32)(DMA_MAX(Size/4)));//更新媒体层数据并播放
          AudioRemSize=(Size/2)-DMA_MAX(AudioTotalSize);//更新剩余数据量
          CurrentPos=pBuffer+DMA_MAX(AudioTotalSize);//更新当新数据指针
          return 0;
}

//开始播放媒体中的音频流
void Audio_MAL_Play(u32 Addr, u32 Size)
{         
          DMA_InitStructure.DMA_Memory0BaseAddr=(uint32_t)Addr;//配置缓冲区地址和大小
          DMA_InitStructure.DMA_BufferSize=(uint32_t)Size/2;
          DMA_Init(DMA1_Stream5,&DMA_InitStructure);
          DMA_Cmd(DMA1_Stream5,ENABLE);//I2S DMA使能   
          if ((SPI3->I2SCFGR & I2S_ENABLE_MASK)==0)I2S_Cmd(SPI3,ENABLE);//若I2S接口未使能,则使能
}

//I2S中断处理
void SPI3_IRQHandler(void)
{
          if (SPI_I2S_GetFlagStatus(SPI3,SPI_I2S_FLAG_TXE)!=RESET)
          {            
            SPI_I2S_SendData(SPI3, 0);//发送空字节到I2S
                        SPI_I2S_ClearFlag(SPI3,SPI_I2S_FLAG_TXE);
          }
}

//DMA中断处理函数
void DMA1_Stream5_IRQHandler(void)
{   
          //传送完成中断
          if (DMA_GetFlagStatus(DMA1_Stream5, DMA_FLAG_TCIF5)!=RESET) { if (AudioRemSize>0) // Check if the end of the file has been reached { printf("DMA1\r\n"); while (DMA_GetCmdStatus(DMA1_Stream5) != DISABLE) IWDG_ReloadCounter(); // Wait for DMA disabled DMA_ClearFlag(DMA1_Stream5, DMA_FLAG_TCIF5); // Clear the transfer completion interrupt flag DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) CurrentPos; // Reconfigure the buffer address and size DMA_InitStructure.DMA_BufferSize = (uint32_t) (DMA_MAX(AudioRemSize)); DMA_Init(DMA1_Stream5, &DMA_InitStructure); DMA_Cmd(DMA1_Stream5, ENABLE); CurrentPos += DMA_MAX(AudioRemSize);//Update data pointer AudioRemSize -= DMA_MAX(AudioRemSize);//Update remaining data DMA_Cmd(DMA1_Stream5, ENABLE); } else//End of file reached{ DMA_Cmd(DMA1_Stream5, DISABLE); DMA_ClearFlag(DMA1_Stream5, DMA_FLAG_TCIF5); AUDIO_TransferComplete((uint32_t)CurrentPos, 0); STM_EVAL_LEDToggle(2); //led invert, display status// printf("DMA2\r\n"); } // printf("DMA3\r\n"); } } [ This post was last edited by xslyk at 2013-7-1 09:12]
This post is from stm32/stm8

Guess Your Favourite
Find a datasheet?

EEWorld Datasheet Technical Support

Related articles more>>

    EEWorld
    subscription
    account

    EEWorld
    service
    account

    Automotive
    development
    circle

    Robot
    development
    community

    Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
    快速回复 返回顶部 Return list