2016-10-05 03:37 PM
Hi, I'm using a STM32F411 on a product that uses I2S to stream some sound to an audio codec.
I use this function to configure oscillator:void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
__PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 6;
RCC_OscInitStruct.PLL.PLLN = 168;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;
RCC_OscInitStruct.PLL.PLLQ = 7;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);
//22050 Hz original del final_09_DPOAE_05_Apexar
// PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2S;
// PeriphClkInitStruct.PLLI2S.PLLI2SN = 192;
// PeriphClkInitStruct.PLLI2S.PLLI2SM = 12;
// PeriphClkInitStruct.PLLI2S.PLLI2SR = 2;
// HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
//44100Hz
// PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2S;
// PeriphClkInitStruct.PLLI2S.PLLI2SN = 271;
// PeriphClkInitStruct.PLLI2S.PLLI2SM = 12;
// PeriphClkInitStruct.PLLI2S.PLLI2SR = 2;
// HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
/*
* Esta configuracion es para tener buen % trabajando a 22KHz
*/
// PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2S;
// PeriphClkInitStruct.PLLI2S.PLLI2SN = 429;
// PeriphClkInitStruct.PLLI2S.PLLI2SM = 12;
// PeriphClkInitStruct.PLLI2S.PLLI2SR = 4;
// HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
/*
* Esta configuracion es para tener buen % trabajando a 96KHz
*/
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2S;
PeriphClkInitStruct.PLLI2S.PLLI2SN = 344;
PeriphClkInitStruct.PLLI2S.PLLI2SM = 12;
PeriphClkInitStruct.PLLI2S.PLLI2SR = 2;
HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
/* SysTick_IRQn interrupt configuration */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
As you can see I have 4 diferent blocks on I2S clock. I need to use 2 of them on my firmware.
I need to know how can I change just I2S clock frecuency. Could I write just this:
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2S;
PeriphClkInitStruct.PLLI2S.PLLI2SN = 344;
PeriphClkInitStruct.PLLI2S.PLLI2SM = 12;
PeriphClkInitStruct.PLLI2S.PLLI2SR = 2;
HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
on any part of my code and it will change I2S clock?
Thank
2016-10-11 03:42 AM
Hello,
Review I2S working example under STM32CubeF4, this may help you to develop your project:STM32Cube_FW_F4_V1.13.0\Projects\STM324xG_EVAL\Examples\I2S\I2S_AudioRegards2016-10-17 04:09 PM
I saw the example code and it is a good starting point.
But it is not clear to me the correct way to properly do this:I'm using CubeMx generated code for some parts of that flowchart.
So, for point 1 I have:/* I2S2 init function */
void MX_I2S2_Init(uint32_t SampleFreq)
{
hi2s2.State = HAL_I2C_STATE_RESET; // To be sure that HAL_I2S_MspInit is executed on point 6
hi2s2.Instance = SPI2;
hi2s2.Init.Mode = I2S_MODE_MASTER_TX;
hi2s2.Init.Standard = I2S_STANDARD_PHILLIPS;
hi2s2.Init.DataFormat = I2S_DATAFORMAT_24B;
hi2s2.Init.MCLKOutput = I2S_MCLKOUTPUT_ENABLE;
hi2s2.Init.AudioFreq = SampleFreq;
hi2s2.Init.CPOL = I2S_CPOL_LOW;
hi2s2.Init.ClockSource = I2S_CLOCK_PLL;
hi2s2.Init.FullDuplexMode = I2S_FULLDUPLEXMODE_ENABLE;
HAL_I2S_Init(&hi2s2);
}
HAL_I2S_MspInit has part of point 2 and is called by HAL_I2S_Init
void HAL_I2S_MspInit(I2S_HandleTypeDef* hi2s)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(hi2s->Instance==SPI2)
{
/* Peripheral clock enable */
__SPI2_CLK_ENABLE();
/**I2S2 GPIO Configuration
PB12 ------> I2S2_WS
PB13 ------> I2S2_CK
PB14 ------> I2S2_ext_SD
PB15 ------> I2S2_SD
PC6 ------> I2S2_MCK
*/
GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_14;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
GPIO_InitStruct.Alternate = GPIO_AF6_I2S2ext;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/* Peripheral DMA init*/
hdma_i2s2_ext_rx.Instance = DMA1_Stream3;
hdma_i2s2_ext_rx.Init.Channel = DMA_CHANNEL_3;
hdma_i2s2_ext_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_i2s2_ext_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_i2s2_ext_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_i2s2_ext_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_i2s2_ext_rx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_i2s2_ext_rx.Init.Mode = DMA_CIRCULAR;
hdma_i2s2_ext_rx.Init.Priority = DMA_PRIORITY_LOW;
hdma_i2s2_ext_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
hdma_i2s2_ext_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_i2s2_ext_rx.Init.MemBurst = DMA_MBURST_SINGLE;
hdma_i2s2_ext_rx.Init.PeriphBurst = DMA_PBURST_SINGLE;
HAL_DMA_Init(&hdma_i2s2_ext_rx);
__HAL_LINKDMA(hi2s,hdmarx,hdma_i2s2_ext_rx);
hdma_spi2_tx.Instance = DMA1_Stream4;
hdma_spi2_tx.Init.Channel = DMA_CHANNEL_0;
hdma_spi2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_spi2_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi2_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_spi2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_spi2_tx.Init.Mode = DMA_CIRCULAR;
hdma_spi2_tx.Init.Priority = DMA_PRIORITY_LOW;
hdma_spi2_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
hdma_spi2_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_spi2_tx.Init.MemBurst = DMA_MBURST_SINGLE;
hdma_spi2_tx.Init.PeriphBurst = DMA_PBURST_SINGLE;
HAL_DMA_Init(&hdma_spi2_tx);
__HAL_LINKDMA(hi2s,hdmatx,hdma_spi2_tx);
}
}
for point 2 I have:
void MX_DMA_Init(void)
{
__DMA2_CLK_ENABLE();
__DMA1_CLK_ENABLE();
/* DMA interrupt init */
HAL_NVIC_SetPriority(DMA1_Stream3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream3_IRQn);
HAL_NVIC_SetPriority(DMA1_Stream4_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream4_IRQn);
HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
}
Then I config my codec. Here there is no problem. I already test my codec initialization and output/input sound and it is ok.
Then for pint 4 I write:
HAL_I2SEx_TransmitReceive_DMA(&hi2s2, (uint16_t *)OutputBuffer, (uint16_t *)InputBuffer, SOUND_BUFF_SIZE);
with output/input buffers configured.
Then after a few seconds I call HAL_I2S_DMAStop(&hi2s2);
It is something like this:
MX_DMA_Init(); // Canales de comunicacion DMA
MX_I2S2_Init(); // I2S para comunicacion de sonidos con Codec de Audio
Codec_Init_DPEOAE();
HAL_Delay(2000);
// Reseteo la bandera de mitad de buffer lleno
f_mitad_buffer=0;
HAL_I2SEx_TransmitReceive_DMA(&hi2s2, (uint16_t *)OutputBuffer, (uint16_t *)InputBuffer, SOUND_BUFF_SIZE);
HAL_Delay(2000);
HAL_I2S_DMAStop(&hi2s2);
All of this is working well.
But the problem is that I need to execute previouse code several times. And the second time I run that code the sound is not well.
So, I would like to know what should I do to put I2S and DMA as it was when uC run for the first time after reset.
Thank
2016-10-18 09:19 AM
Hi,
I suggest you calling I2S_DeInit to deInitializes the I2S peripheral.Regards