cancel
Showing results for 
Search instead for 
Did you mean: 

I cannot get I2C work on stm32l476

Peter Curtis
Associate II
Posted on January 19, 2018 at 21:59

Hi All,

First post on here and a newbie with the STM32 family of devices (I come from a PIC background - sorry about that)

I have just received my first STM32 board design back from the sub contractors and am having a little trouble and am hoping someone can point me in the right direction.

First of all, I'm using keil as the IDE/Compiler.  I have configured the micro using CUBE and am using the HAL libraries. 

My issue is that I cannot get I2C_MEM_WRITE or READ to work.

On the first use of > if(HAL_I2C_IsDeviceReady(&hi2c1, I2C_ROM, 1, 100) == HAL_OK)

I get an OK.  When I try a mem_write it fails (that is HAL_OK returns 0).

I have check my soldering and even shortened the i2c bus by truncating it immediately after the cat24c512 with a craft knife (and adding 2x10k resistors to vcc), but still no luck.

The device address (I2C_ROM) is defined as 0xA0.  I have tried playing with the timeout also.

I notice that in CUBE things like rise and fall time can be set - not idea what to set these to (didn't have to worry about that in the world of PIC).

Any pointers would be most appreciated.

Here is the code:-

uint8_t WriteConfigToI2C(void)

{

    char buffer[5] = 'TEST';

    uint8_t i;

  

  if(HAL_I2C_IsDeviceReady(&hi2c1, I2C_ROM, 1, 100) == HAL_OK)  //i2c address of eeprom = 0b1010000 = 0xa0

  {    

       HAL_UART_Transmit(&hlpuart1, (uint8_t*)'\r\nWrite', 7, 1000);   //(uint8_t*)'\r\nready'

       HAL_Delay(100);

    

      if(HAL_I2C_Mem_Write(&hi2c1, I2C_ROM, 0x00, 0xFFFF, (uint8_t*)buffer, strlen(buffer), 100) == HAL_OK)  // write       'buffer' to I2C mem

   

     {

          HAL_UART_Transmit(&hlpuart1, (uint8_t*)': OK', 4, 1000); // send 'OK' to uart if success

          HAL_Delay(100); // wait for eeprom to commit / finish

     

          // clear buffer

          for(i = 0; i < 50; i++)

         {

               buffer[i] = 0; 

         }

     

        // read the memory and write it back out on uart

     

       HAL_I2C_Mem_Read(&hi2c1, I2C_ROM, 0x00, 0xFFFF, (uint8_t*)buffer, 5, 100);  // read back eeprom and put into        'i2cBuffer'

          

        HAL_UART_Transmit(&hlpuart1, (uint8_t*)buffer, strlen(buffer), 1000);  // write 'i2cBuffer' to uart

     

    }

    else

    {

     HAL_UART_Transmit(&hlpuart1, (uint8_t*)': FAIL', 6, 1000);  // failed to write

    } 

  }

  else

  {

    HAL_UART_Transmit(&hlpuart1, (uint8_t*)'\r\nNotReady', 10, 1000);

  }

 

}
8 REPLIES 8
Andrew Neil
Evangelist
Posted on January 21, 2018 at 00:48

 a newbie with the STM32 ... I have just received my first STM32 board design back from the sub contractors

So have you first prototyped this on a Discovery or Nucleo or other Dev Board?

That should give you a working reference point ...

Have you scoped the pins to see what - if anything - is actually happening on the wires?

T J
Lead
Posted on January 22, 2018 at 04:10

this works for me,

after the cube is setup, I use blocking mode to send the frame.

the last line sends the data in blocking mode.

#define MCP4728_DacAddress 0x60 << 1

struct DacIIC {
 uint8_t DacTxBuffer[4];
 uint8_t DacRxBuffer[16]; 
};

 struct DacIIC MCP4728IIC;
 HAL_StatusTypeDef IIC_Response; 
 char channel;
 char use2xGain = false;
 char powerDownMode = false;
 char UseInternalVRef = false;
 int Dac_Value;
 
 channel = 0;
 Dac0_Value = (4096 * 1) / 5; // 1V
 MCP4728IIC.DacTxBuffer[0] = 0x40 | ((channel & 0x3) << 1);
 MCP4728IIC.DacTxBuffer[1] = ((uint8_t)UseInternalVRef << 7) | ((powerDownMode & 0x3) << 5) | ((uint8_t)use2xGain << 4);
 MCP4728IIC.DacTxBuffer[1] |= (Dac0_Value & 0x0f00)>>8; 
 MCP4728IIC.DacTxBuffer[2] = Dac0_Value & 0xff;
 //DAC_IIC.write(DAC_ADDR + (Dac_Address << 1), buf, 3, 0) == 0; //mbed
 
 IIC_Response = HAL_I2C_Master_Transmit(&hi2c1, MCP4728_DacAddress, &MCP4728IIC.DacTxBuffer[0], 3, 10);�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

Posted on January 25, 2018 at 10:38

Hi Andrew,

Thank you for your response.  Yes.  I hooked SDA/SCL up to a scope and checked out the signals.  The rise looked a bit woolly, so I reduced the pull-ups to 1K. 

0690X00000603jeQAA.jpg

Above shows the trace when running the IsDeviceReady() on 0xA0 (the CAT24C512).

However, if I try to write to the device afterwards, It still fails to write.  Then the mem device appears to lock up - that is I get a not ready response if I try another IsDeviceReady().

Not quite sure where to go with this at the moment.  I have an I2C bus analyser on the way, maybe that will shed more light - but I've never had to use one in the 10years of my using I2C on other controllers.

thanks,

Peter

Posted on January 25, 2018 at 12:25

Can't your scope give you a screenshot directly?

Peter Curtis wrote:

Not quite sure where to go with this at the moment. 

Verify that scope waveform against the I2C spec.

  • Is it a valid Start Condition?
  • Is the slave address correct?
  • is the R/W bit correct?
  • does the Slave ACK?

Again, have you tried it on a known-good board (Nucleo, Disco, etc) with a known-good example for that board?

T J
Lead
Posted on January 25, 2018 at 22:42

'it fails to write'

can you read data and status from the flash CAT24C512 ?

I suggest that you stop using : HAL_I2C_IsDeviceReady

and use something like my suggestion above :

HAL_I2C_Master_Transmit(&hi2c1, MCP4728_DacAddress, &MCP4728IIC.DacTxBuffer[0], 3, 10);
HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout)

Posted on January 26, 2018 at 16:27

Hi TJ,

Thank you for your reply - but it doesn't look possible to use this function with a memory device as I need to set the internal address to write to, before writing data.

Many thanks,

Peter

Posted on January 26, 2018 at 16:37

Hi Andrew,

My scope was purchased sometime ago and the application that came with it does not work with windows 10 unfortunately.  However, I have just received my smartscope and have captured the following:-

0690X00000609UsQAI.png

Comparing against the i2c spec, the start condition is correct as are the 'ack's.  The slave address and the internal address to write to (0x00FF) are also correct.

The interesting thing to note from the trace above is that everything seems to be going swimmingly until its time to write the data - then the clock stops (SCL stays low).

I do, in the depth of my bits box somewhere, have a disco476, so will dig it out over the weekend.  I don't believe it has an I2C memory device on it though.

Kind regards,

Peter

183018CGIL3