/** * @brief Main program. * @param None * @retval None */ int main(void) { /*!< At this stage the microcontroller clock setting is already configured, this is done through SystemInit() function which is called from startup file (startup_stm32f0xx.s) before to branch to application main. To reconfigure the default setting of SystemInit() function, refer to system_stm32f0xx.c file */ /* I2S peripheral Configuration */ I2S_Config(); /* Enable the Tamper button */ STM_EVAL_PBInit(BUTTON_TAMPER, BUTTON_MODE_GPIO); /* Initialize the LEDs */ STM_EVAL_LEDInit(LED3); STM_EVAL_LEDInit(LED1); #if defined (I2S_MASTER_TRANSMITTER) while (STM_EVAL_PBGetState(BUTTON_TAMPER) != RESET) {} /* Enable the I2S1 TX Interrupt */ SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_TXE, ENABLE); /* Enable the I2S */ I2S_Cmd(SPI1, ENABLE); while(TxIdx < 32); #elif defined (I2S_SLAVE_RECEIVER) /* Enable the I2S1 RXNE Interrupt */ SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_RXNE, ENABLE); /* Enable the I2S */ I2S_Cmd(SPI1, ENABLE); /* Wait the end of communication */ while (RxIdx < 32); /* Check if the data transmitted from Master Board and received by Slave Board are the same */ TransferStatus = Buffercmp(I2S_Buffer_Rx, (uint16_t*)I2S_Buffer_Tx, 32); if (TransferStatus == PASSED) /* successful transfer */ { /* Green Led On */ STM_EVAL_LEDOn(LED1); STM_EVAL_LEDOff(LED3); } else /* unsuccessful transfer */ { /* Red Led On */ STM_EVAL_LEDOn(LED3); STM_EVAL_LEDOff(LED1); } #endif /* Infinite loop */ while (1) {} }
//*---------------------------------------------------------------------------- //* Function Name : I2S_Block_Process //* Object : //* Object : //* Input Parameters : //* Output Parameters : //* Functions called : //*---------------------------------------------------------------------------- void I2S_Block_Process(uint32_t txAddr, uint32_t rxAddr, uint32_t Size) { txbuf = txAddr; rxbuf = rxAddr; szbuf = Size; // Configure the tx buffer address and size DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)txAddr; DMA_InitStructure.DMA_BufferSize = (uint32_t)Size; // Configure the DMA Stream with the new parameters DMA_Init(AUDIO_I2S_DMA_STREAM, &DMA_InitStructure); // Configure the rx buffer address and size DMA_InitStructure2.DMA_Memory0BaseAddr = (uint32_t)rxAddr; DMA_InitStructure2.DMA_BufferSize = (uint32_t)Size; // Configure the DMA Stream with the new parameters DMA_Init(AUDIO_I2S_EXT_DMA_STREAM, &DMA_InitStructure2); // Enable the I2S DMA Streams DMA_Cmd(AUDIO_I2S_DMA_STREAM, ENABLE); DMA_Cmd(AUDIO_I2S_EXT_DMA_STREAM, ENABLE); // If the I2S peripheral is still not enabled, enable it if ((CODEC_I2S->I2SCFGR & 0x0400) == 0) { I2S_Cmd(CODEC_I2S, ENABLE); } if ((CODEC_I2S_EXT->I2SCFGR & 0x0400) == 0) { I2S_Cmd(CODEC_I2S_EXT, ENABLE); } }
void I2S_Enable(){ /* If the I2S peripheral is still not enabled, enable it */ if ((CODEC_I2S->I2SCFGR & 0x0400) == 0){ I2S_Cmd(CODEC_I2S, ENABLE); } if ((CODEC_I2S_EXT->I2SCFGR & 0x0400) == 0){ I2S_Cmd(CODEC_I2S_EXT, ENABLE); } }
//*---------------------------------------------------------------------------- //* Function Name : I2S_Block_Stop //* Object : //* Object : //* Input Parameters : //* Output Parameters : //* Functions called : //*---------------------------------------------------------------------------- void I2S_Block_Stop(void) { I2S_Cmd(CODEC_I2S_EXT, DISABLE); I2S_Cmd(CODEC_I2S, DISABLE); DMA_Cmd(AUDIO_I2S_EXT_DMA_STREAM, DISABLE); DMA_Cmd(AUDIO_I2S_DMA_STREAM, DISABLE); SPI_I2S_DMACmd(CODEC_I2S_EXT, SPI_I2S_DMAReq_Rx, DISABLE); NVIC_DisableIRQ(AUDIO_I2S_EXT_DMA_IRQ); DMA_ITConfig(AUDIO_I2S_EXT_DMA_STREAM, DMA_IT_TC | DMA_IT_HT, DISABLE); }
/******************************************************************************* * Function Name : INTR_RXSTSQLVL_ISODU_Callback * Description : Rx FIFO Status Queue Level, Data Update interrupt callback routine. * Input : None. * Output : None. * Return : None. *******************************************************************************/ void INTR_RXSTSQLVL_ISODU_Callback(void) { /* Check if the USB transfer has reached the half of the global buffer */ if(IsocBufferIdx == (NUM_SUB_BUFFERS / 2)) { /* Check if the DMA is already enabled or not */ if ((DMA1_Channel5->CCR & 0x1) == 0x0) { /* Re-Initialize the number of data to be transferred */ DMA1_Channel5->CNDTR = (uint16_t)((ISOC_BUFFER_SZE * NUM_SUB_BUFFERS) / 2); /* Enable DMA1 Channel5 */ DMA_Cmd(DMA1_Channel5, ENABLE); /* Enable I2S DMA request for TX */ SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE); /* Enable the I2S cell */ I2S_Cmd(SPI2, ENABLE); } /* Wait till the TC flag is ON (direct register access to optimize time) */ while (((DMA1->ISR & (uint32_t)0x00020000) == 0)) {} /* Clear All DMA1 channel 5 flags */ DMA_ClearFlag(DMA1_FLAG_GL5); } }
/** * @brief Starts playing audio stream from the audio Media. * @param None * @retval None */ void Audio_MAL_Play(uint32_t Addr, uint32_t Size) { if (CurrAudioInterface == AUDIO_INTERFACE_I2S) { /* Configure the buffer address and size */ DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)Addr; DMA_InitStructure.DMA_BufferSize = (uint32_t)Size/2; /* Configure the DMA Stream with the new parameters */ DMA_Init(AUDIO_MAL_DMA_STREAM, &DMA_InitStructure); /* Enable the I2S DMA Stream*/ DMA_Cmd(AUDIO_MAL_DMA_STREAM, ENABLE); } #ifndef DAC_USE_I2S_DMA else { /* Configure the buffer address and size */ DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)Addr; DMA_InitStructure.DMA_BufferSize = (uint32_t)Size; /* Configure the DMA Stream with the new parameters */ DMA_Init(AUDIO_MAL_DMA_STREAM, &DMA_InitStructure); /* Enable the I2S DMA Stream*/ DMA_Cmd(AUDIO_MAL_DMA_STREAM, ENABLE); } #endif /* DAC_USE_I2S_DMA */ /* If the I2S peripheral is still not enabled, enable it */ if ((CODEC_I2S->I2SCFGR & I2S_ENABLE_MASK) == 0) { I2S_Cmd(CODEC_I2S, ENABLE); } }
/** * @brief Pauses or Resumes the audio stream playing from the Media. * @param Cmd: AUDIO_PAUSE (or 0) to pause, AUDIO_RESUME (or any value different * from 0) to resume. * @param Addr: Address from/at which the audio stream should resume/pause. * @retval None */ static void Audio_MAL_PauseResume(uint32_t Cmd, uint32_t Addr) { /* Pause the audio file playing */ if (Cmd == AUDIO_PAUSE) { /* Disable the I2S DMA request */ SPI_I2S_DMACmd(CODEC_I2S, SPI_I2S_DMAReq_Tx, DISABLE); /* Pause the I2S DMA Stream Note. For the STM32F40x devices, the DMA implements a pause feature, by disabling the stream, all configuration is preserved and data transfer is paused till the next enable of the stream. This feature is not available on STM32F40x devices. */ DMA_Cmd(AUDIO_MAL_DMA_STREAM, DISABLE); } else /* AUDIO_RESUME */ { /* Enable the I2S DMA request */ SPI_I2S_DMACmd(CODEC_I2S, SPI_I2S_DMAReq_Tx, ENABLE); /* Resume the I2S DMA Stream Note. For the STM32F40x devices, the DMA implements a pause feature, by disabling the stream, all configuration is preserved and data transfer is paused till the next enable of the stream. This feature is not available on STM32F40x devices. */ DMA_Cmd(AUDIO_MAL_DMA_STREAM, ENABLE); /* If the I2S peripheral is still not enabled, enable it */ if ((CODEC_I2S->I2SCFGR & I2S_ENABLE_MASK) == 0) { I2S_Cmd(CODEC_I2S, ENABLE); } } }
/******************************************************************************* * Function Name : I2S_Config * Description : Configure the I2S Peripheral. * Input : - Standard: I2S_Standard_Phillips, I2S_Standard_MSB or I2S_Standard_LSB * - MCLKOutput: I2S_MCLKOutput_Enable or I2S_MCLKOutput_Disable * - AudioFreq: I2S_AudioFreq_8K, I2S_AudioFreq_16K, I2S_AudioFreq_22K, * I2S_AudioFreq_44K or I2S_AudioFreq_48K * Output : None * Return : None *******************************************************************************/ static void I2S_Config(uint16_t Standard, uint16_t MCLKOutput, uint16_t AudioFreq) { I2S_InitTypeDef I2S_InitStructure; /* Enable I2S2 APB1 clock */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); /* Deinitialize SPI2 peripheral */ SPI_I2S_DeInit(SPI2); /* I2S2 peripheral configuration */ I2S_InitStructure.I2S_Mode = I2S_Mode_MasterTx; I2S_InitStructure.I2S_Standard = Standard; I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16b; I2S_InitStructure.I2S_MCLKOutput = MCLKOutput; I2S_InitStructure.I2S_AudioFreq = AudioFreq; I2S_InitStructure.I2S_CPOL = I2S_CPOL_High; I2S_Init(SPI2, &I2S_InitStructure); /* Disable the I2S2 TXE Interrupt */ SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_TXE, DISABLE); /* Enable the SPI2/I2S2 peripheral */ I2S_Cmd(SPI2, ENABLE); printf("\n\r I2S peripheral Config finished"); }
/** * @brief I2S_Stop 停止iis总线 * @param none * @retval none */ void I2S_Stop(void) { /* 禁能 SPI2/I2S2 外设 */ //SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, DISABLE); I2S_Cmd(SPI2, DISABLE); DMA_Cmd(DMA1_Channel5, DISABLE); }
/******************************************************************************* * Function Name : INTR_SOFINTR_Callback * Description : Start of frame callback function. * Input : None. * Output : None. * Return : None. *******************************************************************************/ void INTR_SOFINTR_Callback(void) { static __IO uint32_t EmptyFrameCounter = 0; /* If frame hasn't changed and the DMA is enabled */ if (IsocBufferIdx == PrevFrame) { /* Empty packet state */ EmptyFrameCounter++; } else { /* Update status */ PrevFrame = IsocBufferIdx; /* Streaming Active state */ EmptyFrameCounter = 0; } /* Stream Inactive state */ if (EmptyFrameCounter == 5) { /* Mute the audio codec to avoid spurious noise */ CODEC_Mute(MUTE_ON); /* Disable the I2S and the DMA request */ SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, DISABLE); I2S_Cmd(SPI2, DISABLE); /* Disable the DMA channel and clear all its flags*/ DMA1_Channel5->CCR &= 0xFFFFFFFE; DMA_ClearFlag(DMA1_FLAG_GL5); /* Enable the I2S interrupt to continue generating the clocks for the audio codec otherwise there will be a noise on the line when no file is played */ SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_TXE, ENABLE); I2S_Cmd(SPI2, ENABLE); /* Reset counters */ IsocBufferIdx = 0; PrevFrame = 0; /* Idle state */ EmptyFrameCounter ++; } }
static rt_err_t codec_open(rt_device_t dev, rt_uint16_t oflag) { #if !CODEC_MASTER_MODE /* enable I2S */ I2S_Cmd(CODEC_I2S_PORT, ENABLE); #endif return RT_EOK; }
/******************************************************************************* * Function Name : EP1_OUT_Callback * Description : Endpoint 1 out callback routine. * Input : None. * Output : None. * Return : None. *******************************************************************************/ void EP1_OUT_Callback(void) { DMA_InitTypeDef DMA_InitStructure; #ifdef USE_STM3210C_EVAL /* Get the Endpoint descriptor pointer */ ep = PCD_GetOutEP(ENDP1 & 0x7F); /* Enable the Endpoint transfer (since the the Read Endpoint function is not called) */ OTGD_FS_EPStartXfer(ep); /* Toggle the data PID */ if (ep->even_odd_frame != 0) { ep->even_odd_frame = 0; } else { ep->even_odd_frame = 1; } /* If Half of global buffer has been filled and DMA is still not enabled, Re-configure the DMA and unMute the codec */ #if (NUM_SUB_BUFFERS == 2) if (((DMA1_Channel5->CCR & 0x1) == 0) && (IsocBufferIdx == 1)) #else if (((DMA1_Channel5->CCR & 0x1) == 0) && (IsocBufferIdx == ((NUM_SUB_BUFFERS / 2) - 1))) #endif /* NUM_SUB_BUFFERS */ { /* Disable the mute mode */ CODEC_Mute(MUTE_OFF); /* Disable the I2S before starting configuration to avoid spurious transfer */ SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_TXE, DISABLE); I2S_Cmd(SPI2, DISABLE); /* Initialize the DMA1 Channel5 to its default values */ DMA_DeInit(DMA1_Channel5); /* Configure the DMA parameters */ DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)((uint16_t*)IsocBuff); DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)SPI2_DR_Address; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_BufferSize = (ISOC_BUFFER_SZE * NUM_SUB_BUFFERS) / 2; /* Divided by 2 because USB data are 8 bit and I2S buffer is 16 bit */ 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_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel5, &DMA_InitStructure); } #endif /* USE_STM3210C_EVAL */ }
//??????????? void Audio_MAL_Play(u32 Addr, u32 Size) { DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Addr;//?????????? DMA_InitStructure.DMA_BufferSize = (uint32_t)Size/2; DMA_Init(DMA1_Channel5, &DMA_InitStructure); DMA_Cmd(DMA1_Channel5, ENABLE);//I2S DMA?? if ((SPI2->I2SCFGR & I2S_ENABLE_MASK) == 0) I2S_Cmd(SPI2, ENABLE);//?I2S?????,??? }
/** * @brief Restores the Audio Codec audio interface to its default state. * @param None. * @retval None. */ static void Codec_AudioInterface_DeInit(void) { /* Disable the CODEC_I2S peripheral (in case it hasn't already been disabled) */ I2S_Cmd(CODEC_I2S, DISABLE); /* Deinitialize the CODEC_I2S peripheral */ SPI_I2S_DeInit(CODEC_I2S); /* Disable the CODEC_I2S peripheral clock */ RCC_APB1PeriphClockCmd(CODEC_I2S_CLK, DISABLE); }
/******************************************************************************* * Function Name : I2S_Config * Description : Initializes the I2S peripheral. * Input : None * Output : None * Return : None *******************************************************************************/ static void I2S_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; I2S_InitTypeDef I2S_InitStructure; /* Enable GPIOB, GPIOC and AFIO clock */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE); /* I2S2 SD, CK and WS pins configuration */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_15; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOB, &GPIO_InitStructure); /* I2S2 MCK pin configuration */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; GPIO_Init(GPIOC, &GPIO_InitStructure); /* Enable I2S2 APB1 clock */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); /* Deinitialize SPI2 peripheral */ SPI_I2S_DeInit(SPI2); /* I2S2 peripheral configuration */ I2S_InitStructure.I2S_Mode = I2S_Mode_MasterTx; I2S_InitStructure.I2S_Standard = I2S_Standard_Phillips; I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16b; I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Enable; #ifdef AUDIO_FREQ_96K I2S_InitStructure.I2S_AudioFreq = I2S_AudioFreq_96k; #elif defined (AUDIO_FREQ_48K) I2S_InitStructure.I2S_AudioFreq = I2S_AudioFreq_48k; #elif defined (AUDIO_FREQ_44K) I2S_InitStructure.I2S_AudioFreq = I2S_AudioFreq_44k; #elif defined (AUDIO_FREQ_32K) I2S_InitStructure.I2S_AudioFreq = I2S_AudioFreq_32k; #elif defined (AUDIO_FREQ_22K) I2S_InitStructure.I2S_AudioFreq = I2S_AudioFreq_22k; #elif defined (AUDIO_FREQ_16K) I2S_InitStructure.I2S_AudioFreq = I2S_AudioFreq_16k; #elif defined (AUDIO_FREQ_11K) I2S_InitStructure.I2S_AudioFreq = I2S_AudioFreq_11k; #elif defined (AUDIO_FREQ_8K) I2S_InitStructure.I2S_AudioFreq = I2S_AudioFreq_8k; #endif /* AUDIO_FREQ_96K */ I2S_InitStructure.I2S_CPOL = I2S_CPOL_Low; I2S_Init(SPI2, &I2S_InitStructure); /* Enable the SPI2/I2S2 peripheral */ I2S_Cmd(SPI2, ENABLE); }
/** * @brief I2S_Bus_Init 初始化iis总线 * @param none * @retval none */ void I2S_Bus_Init(void) { /* 配置I2S GPIO用到的引脚 */ I2S_GPIO_Config(); /* 配置I2S工作模式 */ I2S_Mode_Config(); I2S_Cmd(SPI2, DISABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); }
/** * @brief Stops audio stream playing on the used Media. * @param None * @retval None */ static void Audio_MAL_Stop(void) { /* Stop the Transfer on the I2S side: Stop and disable the DMA channel */ DMA_Cmd(AUDIO_MAL_DMA_CHANNEL, DISABLE); /* Clear all the DMA flags for the next transfer */ DMA_ClearFlag(AUDIO_MAL_DMA_FLAG_TC |AUDIO_MAL_DMA_FLAG_HT | AUDIO_MAL_DMA_FLAG_TE); /* The I2S DMA requests are not disabled here. */ /* In all modes, disable the I2S peripheral */ I2S_Cmd(CODEC_I2S, DISABLE); }
/** * @brief Starts playing audio stream from the audio Media. * @param Addr: Pointer to the audio stream buffer * @param Size: Number of data in the audio stream buffer * @retval None. */ void Audio_MAL_Play(uint32_t Addr, uint32_t Size) { #ifndef AUDIO_USE_MACROS /* Enable the I2S DMA Stream*/ DMA_Cmd(AUDIO_MAL_DMA_STREAM, DISABLE); /* Clear the Interrupt flag */ DMA_ClearFlag(AUDIO_MAL_DMA_STREAM, AUDIO_MAL_DMA_FLAG_TC); /* Wait the DMA Stream to be effectively disabled */ while (DMA_GetCmdStatus(AUDIO_MAL_DMA_STREAM) != DISABLE) {} /* Configure the buffer address and size */ DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)Addr; DMA_InitStructure.DMA_BufferSize = (uint32_t)(Size*2); /* Configure the DMA Stream with the new parameters */ DMA_Init(AUDIO_MAL_DMA_STREAM, &DMA_InitStructure); /* Enable the I2S DMA Stream*/ DMA_Cmd(AUDIO_MAL_DMA_STREAM, ENABLE); /* If the I2S peripheral is still not enabled, enable it */ if ((CODEC_I2S->I2SCFGR & I2S_ENABLE_MASK) == 0) { I2S_Cmd(CODEC_I2S, ENABLE); } #else /* Disable the I2S DMA Stream*/ AUDIO_MAL_DMA_STREAM->CR &= ~(uint32_t)DMA_SxCR_EN; /* Clear the Interrupt flag */ AUDIO_MAL_DMA->AUDIO_MAL_DMA_IFCR = (uint32_t)(AUDIO_MAL_DMA_FLAG_TC & 0x0F7D0F7D); /* Wait the DMA Stream to be effectively disabled */ while ((AUDIO_MAL_DMA_STREAM->CR & (uint32_t)DMA_SxCR_EN) != 0) {} /* Configure the buffer address and size */ AUDIO_MAL_DMA_STREAM->M0AR = (uint32_t)Addr; AUDIO_MAL_DMA_STREAM->NDTR = (uint32_t)(Size*2); /* Enable the I2S DMA Stream*/ AUDIO_MAL_DMA_STREAM->CR |= (uint32_t)DMA_SxCR_EN; /* If the I2S peripheral is still not enabled, enable it */ CODEC_I2S->I2SCFGR |= SPI_I2SCFGR_I2SE; #endif /* AUDIO_USE_MACROS */ }
void Codec_AudioInterface_Init(uint32_t AudioFreq) { //Setup I2C comms to codec Codec_GPIO_Init(); I2C_Cntrl_Init(); //Bring Up Codec via the I2C comms Codec_Init(); //Invoke I2S Pin connections I2S_GPIO_Init(); //Now, get down to defining I2S, Full Duplex, Codec Master Configuration I2S_InitTypeDef I2S_InitStructure; /* Enable the CODEC_I2S peripheral clock */ RCC_APB1PeriphClockCmd(CODEC_I2S_CLK, ENABLE); /* CODEC_I2S peripheral configuration */ I2S_InitStructure.I2S_AudioFreq = AudioFreq; I2S_InitStructure.I2S_Standard = I2S_Standard_MSB; I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16b; I2S_InitStructure.I2S_CPOL = I2S_CPOL_Low; I2S_InitStructure.I2S_Mode = I2S_Mode_SlaveTx; I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Disable; /* Initialize the I2S peripheral with the structure above */ I2S_Init(CODEC_I2S, &I2S_InitStructure); I2S_FullDuplexConfig(I2S3ext, &I2S_InitStructure); //Turn on the I2S interface I2S_Cmd(CODEC_I2S, ENABLE); I2S_Cmd(I2S3ext, ENABLE); }
/** * @brief I2S_Freq_Config 根据采样频率配置iis总线,在播放音频文件时可从文件中解码获取 * @param SampleFreq 采样频率 * @retval none */ void I2S_Freq_Config(uint16_t SampleFreq) { I2S_InitTypeDef I2S_InitStructure; I2S_Stop(); I2S_InitStructure.I2S_Mode = I2S_Mode_MasterTx; // 配置I2S工作模式 I2S_InitStructure.I2S_Standard = I2S_Standard_LSB; // 接口标准 I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16b; // 数据格式,16bit I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Enable; // 主时钟模式 I2S_InitStructure.I2S_AudioFreq = SampleFreq; // 音频采样频率 I2S_InitStructure.I2S_CPOL = I2S_CPOL_Low; I2S_Init(SPI2, &I2S_InitStructure); I2S_Cmd(SPI2, ENABLE); //使能iis总线 }
/** * @brief Stop audio recording * @param None * @retval None */ uint32_t MicListenerStop(void) { /* Check if the interface has already been initialized */ if (AudioMicInited) { /* Stop conversion */ I2S_Cmd(SPI2, DISABLE); /* Return 0 if all operations are OK */ return 0; } else { /* Cannot perform operation */ return 1; } }
//参数I2S_Standard: @ref SPI_I2S_Standard I2S标准, //I2S_Standard_Phillips,飞利浦标准; //I2S_Standard_MSB,MSB对齐标准(右对齐); //I2S_Standard_LSB,LSB对齐标准(左对齐); //I2S_Standard_PCMShort,I2S_Standard_PCMLong:PCM标准 //参数I2S_Mode: @ref SPI_I2S_Mode I2S_Mode_SlaveTx:从机发送;I2S_Mode_SlaveRx:从机接收;I2S_Mode_MasterTx:主机发送;I2S_Mode_MasterRx:主机接收; //参数I2S_Clock_Polarity @ref SPI_I2S_Clock_Polarity: I2S_CPOL_Low,时钟低电平有效;I2S_CPOL_High,时钟高电平有效 //参数I2S_DataFormat: @ref SPI_I2S_Data_Format :数据长度,I2S_DataFormat_16b,16位标准;I2S_DataFormat_16bextended,16位扩展(frame=32bit);I2S_DataFormat_24b,24位;I2S_DataFormat_32b,32位. void I2S2_Init(u16 I2S_Standard,u16 I2S_Mode,u16 I2S_Clock_Polarity,u16 I2S_DataFormat) { I2S_InitTypeDef I2S_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);//使能SPI2时钟 RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2,ENABLE); //复位SPI2 RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2,DISABLE);//结束复位 I2S_InitStructure.I2S_Mode=I2S_Mode;//IIS模式 I2S_InitStructure.I2S_Standard=I2S_Standard;//IIS标准 I2S_InitStructure.I2S_DataFormat=I2S_DataFormat;//IIS数据长度 I2S_InitStructure.I2S_MCLKOutput=I2S_MCLKOutput_Disable;//主时钟输出禁止 I2S_InitStructure.I2S_AudioFreq=I2S_AudioFreq_Default;//IIS频率设置 I2S_InitStructure.I2S_CPOL=I2S_Clock_Polarity;//空闲状态时钟电平 I2S_Init(SPI2,&I2S_InitStructure);//初始化IIS SPI_I2S_DMACmd(SPI2,SPI_I2S_DMAReq_Tx,ENABLE);//SPI2 TX DMA请求使能. I2S_Cmd(SPI2,ENABLE);//SPI2 I2S EN使能. }
/** * @brief Starts playing audio stream from the audio Media. * @param None * @retval None */ static void Audio_MAL_Play(uint32_t Addr, uint32_t Size) { #ifndef I2S_INTERRUPT if (CurrAudioInterface == AUDIO_INTERFACE_I2S) { /* Configure the buffer address and size */ DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) Addr; DMA_InitStructure.DMA_BufferSize = (uint32_t) Size; /* Configure the DMA Channel with the new parameters */ DMA_Init(AUDIO_MAL_DMA_CHANNEL, &DMA_InitStructure); /* Enable the I2S DMA Channel */ DMA_Cmd(AUDIO_MAL_DMA_CHANNEL, ENABLE); } #else /* If the I2S peripheral is still not enabled, enable it */ if ((CODEC_I2S->I2SCFGR & I2S_ENABLE_MASK) == 0) { I2S_Cmd(CODEC_I2S, ENABLE); } #endif /* I2S_INTERRUPT */ }
void audioInit() { I2S_InitTypeDef I2S_InitStructure; Audio_GPIO_Init(); /*CONFIG the I2S_RCC ,MUST before enabling the I2S APB clock*/ //PLLI2SN 302,PLLI2SR 2,I2SDIV 53,I2SODD 1,FS 44.1KHZ,16bit,Error 0.0011% RCC_PLLI2SConfig(302,2); RCC_PLLI2SCmd(ENABLE); RCC_I2SCLKConfig(RCC_I2S2CLKSource_PLLI2S); /* Enable the CODEC_I2S peripheral clock */ RCC_APB1PeriphClockCmd(CODEC_I2S_CLK, ENABLE); /* CODEC_I2S peripheral configuration */ SPI_I2S_DeInit(CODEC_I2S); 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;//clk 0 when idle state I2S_InitStructure.I2S_Mode = I2S_Mode_MasterTx; #ifdef CODEC_MCLK_ENABLED I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Enable; #elif defined(CODEC_MCLK_DISABLED) I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Disable; #else #error "No selection for the MCLK output has been defined !" #endif /* CODEC_MCLK_ENABLED */ /* Initialize the I2S peripheral with the structure above */ I2S_Init(CODEC_I2S, &I2S_InitStructure); I2S_Cmd(CODEC_I2S, ENABLE); //interrupt #ifdef CODEC_USE_INT SPI_I2S_ITConfig(CODEC_I2S,SPI_I2S_IT_TXE,ENABLE); #elif defined(CODEC_USE_DMA) #error "DMA is not initialized" #endif }
/** * @brief Start audio recording * @param pbuf: pointer to a buffer * @retval None */ uint8_t WaveRecorderStart(uint16_t* pbuf) { /* Check if the interface has already been initialized */ if (AudioRecInited) { /* Store the location and size of the audio buffer */ pAudioRecBuf = pbuf; /* Enable the Rx buffer not empty interrupt */ SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_RXNE, ENABLE); /* The Data transfer is performed in the SPI interrupt routine */ /* Enable the SPI peripheral */ I2S_Cmd(SPI2, ENABLE); /* Return 0 if all operations are OK */ return 0; } else { /* Cannot perform operation */ return 1; } }
/** * @brief Pauses or Resumes the audio stream playing from the Media. * @param Cmd: AUDIO_PAUSE (or 0) to pause, AUDIO_RESUME (or any value different * from 0) to resume. * @param Addr: Address from/at which the audio stream should resume/pause. * @param Size: Number of data to be configured for next resume. * @retval None. */ void Audio_MAL_PauseResume(uint32_t Cmd, uint32_t Addr, uint32_t Size) { /* Pause the audio file playing */ if (Cmd == AUDIO_PAUSE) { /* Stop the current DMA request by resetting the I2S cell */ Codec_AudioInterface_DeInit(); /* Re-configure the I2S interface for the next resume operation */ Codec_AudioInterface_Init(I2S_InitStructure.I2S_AudioFreq); /* Disable the DMA Stream */ DMA_Cmd(AUDIO_MAL_DMA_CHANNEL, DISABLE); /* Clear the Interrupt flag */ DMA_ClearFlag(AUDIO_MAL_DMA_FLAG_ALL); } else /* AUDIO_RESUME */ { /* Configure the buffer address and size */ DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Addr; DMA_InitStructure.DMA_BufferSize = (uint32_t)(Size*2); /* Configure the DMA Stream with the new parameters */ DMA_Init(AUDIO_MAL_DMA_CHANNEL, &DMA_InitStructure); /* Enable the I2S DMA Stream*/ DMA_Cmd(AUDIO_MAL_DMA_CHANNEL, ENABLE); /* If the I2S peripheral is still not enabled, enable it */ if ((CODEC_I2S->I2SCFGR & I2S_ENABLE_MASK) == 0) { I2S_Cmd(CODEC_I2S, ENABLE); } } }
/** * @brief Starts playing audio stream from the audio Media. * @param Addr: Pointer to the audio stream buffer * @param Size: Number of data in the audio stream buffer * @retval None. */ void Audio_MAL_Play(uint32_t Addr, uint32_t Size) { /* Enable the I2S DMA Stream*/ DMA_Cmd(AUDIO_MAL_DMA_CHANNEL, DISABLE); /* Clear the Interrupt flag */ DMA_ClearFlag(AUDIO_MAL_DMA_FLAG_TC); /* Configure the buffer address and size */ DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Addr; DMA_InitStructure.DMA_BufferSize = (uint32_t)(Size*2); /* Configure the DMA Stream with the new parameters */ DMA_Init(AUDIO_MAL_DMA_CHANNEL, &DMA_InitStructure); /* Enable the I2S DMA Stream*/ DMA_Cmd(AUDIO_MAL_DMA_CHANNEL, ENABLE); /* If the I2S peripheral is still not enabled, enable it */ if ((CODEC_I2S->I2SCFGR & I2S_ENABLE_MASK) == 0) { I2S_Cmd(CODEC_I2S, ENABLE); } }
/** * @brief Options control function. * @param cmd: pointer to the command/option buffer. * @param size: Size of the command/option buffer. * @retval Value of the current audio sampling rate. */ static uint32_t OptionCtrl (uint8_t* cmd, uint32_t size) { uint32_t freq = 48000; /* Decode the audio frequency */ freq = (uint32_t)(*(uint8_t*)(cmd) | (*(uint8_t*)(cmd + 1) << 8) | (*(uint8_t*)(cmd + 2) << 16)); /* Check ff the requested audio frequency is not supported */ if ((freq > MAX_AUDIO_FREQ) || (freq < MIN_AUDIO_FREQ)) { /* Set the default audio frequency */ freq = DEFAULT_OUT_AUDIO_FREQ; } #ifdef USE_SYNCHRONIZATION /* If the external clock is used, reconfigure the clock synthesizer sub-system */ AUDIO_CORR_Out_Update(freq, 0, 0, 0); #endif /* USE_SYNCHRONIZATION */ /* If the I2S peripheral is still not enabled, enable it */ I2S_Cmd(CODEC_I2S, ENABLE); return freq; }
void CS43L22_Config() { // configure STM32F4Discovery I2S pins RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_StructInit(&GPIO_InitStructure); GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Pin = STM32F4D_I2S_WS_PIN; GPIO_Init(STM32F4D_I2S_WS_PORT, &GPIO_InitStructure); GPIO_PinAFConfig(STM32F4D_I2S_WS_PORT, STM32F4D_I2S_WS_PINSRC, GPIO_AF_SPI3); GPIO_InitStructure.GPIO_Pin = STM32F4D_I2S_CK_PIN; GPIO_Init(STM32F4D_I2S_CK_PORT, &GPIO_InitStructure); GPIO_PinAFConfig(STM32F4D_I2S_CK_PORT, STM32F4D_I2S_CK_PINSRC, GPIO_AF_SPI3); GPIO_InitStructure.GPIO_Pin = STM32F4D_I2S_SD_PIN; GPIO_Init(STM32F4D_I2S_SD_PORT, &GPIO_InitStructure); GPIO_PinAFConfig(STM32F4D_I2S_SD_PORT, STM32F4D_I2S_SD_PINSRC, GPIO_AF_SPI3); GPIO_InitStructure.GPIO_Pin = STM32F4D_I2S_MCLK_PIN; GPIO_Init(STM32F4D_I2S_MCLK_PORT, &GPIO_InitStructure); GPIO_PinAFConfig(STM32F4D_I2S_MCLK_PORT, STM32F4D_I2S_MCLK_PINSRC, GPIO_AF_SPI3); // configure I2C pins to access the CS43L22 configuration registers GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Pin = CODEC_I2C_SCL_PIN; GPIO_Init(CODEC_I2C_SCL_PORT, &GPIO_InitStructure); GPIO_PinAFConfig(CODEC_I2C_SCL_PORT, GPIO_PinSource6, GPIO_AF_I2C1); GPIO_InitStructure.GPIO_Pin = CODEC_I2C_SDA_PIN; GPIO_Init(CODEC_I2C_SDA_PORT, &GPIO_InitStructure); GPIO_PinAFConfig(CODEC_I2C_SDA_PORT, GPIO_PinSource9, GPIO_AF_I2C1); // CS43L22 reset pin GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Pin = CODEC_RESET_PIN; GPIO_Init(CODEC_RESET_PORT, &GPIO_InitStructure); GPIO_ResetBits(CODEC_RESET_PORT, CODEC_RESET_PIN); // activate reset // I2S initialisation RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE); RCC_PLLI2SCmd(ENABLE); // new for STM32F4: enable I2S PLL SPI_I2S_DeInit(SPI3); I2S_InitTypeDef I2S_InitStructure; I2S_StructInit(&I2S_InitStructure); I2S_InitStructure.I2S_Standard = STM32F4D_I2S_STANDARD; I2S_InitStructure.I2S_DataFormat = STM32F4D_I2S_DATA_FORMAT; I2S_InitStructure.I2S_MCLKOutput = STM32F4D_I2S_MCLK_ENABLE ? I2S_MCLKOutput_Enable : I2S_MCLKOutput_Disable; I2S_InitStructure.I2S_AudioFreq = (u16)(STM32F4D_I2S_AUDIO_FREQ); I2S_InitStructure.I2S_CPOL = I2S_CPOL_Low; // configuration required as well? I2S_InitStructure.I2S_Mode = I2S_Mode_MasterTx; I2S_Init(SPI3, &I2S_InitStructure); I2S_Cmd(SPI3, ENABLE); // DMA Configuration for SPI Tx Event RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE); DMA_InitTypeDef DMA_InitStructure; DMA_StructInit(&DMA_InitStructure); DMA_Cmd(DMA1_Stream5, DISABLE); DMA_ClearFlag(DMA1_Stream5, DMA_FLAG_TCIF5 | DMA_FLAG_TEIF5 | DMA_FLAG_HTIF5 | DMA_FLAG_FEIF5); DMA_InitStructure.DMA_Channel = DMA_Channel_0; DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&SPI3->DR; // DMA_InitStructure.DMA_MemoryBaseAddr = ...; // configured in CS43L22_Start DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; // DMA_InitStructure.DMA_BufferSize = ...; // configured in CS43L22_Start 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_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_Init(DMA1_Stream5, &DMA_InitStructure); // DMA_Cmd(DMA1_Stream5, ENABLE); // done on CS43L22_Start DMA_ITConfig(DMA1_Stream5, DMA_IT_TE | DMA_IT_FE, DISABLE); // trigger interrupt when transfer half complete/complete DMA_ITConfig(DMA1_Stream5, DMA_IT_HT | DMA_IT_TC, ENABLE); // enable SPI interrupts to DMA SPI_I2S_DMACmd(SPI3, SPI_I2S_DMAReq_Tx, ENABLE); // Configure and enable DMA interrupt /* Configure the DMA IRQ handler priority */ NVIC_SetPriority(DMA1_Stream5_IRQn, 0x0); NVIC_EnableIRQ(DMA1_Stream5_IRQn); // configure I2C RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); I2C_DeInit(CODEC_I2C); I2C_InitTypeDef I2C_InitStructure; I2C_StructInit(&I2C_InitStructure); I2C_InitStructure.I2C_ClockSpeed = 100000; I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; I2C_InitStructure.I2C_OwnAddress1 = CORE_I2C_ADDRESS; I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; I2C_Cmd(CODEC_I2C, ENABLE); I2C_Init(CODEC_I2C, &I2C_InitStructure); codec_init(); }
void codec_dma_isr(void) { /* switch to next buffer */ rt_uint16_t next_index; void* data_ptr; next_index = codec.read_index + 1; if (next_index >= DATA_NODE_MAX) next_index = 0; /* save current data pointer */ data_ptr = codec.data_list[codec.read_index].data_ptr; #if !CODEC_MASTER_MODE if (codec_sr_new) { I2S_Configuration(codec_sr_new); I2S_Cmd(CODEC_I2S_PORT, ENABLE); codec_sr_new = 0; } #endif codec.read_index = next_index; if (next_index != codec.put_index) { /* enable next dma request */ DMA_Configuration((rt_uint32_t) codec.data_list[codec.read_index].data_ptr, codec.data_list[codec.read_index].data_size); #if CODEC_MASTER_MODE if ((r06 & MS) == 0) { CODEC_I2S_PORT->I2SCFGR |= SPI_I2SCFGR_I2SE; r06 |= MS; codec_send(r06); } #endif } else { #if CODEC_MASTER_MODE if (r06 & MS) { CODEC_I2S_DMA->CCR &= ~DMA_CCR1_EN; while ((CODEC_I2S_PORT->SR & SPI_I2S_FLAG_TXE) == 0); while ((CODEC_I2S_PORT->SR & SPI_I2S_FLAG_BSY) != 0); CODEC_I2S_PORT->I2SCFGR &= ~SPI_I2SCFGR_I2SE; r06 &= ~MS; codec_send(r06); } #endif rt_kprintf("*\n"); } /* notify transmitted complete. */ if (codec.parent.tx_complete != RT_NULL) { codec.parent.tx_complete(&codec.parent, data_ptr); } }