/** * @brief Initializes the SPIx peripheral according to the specified * parameters in the I2S_InitStruct. * @param SPIx: where x can be 1 to select the SPI peripheral (configured in I2S mode). * @param I2S_InitStruct: pointer to an I2S_InitTypeDef structure that * contains the configuration information for the specified SPI peripheral * configured in I2S mode. * @note This function calculates the optimal prescaler needed to obtain the most * accurate audio frequency (depending on the I2S clock source, the PLL values * and the product configuration). But in case the prescaler value is greater * than 511, the default value (0x02) will be configured instead. * @retval None */ void I2S_Init(SPI_TypeDef* SPIx, I2S_InitTypeDef* I2S_InitStruct) { uint16_t tmpreg = 0, i2sdiv = 2, i2sodd = 0, packetlength = 1; uint32_t tmp = 0; RCC_ClocksTypeDef RCC_Clocks; uint32_t sourceclock = 0; /* Check the I2S parameters */ assert_param(IS_SPI_1_PERIPH(SPIx)); assert_param(IS_I2S_MODE(I2S_InitStruct->I2S_Mode)); assert_param(IS_I2S_STANDARD(I2S_InitStruct->I2S_Standard)); assert_param(IS_I2S_DATA_FORMAT(I2S_InitStruct->I2S_DataFormat)); assert_param(IS_I2S_MCLK_OUTPUT(I2S_InitStruct->I2S_MCLKOutput)); assert_param(IS_I2S_AUDIO_FREQ(I2S_InitStruct->I2S_AudioFreq)); assert_param(IS_I2S_CPOL(I2S_InitStruct->I2S_CPOL)); /*----------------------- SPIx I2SCFGR & I2SPR Configuration -----------------*/ /* Clear I2SMOD, I2SE, I2SCFG, PCMSYNC, I2SSTD, CKPOL, DATLEN and CHLEN bits */ SPIx->I2SCFGR &= I2SCFGR_CLEAR_Mask; SPIx->I2SPR = 0x0002; /* Get the I2SCFGR register value */ tmpreg = SPIx->I2SCFGR; /* If the default value has to be written, reinitialize i2sdiv and i2sodd*/ if(I2S_InitStruct->I2S_AudioFreq == I2S_AudioFreq_Default) { i2sodd = (uint16_t)0; i2sdiv = (uint16_t)2; } /* If the requested audio frequency is not the default, compute the prescaler */ else { /* Check the frame length (For the Prescaler computing) */ if(I2S_InitStruct->I2S_DataFormat == I2S_DataFormat_16b) { /* Packet length is 16 bits */ packetlength = 1; } else { /* Packet length is 32 bits */ packetlength = 2; } /* I2S Clock source is System clock: Get System Clock frequency */ RCC_GetClocksFreq(&RCC_Clocks); /* Get the source clock value: based on System Clock value */ sourceclock = RCC_Clocks.SYSCLK_Frequency; /* Compute the Real divider depending on the MCLK output state with a floating point */ if(I2S_InitStruct->I2S_MCLKOutput == I2S_MCLKOutput_Enable) { /* MCLK output is enabled */ tmp = (uint16_t)(((((sourceclock / 256) * 10) / I2S_InitStruct->I2S_AudioFreq)) + 5); } else { /* MCLK output is disabled */ tmp = (uint16_t)(((((sourceclock / (32 * packetlength)) *10 ) / I2S_InitStruct->I2S_AudioFreq)) + 5); } /* Remove the floating point */ tmp = tmp / 10; /* Check the parity of the divider */ i2sodd = (uint16_t)(tmp & (uint16_t)0x0001); /* Compute the i2sdiv prescaler */ i2sdiv = (uint16_t)((tmp - i2sodd) / 2); /* Get the Mask for the Odd bit (SPI_I2SPR[8]) register */ i2sodd = (uint16_t) (i2sodd << 8); } /* Test if the divider is 1 or 0 or greater than 0xFF */ if ((i2sdiv < 2) || (i2sdiv > 0xFF)) { /* Set the default values */ i2sdiv = 2; i2sodd = 0; } /* Write to SPIx I2SPR register the computed value */ SPIx->I2SPR = (uint16_t)(i2sdiv | (uint16_t)(i2sodd | (uint16_t)I2S_InitStruct->I2S_MCLKOutput)); /* Configure the I2S with the SPI_InitStruct values */ tmpreg |= (uint16_t)(SPI_I2SCFGR_I2SMOD | (uint16_t)(I2S_InitStruct->I2S_Mode | \ (uint16_t)(I2S_InitStruct->I2S_Standard | (uint16_t)(I2S_InitStruct->I2S_DataFormat | \ (uint16_t)I2S_InitStruct->I2S_CPOL)))); /* Write to SPIx I2SCFGR */ SPIx->I2SCFGR = tmpreg; }
/** * @brief Initializes the SPIx peripheral according to the specified * parameters in the I2S_InitStruct. * @param SPIx: where x can be 2 or 3 to select the SPI peripheral * (configured in I2S mode). * @param I2S_InitStruct: pointer to an I2S_InitTypeDef structure that * contains the configuration information for the specified SPI peripheral * configured in I2S mode. * @note * The function calculates the optimal prescaler needed to obtain the most * accurate audio frequency (depending on the I2S clock source, the PLL values * and the product configuration). But in case the prescaler value is greater * than 511, the default value (0x02) will be configured instead. * * @retval None */ void I2S_Init(SPI_TypeDef* SPIx, I2S_InitTypeDef* I2S_InitStruct) { uint16_t tmpreg = 0, i2sdiv = 2, i2sodd = 0, packetlength = 1; uint32_t tmp = 0; RCC_ClocksTypeDef RCC_Clocks; uint32_t sourceclock = 0; /* Check the I2S parameters */ assert_param(IS_SPI_23_PERIPH(SPIx)); assert_param(IS_I2S_MODE(I2S_InitStruct->I2S_Mode)); assert_param(IS_I2S_STANDARD(I2S_InitStruct->I2S_Standard)); assert_param(IS_I2S_DATA_FORMAT(I2S_InitStruct->I2S_DataFormat)); assert_param(IS_I2S_MCLK_OUTPUT(I2S_InitStruct->I2S_MCLKOutput)); assert_param(IS_I2S_AUDIO_FREQ(I2S_InitStruct->I2S_AudioFreq)); assert_param(IS_I2S_CPOL(I2S_InitStruct->I2S_CPOL)); /*----------------------- SPIx I2SCFGR & I2SPR Configuration -----------------*/ /* Clear I2SMOD, I2SE, I2SCFG, PCMSYNC, I2SSTD, CKPOL, DATLEN and CHLEN bits */ SPIx->I2SCFGR &= I2SCFGR_CLEAR_Mask; SPIx->I2SPR = 0x0002; /* Get the I2SCFGR register value */ tmpreg = SPIx->I2SCFGR; /* If the default value has to be written, reinitialize i2sdiv and i2sodd*/ if(I2S_InitStruct->I2S_AudioFreq == I2S_AudioFreq_Default) { i2sodd = (uint16_t)0; i2sdiv = (uint16_t)2; } /* If the requested audio frequency is not the default, compute the prescaler */ else { /* Check the frame length (For the Prescaler computing) */ if(I2S_InitStruct->I2S_DataFormat == I2S_DataFormat_16b) { /* Packet length is 16 bits */ packetlength = 1; } else { /* Packet length is 32 bits */ packetlength = 2; } /* Get the I2S clock source mask depending on the peripheral number */ if(((uint32_t)SPIx) == SPI2_BASE) { /* The mask is relative to I2S2 */ tmp = I2S2_CLOCK_SRC; } else { /* The mask is relative to I2S3 */ tmp = I2S3_CLOCK_SRC; } /* Check the I2S clock source configuration depending on the Device: Only Connectivity line devices have the PLL3 VCO clock */ #ifdef STM32F10X_CL if((RCC->CFGR2 & tmp) != 0) { /* Get the configuration bits of RCC PLL3 multiplier */ tmp = (uint32_t)((RCC->CFGR2 & I2S_MUL_MASK) >> 12); /* Get the value of the PLL3 multiplier */ if((tmp > 5) && (tmp < 15)) { /* Multplier is between 8 and 14 (value 15 is forbidden) */ tmp += 2; } else { if (tmp == 15) { /* Multiplier is 20 */ tmp = 20; } } /* Get the PREDIV2 value */ sourceclock = (uint32_t)(((RCC->CFGR2 & I2S_DIV_MASK) >> 4) + 1); /* Calculate the Source Clock frequency based on PLL3 and PREDIV2 values */ sourceclock = (uint32_t) ((HSE_Value / sourceclock) * tmp * 2); } else {
/** * @brief Initializes the I2S according to the specified parameters * in the I2S_InitTypeDef and create the associated handle. * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains * the configuration information for I2S module * @retval HAL status */ HAL_StatusTypeDef HAL_I2S_Init(I2S_HandleTypeDef *hi2s) { uint32_t i2sdiv = 2, i2sodd = 0, packetlength = 1; uint32_t tmp = 0, i2sclk = 0, tmpreg = 0; /* Check the I2S handle allocation */ if(hi2s == NULL) { return HAL_ERROR; } /* Check the I2S parameters */ assert_param(IS_I2S_ALL_INSTANCE(hi2s->Instance)); assert_param(IS_I2S_MODE(hi2s->Init.Mode)); assert_param(IS_I2S_STANDARD(hi2s->Init.Standard)); assert_param(IS_I2S_DATA_FORMAT(hi2s->Init.DataFormat)); assert_param(IS_I2S_MCLK_OUTPUT(hi2s->Init.MCLKOutput)); assert_param(IS_I2S_AUDIO_FREQ(hi2s->Init.AudioFreq)); assert_param(IS_I2S_CPOL(hi2s->Init.CPOL)); if(hi2s->State == HAL_I2S_STATE_RESET) { /* Allocate lock resource and initialize it */ hi2s->Lock = HAL_UNLOCKED; /* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */ HAL_I2S_MspInit(hi2s); } hi2s->State = HAL_I2S_STATE_BUSY; /* If the default value has to be written, reinitialize i2sdiv and i2sodd*/ if(hi2s->Init.AudioFreq == I2S_AUDIOFREQ_DEFAULT) { i2sodd = (uint32_t)0; i2sdiv = (uint32_t)2; } /* If the requested audio frequency is not the default, compute the prescaler */ else { /* Check the frame length (For the Prescaler computing) *******************/ if(hi2s->Init.DataFormat == I2S_DATAFORMAT_16B) { /* Packet length is 16 bits */ packetlength = 1; } else { /* Packet length is 32 bits */ packetlength = 2; } /* Get the source clock value: based on System Clock value */ i2sclk = HAL_RCC_GetSysClockFreq(); /* Compute the Real divider depending on the MCLK output state, with a floating point */ if(hi2s->Init.MCLKOutput == I2S_MCLKOUTPUT_ENABLE) { /* MCLK output is enabled */ tmp = (uint32_t)(((((i2sclk / 256) * 10) / hi2s->Init.AudioFreq)) + 5); } else { /* MCLK output is disabled */ tmp = (uint32_t)(((((i2sclk / (32 * packetlength)) *10 ) / hi2s->Init.AudioFreq)) + 5); } /* Remove the flatting point */ tmp = tmp / 10; /* Check the parity of the divider */ i2sodd = (uint32_t)(tmp & (uint32_t)1); /* Compute the i2sdiv prescaler */ i2sdiv = (uint32_t)((tmp - i2sodd) / 2); /* Get the Mask for the Odd bit (SPI_I2SPR[8]) register */ i2sodd = (uint32_t) (i2sodd << 8); } /* Test if the divider is 1 or 0 or greater than 0xFF */ if((i2sdiv < 2) || (i2sdiv > 0xFF)) { /* Set the default values */ i2sdiv = 2; i2sodd = 0; } /*----------------------- SPIx I2SCFGR & I2SPR Configuration ----------------*/ /* Write to SPIx I2SPR register the computed value */ hi2s->Instance->I2SPR = (uint32_t)((uint32_t)i2sdiv | (uint32_t)(i2sodd | (uint32_t)hi2s->Init.MCLKOutput)); /* Clear I2SMOD, I2SE, I2SCFG, PCMSYNC, I2SSTD, CKPOL, DATLEN and CHLEN bits */ /* And configure the I2S with the I2S_InitStruct values */ MODIFY_REG( hi2s->Instance->I2SCFGR, (SPI_I2SCFGR_CHLEN | SPI_I2SCFGR_DATLEN |\ SPI_I2SCFGR_CKPOL | SPI_I2SCFGR_I2SSTD |\ SPI_I2SCFGR_PCMSYNC | SPI_I2SCFGR_I2SCFG |\ SPI_I2SCFGR_I2SE | SPI_I2SCFGR_I2SMOD),\ (SPI_I2SCFGR_I2SMOD | hi2s->Init.Mode |\ hi2s->Init.Standard | hi2s->Init.DataFormat |\ hi2s->Init.CPOL)); /* Get the I2SCFGR register value */ tmpreg = hi2s->Instance->I2SCFGR; #if defined(SPI_I2SCFGR_ASTRTEN) if (hi2s->Init.Standard == I2S_STANDARD_PCM_SHORT) { /* Write to SPIx I2SCFGR */ hi2s->Instance->I2SCFGR = tmpreg | SPI_I2SCFGR_ASTRTEN; } else { /* Write to SPIx I2SCFGR */ hi2s->Instance->I2SCFGR = tmpreg; } #else /* Write to SPIx I2SCFGR */ hi2s->Instance->I2SCFGR = tmpreg; #endif hi2s->ErrorCode = HAL_I2S_ERROR_NONE; hi2s->State= HAL_I2S_STATE_READY; return HAL_OK; }