2024-07-12 03:21 AM
in stdlib version1.9.0,
void I2S_Init(SPI_TypeDef* SPIx, I2S_InitTypeDef* I2S_InitStruct)
{
uint16_t tmpreg = 0, i2sdiv = 2, i2sodd = 0, packetlength = 1;
uint32_t tmp = 0, i2sclk = 0;
#ifndef I2S_EXTERNAL_CLOCK_VAL
uint32_t pllm = 0, plln = 0, pllr = 0;
#endif /* I2S_EXTERNAL_CLOCK_VAL */
/* 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 = 16;
}
else
{
/* Packet length is 32 bits */
packetlength = 32;
}
if(I2S_InitStruct->I2S_Standard <= I2S_Standard_LSB)
{
/* In I2S standard packet length is multiplied by 2 */
packetlength = packetlength * 2;
}
/* Get I2S source Clock frequency ****************************************/
/* If an external I2S clock has to be used, this define should be set
in the project configuration or in the stm32f4xx_conf.h file */
#ifdef I2S_EXTERNAL_CLOCK_VAL
/* Set external clock as I2S clock source */
if ((RCC->CFGR & RCC_CFGR_I2SSRC) == 0)
{
RCC->CFGR |= (uint32_t)RCC_CFGR_I2SSRC;
}
/* Set the I2S clock to the external clock value */
i2sclk = I2S_EXTERNAL_CLOCK_VAL;
#else /* There is no define for External I2S clock source */
/* Set PLLI2S as I2S clock source */
if ((RCC->CFGR & RCC_CFGR_I2SSRC) != 0)
{
RCC->CFGR &= ~(uint32_t)RCC_CFGR_I2SSRC;
}
/* Get the PLLI2SN value */
plln = (uint32_t)(((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6) & \
(RCC_PLLI2SCFGR_PLLI2SN >> 6));
/* Get the PLLI2SR value */
pllr = (uint32_t)(((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> 28) & \
(RCC_PLLI2SCFGR_PLLI2SR >> 28));
/* Get the PLLM value */
pllm = (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM);
if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLCFGR_PLLSRC_HSE)
{
/* Get the I2S source clock value */
i2sclk = (uint32_t)(((HSE_VALUE / pllm) * plln) / pllr);
}
else
{ /* Get the I2S source clock value */
i2sclk = (uint32_t)(((HSI_VALUE / pllm) * plln) / pllr);
}
#endif /* I2S_EXTERNAL_CLOCK_VAL */
/* 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)(((((i2sclk / 256) * 10) / I2S_InitStruct->I2S_AudioFreq)) + 5);
}
else
{
/* MCLK output is disabled */
tmp = (uint16_t)(((((i2sclk / (32 * packetlength)) *10 ) / I2S_InitStruct->I2S_AudioFreq)) + 5);
}
/* Remove the flatting 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)((uint16_t)i2sdiv | (uint16_t)(i2sodd | (uint16_t)I2S_InitStruct->I2S_MCLKOutput));
/* Configure the I2S with the SPI_InitStruct values */
tmpreg |= (uint16_t)((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))));
#if defined(SPI_I2SCFGR_ASTRTEN)
if((I2S_InitStruct->I2S_Standard == I2S_Standard_PCMShort) || (I2S_InitStruct->I2S_Standard == I2S_Standard_PCMLong))
{
/* Write to SPIx I2SCFGR */
SPIx->I2SCFGR = tmpreg | SPI_I2SCFGR_ASTRTEN;
}
#else
/* Write to SPIx I2SCFGR */
SPIx->I2SCFGR = tmpreg ;
#endif
}
in older version,the same function is
void I2S_Init(SPI_TypeDef* SPIx, I2S_InitTypeDef* I2S_InitStruct)
{
uint16_t tmpreg = 0, i2sdiv = 2, i2sodd = 0, packetlength = 1;
uint32_t tmp = 0, i2sclk = 0;
#ifndef I2S_EXTERNAL_CLOCK_VAL
uint32_t pllm = 0, plln = 0, pllr = 0;
#endif /* I2S_EXTERNAL_CLOCK_VAL */
/* 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 I2S source Clock frequency ****************************************/
/* If an external I2S clock has to be used, this define should be set
in the project configuration or in the stm32f4xx_conf.h file */
#ifdef I2S_EXTERNAL_CLOCK_VAL
/* Set external clock as I2S clock source */
if ((RCC->CFGR & RCC_CFGR_I2SSRC) == 0)
{
RCC->CFGR |= (uint32_t)RCC_CFGR_I2SSRC;
}
/* Set the I2S clock to the external clock value */
i2sclk = I2S_EXTERNAL_CLOCK_VAL;
#else /* There is no define for External I2S clock source */
/* Set PLLI2S as I2S clock source */
if ((RCC->CFGR & RCC_CFGR_I2SSRC) != 0)
{
RCC->CFGR &= ~(uint32_t)RCC_CFGR_I2SSRC;
}
/* Get the PLLI2SN value */
plln = (uint32_t)(((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6) & \
(RCC_PLLI2SCFGR_PLLI2SN >> 6));
/* Get the PLLI2SR value */
pllr = (uint32_t)(((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> 28) & \
(RCC_PLLI2SCFGR_PLLI2SR >> 28));
/* Get the PLLM value */
pllm = (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM);
if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLCFGR_PLLSRC_HSE)
{
/* Get the I2S source clock value */
i2sclk = (uint32_t)(((HSE_VALUE / pllm) * plln) / pllr);
}
else
{ /* Get the I2S source clock value */
i2sclk = (uint32_t)(((HSI_VALUE / pllm) * plln) / pllr);
}
#endif /* I2S_EXTERNAL_CLOCK_VAL */
/* 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)(((((i2sclk / 256) * 10) / I2S_InitStruct->I2S_AudioFreq)) + 5);
}
else
{
/* MCLK output is disabled */
tmp = (uint16_t)(((((i2sclk / (32 * packetlength)) *10 ) / I2S_InitStruct->I2S_AudioFreq)) + 5);
}
/* Remove the flatting 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)((uint16_t)i2sdiv | (uint16_t)(i2sodd | (uint16_t)I2S_InitStruct->I2S_MCLKOutput));
/* Configure the I2S with the SPI_InitStruct values */
tmpreg |= (uint16_t)((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;
}
differ as picture above, I think there is a problem. Can you help me with it?