Skip to main content
Peter Curtis
Associate II
January 19, 2018
Question

I cannot get I2C work on stm32l476

  • January 19, 2018
  • 8 replies
  • 1440 views
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);

  }

 

}
    This topic has been closed for replies.

    8 replies

    Andrew Neil
    Super User
    January 20, 2018
    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?

    A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
    Peter Curtis
    Associate II
    January 25, 2018
    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

    Andrew Neil
    Super User
    January 25, 2018
    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?

    A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
    T J
    Senior III
    January 22, 2018
    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);�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

    T J
    Senior III
    January 25, 2018
    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)
    

    Peter Curtis
    Associate II
    January 26, 2018
    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

    T J
    Senior III
    January 27, 2018
    183018CGIL3