/** * @brief Enables or disables the specified SPI peripheral (in I2S mode). * @param SPIx: where x can be 1 to select the SPI peripheral. * @param NewState: new state of the SPIx peripheral. * This parameter can be: ENABLE or DISABLE. * @retval None */ void I2S_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState) { /* Check the parameters */ assert_param(IS_SPI_1_PERIPH(SPIx)); assert_param(IS_FUNCTIONAL_STATE(NewState)); if (NewState != DISABLE) { /* Enable the selected SPI peripheral in I2S mode */ SPIx->I2SCFGR |= SPI_I2SCFGR_I2SE; } else { /* Disable the selected SPI peripheral in I2S mode */ SPIx->I2SCFGR &= (uint16_t)~((uint16_t)SPI_I2SCFGR_I2SE); } }
/** * @brief Enables or disables the TI Mode. * @note This function can be called only after the SPI_Init() function has * been called. * @note When TI mode is selected, the control bits SSM, SSI, CPOL and CPHA * are not taken into consideration and are configured by hardware * respectively to the TI mode requirements. * @param SPIx: where x can be 1 to select the SPI peripheral. * @param NewState: new state of the selected SPI TI communication mode. * This parameter can be: ENABLE or DISABLE. * @retval None */ void SPI_TIModeCmd(SPI_TypeDef* SPIx, FunctionalState NewState) { /* Check the parameters */ assert_param(IS_SPI_1_PERIPH(SPIx)); assert_param(IS_FUNCTIONAL_STATE(NewState)); if (NewState != DISABLE) { /* Enable the TI mode for the selected SPI peripheral */ SPIx->CR2 |= SPI_CR2_FRF; } else { /* Disable the TI mode for the selected SPI peripheral */ SPIx->CR2 &= (uint16_t)~((uint16_t)SPI_CR2_FRF); } }
/** * @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; }