cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L476 SAI2 MCLK generation

kardwor1
Associate II
Posted on February 10, 2017 at 16:55

Hi,

I'm trying to communicate with

http://www.analog.com/media/en/technical-documentation/data-sheets/ADAU1761.pdf

 via SAI, STM32L476 is master. I sucessfully connected to it via I2C, now I need to send data. I dont have much experience with SAI. The task is to play

22.05kHz

16 bit WAVE and also record audio. I used

SAI2A for RX, SAI2B for TX, 4 pins mode (ADC_SDATA - SAI2_SD_A, DAC_SDATA - SAI2_SD_B, LRCLK - SAI2_FS_A, BCLK - SAI2_SCK_A)

. I saw 

http://www.st.com/content/ccc/resource/training/technical/product_training/0c/16/3b/b4/76/8a/47/51/STM32L4_Peripheral_SAI.pdf/files/STM32L4_Peripheral_SAI.pdf/jcr:content/translations/en.STM32L4_Peripheral_SAI.pdf

 guide but instead of using SAI2A for TX I use it for RX. As far I as understood ADAU1761 needs MCLK to record/play audio. When I use HAL_SAI_Transmit() the MCLK is not generated, I checked it with logic analyzer. However with HAL_SAI_Receive() MCLK is present. Is there any way to generate MCLK during 

HAL_SAI_Transmit()

with this configuration? Maybe somebody has some experience with interfacing STM32 and ADAU17xx or ADAU14xx DSPs. Here is my configuration:

void MX_SAI2_Init(void)

{

hsai_BlockA2.Instance = SAI2_Block_A;

hsai_BlockA2.Init.Protocol = SAI_FREE_PROTOCOL;

hsai_BlockA2.Init.AudioMode = SAI_MODEMASTER_RX;

hsai_BlockA2.Init.DataSize = SAI_DATASIZE_16;

hsai_BlockA2.Init.FirstBit = SAI_FIRSTBIT_MSB;

hsai_BlockA2.Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE;

hsai_BlockA2.Init.Synchro = SAI_ASYNCHRONOUS;

hsai_BlockA2.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLE;

hsai_BlockA2.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE;

hsai_BlockA2.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF;

hsai_BlockA2.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_22K;

hsai_BlockA2.Init.SynchroExt = SAI_SYNCEXT_DISABLE;

hsai_BlockA2.Init.MonoStereoMode = SAI_STEREOMODE;

hsai_BlockA2.Init.CompandingMode = SAI_NOCOMPANDING;

hsai_BlockA2.FrameInit.FrameLength = 32;

hsai_BlockA2.FrameInit.ActiveFrameLength = 16;

hsai_BlockA2.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;

hsai_BlockA2.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;

hsai_BlockA2.FrameInit.FSOffset = SAI_FS_FIRSTBIT;

hsai_BlockA2.SlotInit.FirstBitOffset = 0;

hsai_BlockA2.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;

hsai_BlockA2.SlotInit.SlotNumber = 2;

hsai_BlockA2.SlotInit.SlotActive = 0x00000003;

if (HAL_SAI_Init(&hsai_BlockA2) != HAL_OK)

{

Error_Handler();

}

hsai_BlockB2.Instance = SAI2_Block_B;

hsai_BlockB2.Init.Protocol = SAI_FREE_PROTOCOL;

hsai_BlockB2.Init.AudioMode = SAI_MODESLAVE_TX;

hsai_BlockB2.Init.DataSize = SAI_DATASIZE_16;

hsai_BlockB2.Init.FirstBit = SAI_FIRSTBIT_MSB;

hsai_BlockB2.Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE;

hsai_BlockB2.Init.Synchro = SAI_SYNCHRONOUS;

hsai_BlockB2.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLE;

hsai_BlockB2.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF;

hsai_BlockB2.Init.SynchroExt = SAI_SYNCEXT_DISABLE;

hsai_BlockB2.Init.MonoStereoMode = SAI_STEREOMODE;

hsai_BlockB2.Init.CompandingMode = SAI_NOCOMPANDING;

hsai_BlockB2.Init.TriState = SAI_OUTPUT_NOTRELEASED;

hsai_BlockB2.FrameInit.FrameLength = 32;

hsai_BlockB2.FrameInit.ActiveFrameLength = 16;

hsai_BlockB2.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;

hsai_BlockB2.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;

hsai_BlockB2.FrameInit.FSOffset = SAI_FS_FIRSTBIT;

hsai_BlockB2.SlotInit.FirstBitOffset = 0;

hsai_BlockB2.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;

hsai_BlockB2.SlotInit.SlotNumber = 2;

hsai_BlockB2.SlotInit.SlotActive = 0x00000003;

if (HAL_SAI_Init(&hsai_BlockB2) != HAL_OK)

{

Error_Handler();

}

}

DMA SAI2A init:

hdma_sai2_a.Instance = DMA1_Channel6;

hdma_sai2_a.Init.Request = DMA_REQUEST_1;

hdma_sai2_a.Init.Direction = DMA_MEMORY_TO_PERIPH;

hdma_sai2_a.Init.PeriphInc = DMA_PINC_DISABLE;

hdma_sai2_a.Init.MemInc = DMA_MINC_ENABLE;

hdma_sai2_a.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;

hdma_sai2_a.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;

hdma_sai2_a.Init.Mode = DMA_CIRCULAR;

hdma_sai2_a.Init.Priority = DMA_PRIORITY_HIGH;

DMA SAI2B init:

hdma_sai2_b.Instance = DMA1_Channel7;

hdma_sai2_b.Init.Request = DMA_REQUEST_1;

hdma_sai2_b.Init.Direction = DMA_MEMORY_TO_PERIPH;

hdma_sai2_b.Init.PeriphInc = DMA_PINC_DISABLE;

hdma_sai2_b.Init.MemInc = DMA_MINC_ENABLE;

hdma_sai2_b.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;

hdma_sai2_b.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;

hdma_sai2_b.Init.Mode = DMA_CIRCULAR;

hdma_sai2_b.Init.Priority = DMA_PRIORITY_HIGH;

#stm32 #stm32l4 #stm32-sai #sai
2 REPLIES 2
kardwor1
Associate II
Posted on February 11, 2017 at 17:12

OK, The answer is simple. I need to call 

HAL_SAI_Receive_DMA(&hsai_BlockA2, saiRxBuff, 512);

HAL_SAI_Transmit_DMA(&hsai_BlockB2, saiTxBuff, 512);

and the MCLK is generated during SAI2B transmission. 

kardwor1
Associate II
Posted on February 14, 2017 at 16:56

Ok, I'm confused about MCLK. Datasheet says that MCLK = (sampling rate * 256). However if I use CubeMX and generate code for 48kHz sampling rate the MCLK should be 12,288MHz. In clock configuration tab I can choose SAI2 clock source and speed. I choosed PLLSAI2P = 24MHz, there is 12MHz on the output. I checked it with logic analyzer and it looks like this:

 0690X00000606J8QAI.png

Any idea why?