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); } }
/////////////////////////////////////////////////////////////////////////////// ////! 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); }
/** * @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; }
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_init() { GPIO_InitTypeDef PinInitStruct; GPIO_StructInit(&PinInitStruct); I2S_InitTypeDef I2S_InitType; I2C_InitTypeDef I2C_InitType; //Reset pin as GPIO PinInitStruct.GPIO_Pin = CODEC_RESET_PIN; PinInitStruct.GPIO_Mode = GPIO_Mode_OUT; PinInitStruct.GPIO_PuPd = GPIO_PuPd_DOWN; PinInitStruct.GPIO_OType = GPIO_OType_PP; PinInitStruct.GPIO_Speed = GPIO_Speed_50MHz; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOB, ENABLE); GPIO_Init(GPIOD, &PinInitStruct); // I2C pins PinInitStruct.GPIO_Mode = GPIO_Mode_AF; PinInitStruct.GPIO_OType = GPIO_OType_OD; PinInitStruct.GPIO_Pin = I2C_SCL_PIN | I2C_SDA_PIN; PinInitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; PinInitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &PinInitStruct); GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1); GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_I2C1); //enable I2S and I2C clocks //RCC_I2SCLKConfig(RCC_I2S2CLKSource_PLLI2S); RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1 | RCC_APB1Periph_SPI3, ENABLE); RCC_PLLI2SCmd(ENABLE); // I2S pins PinInitStruct.GPIO_OType = GPIO_OType_PP; PinInitStruct.GPIO_Pin = I2S3_SCLK_PIN | I2S3_SD_PIN | I2S3_MCLK_PIN; GPIO_Init(GPIOC, &PinInitStruct); PinInitStruct.GPIO_Pin = I2S3_WS_PIN; GPIO_Init(GPIOA, &PinInitStruct); //prepare output ports for alternate function GPIO_PinAFConfig(GPIOA, GPIO_PinSource4, GPIO_AF_SPI3); GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_SPI3); GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_SPI3); GPIO_PinAFConfig(GPIOC, GPIO_PinSource12, GPIO_AF_SPI3); //keep Codec off for now GPIO_ResetBits(GPIOD, CODEC_RESET_PIN); // configure I2S port SPI_I2S_DeInit(CODEC_I2S); I2S_InitType.I2S_AudioFreq = I2S_AudioFreq_11k; // <-- tutaj zmienione I2S_InitType.I2S_MCLKOutput = I2S_MCLKOutput_Enable; I2S_InitType.I2S_DataFormat = I2S_DataFormat_16b; // <-- nie zmienioone, ale dlatego nie trzeba zmniejszac wartosci na 12 bitow I2S_InitType.I2S_Mode = I2S_Mode_MasterTx; I2S_InitType.I2S_Standard = I2S_Standard_Phillips; I2S_InitType.I2S_CPOL = I2S_CPOL_Low; I2S_Init(CODEC_I2S, &I2S_InitType); I2S_Cmd(CODEC_I2S, ENABLE); // configure I2C port I2C_DeInit(CODEC_I2C); I2C_InitType.I2C_ClockSpeed = 100000; I2C_InitType.I2C_Mode = I2C_Mode_I2C; I2C_InitType.I2C_OwnAddress1 = CORE_I2C_ADDRESS; I2C_InitType.I2C_Ack = I2C_Ack_Enable; I2C_InitType.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; I2C_InitType.I2C_DutyCycle = I2C_DutyCycle_2; I2C_Cmd(CODEC_I2C, ENABLE); I2C_Init(CODEC_I2C, &I2C_InitType); }