I²S on STM32F411

30 Jun 2015

Hi! I'm trying to communicate with a CS4344 DAC via I²S but I can't get it to work. I followed the steps on the STM32's HAL reference but I guess I made one or several mistakes as I don't get any output on any of the I²S pins.

Here is my code :

I²S tests

#include "mbed.h"

I2S_InitTypeDef CS4344_conf;
I2S_HandleTypeDef CS4344;
GPIO_InitTypeDef SDIN;
GPIO_InitTypeDef SCLK;
GPIO_InitTypeDef LRCLK;
GPIO_InitTypeDef MCLK;
uint16_t buf[2] = {0x1245, 0x6842};

int main() {
    CS4344_conf.Mode = I2S_MODE_MASTER_TX;
    CS4344_conf.Standard = I2S_STANDARD_PHILIPS;
    CS4344_conf.DataFormat = I2S_DATAFORMAT_16B;
    CS4344_conf.MCLKOutput = I2S_MCLKOUTPUT_ENABLE;
    CS4344_conf.AudioFreq = I2S_AUDIOFREQ_96K;
    CS4344_conf.CPOL = I2S_CPOL_LOW;
    CS4344_conf.ClockSource = I2S_CLOCK_PLL;
    CS4344_conf.FullDuplexMode = I2S_FULLDUPLEXMODE_DISABLE;
    
    CS4344.Instance = SPI3;
    CS4344.Init = CS4344_conf;
    
    //HAL_I2S_MspInit (&CS4344);
    
    //-------- Enable the SPIx interface clock. 
    __HAL_RCC_SPI3_CLK_ENABLE();
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    __HAL_I2S_ENABLE(&CS4344);
    
    //-------- I2S pins configuration: 
    SDIN.Pin = GPIO_PIN_5;
    SDIN.Mode = GPIO_MODE_AF_PP;
    SDIN.Pull = GPIO_PULLUP;
    SDIN.Alternate = GPIO_AF6_SPI3;
    
    SCLK.Pin = GPIO_PIN_3;
    SCLK.Mode = GPIO_MODE_AF_PP;
    SCLK.Pull = GPIO_PULLUP;
    SCLK.Alternate = GPIO_AF6_SPI3;
    
    LRCLK.Pin = GPIO_PIN_15;
    LRCLK.Mode = GPIO_MODE_AF_PP;
    LRCLK.Pull = GPIO_PULLUP;
    LRCLK.Alternate = GPIO_AF6_SPI3;
    
    MCLK.Pin = GPIO_PIN_10;
    MCLK.Mode = GPIO_MODE_AF_PP;
    MCLK.Pull = GPIO_PULLUP;
    MCLK.Alternate = GPIO_AF6_SPI3;
    
    HAL_GPIO_Init (GPIOB, &SDIN);
    HAL_GPIO_Init (GPIOB, &SCLK);
    HAL_GPIO_Init (GPIOB, &MCLK);
    HAL_GPIO_Init (GPIOA, &LRCLK);
    
    // ------------- Program the Mode, Standard, Data Format, MCLK Output, Audio frequency and Polarity using HAL_I2S_Init() function.
    
    HAL_I2S_Init (&CS4344);

    while(1) {
        HAL_I2S_Transmit (&CS4344, buf, 2, 1000);
        wait(5);
    }
}

What am I doing wrong?

03 Jul 2015

I2S Clock not generate ? use STM32CubeMX & generate clock source code. it will help you.)

03 Jul 2015

I try STM32CubeMX. This image is Clock setting for I2S 96kHz. But peripheral Clock is not fix.. pls try!! /media/uploads/p_igmon/clockconfig.png /media/uploads/p_igmon/i2s.png

03 Jul 2015

Recently I make PCM Music synthesizer by DAC CS43L22 on STM32Fdiscovery168MHz. But not mbed,EWARM(Free Version limited code size). If you interested.in this code. Post mail below.

pigmon_2014@excite.co.jp

24 Jul 2015

Hey I'm so sorry for the late answer, I was travelling in Tokyo for 3 weeks.

Thank you so much for your help, I will try that right now and tell you

28 Jul 2015

I live in Japan ,Chiba near Tokyo. ^ ^ )

28 Jul 2015

Haha I actually lived there for 1 week! I tried using STM32Cube with SW4STM32 IDE but it still doesn't work... should I send you my code/config?

28 Jul 2015

OK pls send me. pigmon_2014@excite.co.jp

17 Jan 2016

#include "mbed.h"

I2S_HandleTypeDef hi2s2;

// a full cycle, 16-bit, 2's complement sine wave lookup table
uint16_t SINE_TABLE[256] = {

   0x0000, 0x0324, 0x0647, 0x096a, 0x0c8b, 0x0fab, 0x12c8, 0x15e2, 
   0x18f8, 0x1c0b, 0x1f19, 0x2223, 0x2528, 0x2826, 0x2b1f, 0x2e11,
   0x30fb, 0x33de, 0x36ba, 0x398c, 0x3c56, 0x3f17, 0x41ce, 0x447a, 
   0x471c, 0x49b4, 0x4c3f, 0x4ebf, 0x5133, 0x539b, 0x55f5, 0x5842,
   0x5a82, 0x5cb4, 0x5ed7, 0x60ec, 0x62f2, 0x64e8, 0x66cf, 0x68a6, 
   0x6a6d, 0x6c24, 0x6dca, 0x6f5f, 0x70e2, 0x7255, 0x73b5, 0x7504,
   0x7641, 0x776c, 0x7884, 0x798a, 0x7a7d, 0x7b5d, 0x7c29, 0x7ce3, 
   0x7d8a, 0x7e1d, 0x7e9d, 0x7f09, 0x7f62, 0x7fa7, 0x7fd8, 0x7ff6,
   0x7fff, 0x7ff6, 0x7fd8, 0x7fa7, 0x7f62, 0x7f09, 0x7e9d, 0x7e1d, 
   0x7d8a, 0x7ce3, 0x7c29, 0x7b5d, 0x7a7d, 0x798a, 0x7884, 0x776c,
   0x7641, 0x7504, 0x73b5, 0x7255, 0x70e2, 0x6f5f, 0x6dca, 0x6c24, 
   0x6a6d, 0x68a6, 0x66cf, 0x64e8, 0x62f2, 0x60ec, 0x5ed7, 0x5cb4,
   0x5a82, 0x5842, 0x55f5, 0x539b, 0x5133, 0x4ebf, 0x4c3f, 0x49b4, 
   0x471c, 0x447a, 0x41ce, 0x3f17, 0x3c56, 0x398c, 0x36ba, 0x33de,
   0x30fb, 0x2e11, 0x2b1f, 0x2826, 0x2528, 0x2223, 0x1f19, 0x1c0b, 
   0x18f8, 0x15e2, 0x12c8, 0x0fab, 0x0c8b, 0x096a, 0x0647, 0x0324,
   0x0000, 0xfcdc, 0xf9b9, 0xf696, 0xf375, 0xf055, 0xed38, 0xea1e, 
   0xe708, 0xe3f5, 0xe0e7, 0xdddd, 0xdad8, 0xd7da, 0xd4e1, 0xd1ef,
   0xcf05, 0xcc22, 0xc946, 0xc674, 0xc3aa, 0xc0e9, 0xbe32, 0xbb86, 
   0xb8e4, 0xb64c, 0xb3c1, 0xb141, 0xaecd, 0xac65, 0xaa0b, 0xa7be,
   0xa57e, 0xa34c, 0xa129, 0x9f14, 0x9d0e, 0x9b18, 0x9931, 0x975a, 
   0x9593, 0x93dc, 0x9236, 0x90a1, 0x8f1e, 0x8dab, 0x8c4b, 0x8afc,
   0x89bf, 0x8894, 0x877c, 0x8676, 0x8583, 0x84a3, 0x83d7, 0x831d, 
   0x8276, 0x81e3, 0x8163, 0x80f7, 0x809e, 0x8059, 0x8028, 0x800a,
   0x8000, 0x800a, 0x8028, 0x8059, 0x809e, 0x80f7, 0x8163, 0x81e3, 
   0x8276, 0x831d, 0x83d7, 0x84a3, 0x8583, 0x8676, 0x877c, 0x8894,
   0x89bf, 0x8afc, 0x8c4b, 0x8dab, 0x8f1e, 0x90a1, 0x9236, 0x93dc, 
   0x9593, 0x975a, 0x9931, 0x9b18, 0x9d0e, 0x9f14, 0xa129, 0xa34c,
   0xa57e, 0xa7be, 0xaa0b, 0xac65, 0xaecd, 0xb141, 0xb3c1, 0xb64c, 
   0xb8e4, 0xbb86, 0xbe32, 0xc0e9, 0xc3aa, 0xc674, 0xc946, 0xcc22,
   0xcf05, 0xd1ef, 0xd4e1, 0xd7da, 0xdad8, 0xdddd, 0xe0e7, 0xe3f5, 
   0xe708, 0xea1e, 0xed38, 0xf055, 0xf375, 0xf696, 0xf9b9, 0xfcdc,
};


int main() {
	
	// enable clocks to PORTB, PORTC and SPI2
	__GPIOB_CLK_ENABLE();
	__GPIOC_CLK_ENABLE();
	__SPI2_CLK_ENABLE();
	
	/**I2S2 GPIO Configuration    
	PC3     ------> I2S2_SD
	PB10     ------> I2S2_CK
	PB12     ------> I2S2_WS 
	*/
	
	GPIO_InitTypeDef GPIO_InitStruct;
	
	GPIO_InitStruct.Pin = GPIO_PIN_3;
	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);

	GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_12;
	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);
	
	// intialize I2S clocks
	
	RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
	
	PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2S;

	//get 1MHz from 16MHz HSI
	PeriphClkInitStruct.PLLI2S.PLLI2SM = 16;
	
	// from reference manual for 44.1kHz (no MCLK)
	PeriphClkInitStruct.PLLI2S.PLLI2SR = 2;
	PeriphClkInitStruct.PLLI2S.PLLI2SN = 302;
	
  HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
	
	// set up I2S
	
	hi2s2.Instance = SPI2;
  hi2s2.Init.Mode = I2S_MODE_MASTER_TX;
  hi2s2.Init.Standard = I2S_STANDARD_PHILLIPS;
  hi2s2.Init.DataFormat = I2S_DATAFORMAT_16B;
  hi2s2.Init.MCLKOutput = I2S_MCLKOUTPUT_DISABLE;
  hi2s2.Init.AudioFreq = I2S_AUDIOFREQ_44K;
  hi2s2.Init.CPOL = I2S_CPOL_LOW;
  hi2s2.Init.ClockSource = I2S_CLOCK_PLL;
  hi2s2.Init.FullDuplexMode = I2S_FULLDUPLEXMODE_DISABLE;  
	HAL_I2S_Init(&hi2s2);
	
		uint16_t test = 0x00;
		
		int index = 0;
		
		bool channel = false;
    while(1) {
			
      if (HAL_I2S_GetState(&hi2s2) == HAL_I2S_STATE_READY)
			{
				HAL_I2S_Transmit(&hi2s2,&SINE_TABLE[index],1,0);
				
				channel = !channel;
				if (channel)
				{
					index++;
					index = index % 256;
				}
				
			}
    }
}

distorted as hell but I got this working tonight. It's a first step.. you need to enable the clocks to the ports and the SPI

Cheers Dave