/////////////////////////////////////////////////////////////////////////////// ////! Starts DMA driven I2S transfers ////! \param[in] *buffer pointer to sample buffer (contains L/R halfword) ////! \param[in] len size of audio buffer /////////////////////////////////////////////////////////////////////////////// void CS43L22_Start(u32 *buffer, u16 len) { // start I2S DMA transfers RCC_PLLI2SCmd(DISABLE); #ifndef OVERCLOCK RCC_PLLI2SConfig((uint32_t)214,(uint32_t)2); //I2S PLL dividers for 38009 calculated from stm32f407 datasheet!!! #else // RCC_PLLI2SConfig((uint32_t)198,(uint32_t)2); //I2S PLL dividers for 43010 calculated from stm32f407 datasheet!!! RCC_PLLI2SConfig((uint32_t)258,(uint32_t)3); //I2S PLL dividers for 48000 from stm32f407 datasheet!!! #endif CS43L22_Config(); // reload DMA source address and counter DMA_Cmd(DMA1_Stream5, DISABLE); // ensure that IRQ flag is cleared (so that DMA IRQ isn't invoked by accident while this function is called) DMA_ClearFlag(DMA1_Stream5, DMA_FLAG_TCIF5 | DMA_FLAG_TEIF5 | DMA_FLAG_HTIF5 | DMA_FLAG_FEIF5); // take over new buffer pointer/length DMA1_Stream5->M0AR = (u32)buffer; DMA1_Stream5->NDTR = 2*len; DMA_Cmd(DMA1_Stream5, ENABLE); }
void initClocks() { // enable HSI and set it as the system clock source RCC_HSICmd(ENABLE); while(!(RCC->CR & RCC_CR_HSIRDY)); // wait for it to be ready RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI); // disable PLL and PLLI2S RCC_PLLCmd(DISABLE); RCC_PLLI2SCmd(DISABLE); // disable HSE and CSS (disabling the HSE also disables CSS) RCC_HSEConfig(RCC_HSE_OFF); // Configure PLL values and set source to HSE RCC_PLLConfig( RCC_PLLSource_HSE, DESIRED_PLL_M, DESIRED_PLL_N, DESIRED_PLL_P, DESIRED_PLL_Q ); // set PLL I2S to our new values RCC_PLLI2SConfig( DESIRED_PLL_I2S_N, DESIRED_PLL_I2S_R ); // set I2S clock source to PLLI2S RCC_I2SCLKConfig(RCC_I2S2CLKSource_PLLI2S); // set AHB, APB1, APB2 prescalers RCC_HCLKConfig(DESIRED_HCLK_DIV); RCC_PCLK1Config(DESIRED_PCLK1_DIV); RCC_PCLK2Config(DESIRED_PCKL2_DIV); // enable HSE RCC_HSEConfig(RCC_HSE_ON); if(RCC_WaitForHSEStartUp() == ERROR) RCC_DeInit(); // SHUT DOWN, EVERYTHING! // enable CSS RCC_ClockSecuritySystemCmd(ENABLE); // enable PLL RCC_PLLCmd(ENABLE); while(!(RCC->CR & RCC_CR_PLLRDY)); // wait for ready // enable PLL I2S RCC_PLLI2SCmd(ENABLE); // set system clock source to PLL RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); if(!checkClocks()){ // No actual error reporting done here because we don't want to depend on GPIO etc while(1); } }
/** * @brief Configure PLLSAI. * @param None * @retval None */ void PLLSAI_Config(void) { /* Configure PLLSAI prescalers */ /* PLLSAI_VCO : VCO_429M */ /* SAI_CLK(first level) = PLLSAI_VCO/PLLSAIQ = 429/2 = 214.5 Mhz */ RCC_PLLSAIConfig(429, 2, 4); /* SAI_CLK_x = SAI_CLK(first level)/PLLSAIDIVQ = 214.5/19 = 11.289 Mhz */ RCC_SAIPLLSAIClkDivConfig(19); /* Configure PLLI2S prescalers */ /* PLLI2S_VCO : VCO_344M */ /* SAI_CLK(first level) = PLLI2S_VCO/PLLI2SQ = 344/7 = 49.142 Mhz */ RCC_PLLI2SConfig(344, 7, 4); /* SAI_CLK_x = SAI_CLK(first level)/PLLI2SDIVQ = 49.142/1 = 49.142 Mhz */ RCC_SAIPLLI2SClkDivConfig(1); /* Configure Clock source for SAI Block A */ RCC_SAIBlockACLKConfig(RCC_SAIACLKSource_PLLSAI); /* Configure Clock source for SAI Block B */ RCC_SAIBlockBCLKConfig(RCC_SAIBCLKSource_PLLI2S); /* Enable PLLSAI Clock */ RCC_PLLSAICmd(ENABLE); /* Wait till PLLSAI is ready */ while(RCC_GetFlagStatus(RCC_FLAG_PLLSAIRDY) == RESET) { } /* Enable PLLI2S Clock */ RCC_PLLI2SCmd(ENABLE); /* Wait till PLLI2S is ready */ while(RCC_GetFlagStatus(RCC_FLAG_PLLI2SRDY) == RESET) { } }
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 }
//设置IIS的采样率(@MCKEN) //samplerate:采样率,单位:Hz //返回值:0,设置成功;1,无法设置. u8 I2S2_SampleRate_Set(u32 samplerate) { u8 i=0; u32 tempreg=0; samplerate/=10;//缩小10倍 for(i=0;i<(sizeof(I2S_PSC_TBL)/10);i++)//看看改采样率是否可以支持 { if(samplerate==I2S_PSC_TBL[i][0])break; } RCC_PLLI2SCmd(DISABLE);//先关闭PLLI2S if(i==(sizeof(I2S_PSC_TBL)/10))return 1;//搜遍了也找不到 RCC_PLLI2SConfig((u32)I2S_PSC_TBL[i][1],(u32)I2S_PSC_TBL[i][2]);//设置I2SxCLK的频率(x=2) 设置PLLI2SN PLLI2SR RCC->CR|=1<<26; //开启I2S时钟 while((RCC->CR&1<<27)==0); //等待I2S时钟开启成功. tempreg=I2S_PSC_TBL[i][3]<<0; //设置I2SDIV tempreg|=I2S_PSC_TBL[i][3]<<8; //设置ODD位 tempreg|=1<<9; //使能MCKOE位,输出MCK SPI2->I2SPR=tempreg; //设置I2SPR寄存器 return 0; }