I2C addressing on STM32F4-Discovery

In past month STM published new set of tools and software examples that implement HAL (wikipedia: Hardware abstraction layer) on the many of theirs µC. They are calling this set of tools STM32CubeF4. This post is a little public note to myself and all others who are banging or will be banging their heads at wall because they aren’t able to make I2C communication to work.


I2C addressing (not the 10bit, i am talking about 7bit) has only 7 bits because one bit of 8 bit addressing space is reserved for flag denoting if operation will be reading or writing. That one bit is LSB (Least significant bit). If you are into details, you can more here.


Till now i worked with libraries that input a 7bit address and they automatically shift it for one bit to left. After that libs set LSB to the right value depending on the operation.

 STM32CubeF4’s way

(At the time writting this: HAL version is 1.1.0 )

Long story short: You have to shift the 7 bit address yourself. You can see two functions from my I2C library that are more or less self explanatory – note the shifted addresses  (uint16_t)I2C_ADDRESS<<1 


And ReadBuffer :


I hope i saved you an hour or two :-).

34 thoughts on “I2C addressing on STM32F4-Discovery”

  1. Hello,

    I’m happy to see this post!
    I’m struggling for several days to make the I2C work using IAR (while it was working OK on MBED, I have to switch to IAR in order to use bluetooth blueNRG librairies for STM32F4).
    So this post might be the next step I would have needed, because right now, I’m still having it returning HAL_BUSY.

    Do you have the possibility to publish some kind of “full example” where you set a communication up that would help me going further?

    Kind regards


    1. Hi,

      glad to hear that my post is useful. Honestly, nowadays I get little time to play with my ARMs. My guess that If code worked ok with mbed, that its not the code’s fault? Is my code returning HAL_BUSY? I have with my own project some problems with HAL_BUSY, but as far as I debugged it, it’s hardware related issue – too many capacitance on I2C lines, could that be problem in your case? Did you change hardware in any way (more components on I2C lines, longer wires, etc.) – that could be the reason? Does communication always fail or it sometimes get message through?

      I’ll try to fund some code somewhere – but i don’t have it on this pc. Keep me posted about your problems.

      Regards, Jure

  2. This might seem like a dumb question, but what value should be set for ‘I2C_ADDRESS’. Is it a 7 bit binary number or can I define it as an 8 bit hex number ‘0x3c’ for example. ?

    1. If you are refering to functions I worte above you can see here:

      void I2C::ReadBuffer(uint8_t I2C_ADDRESS, uint8_t RegAddr, uint8_t *aRxBuffer, uint8_t RXBUFFERSIZE)

      I2C_ADDRESS is defined as uint8_t so unsigned 8 bit number.

    1. Hi, glad to help. For almost a year now I didn’t have any time to work on STM32F4 (started job and PhD). If you want to have some inspiration what can be done with STM32F4 this is my biggest project http://jure.tuta.si/robot , I hope I will have time soon to write about it here on the blog.

  3. Hi,
    I am new to this HAL driver. I struggle with the Register Address.. When Master needs to write or read something, the “I2C_Write” function takes the Device Address and Register Address as some of its parameters. I don’t see how this driver does it..

    Here https://github.com/MaJerle/stm32fxxx_hal_libraries/blob/b181cc3edbfaf427f75d7f43e325f5ec18dd1265/00-STM32_LIBRARIES/tm_stm32_i2c.c someone used the data[0] as the register address.. Is it the way the register address is handled by this driver??

    1. Which driver do you mean? The one I write about in the post? I think the source code I posted has more or less self explanatory variable names and a lot of comments.

      For example in read function you have:

      /* -> Lets ask for register’s address */
      WriteBuffer(I2C_ADDRESS, &RegAddr, 1);

      This means you ask device whose address is I2C_ADDRESS for the content of the RegAddr.

      1. I think I’ve found the answer to my question. I think I was looking for a higher level function that dealt with all the low level stuff.

        The function below seems to do it. I haven’t tested it yet though. It is the original HAL driver function prototype. It takes in all necessary parameters and performs the write operation. At least, it seems to.

        HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)

  4. Thanks, I got stuck on this for a few days, got down to use the scope and noticed the MSb was being transmitted, then your post gave the answer.

    1. Lucky you had scope. I didn’t and still don’t have 🙁 that is why (and of course because the lack of time) this project is on hold. I have suspicion that wires to the sensors on the feet (6axes gyro/accelerometers) are too long and therefore they hold too much capacity and therefore the I2C communication randomly hangs. Of course if I would have time first idea is to connect each of the sensors to separate I2C pins as STM has many of them. That would reduce the capacity of the wires by half.

      When my phd will be over I would really like to continue with development of the robot. I’d like to implement that if sensors in the feet sense the fall of the robot it would catch itself.

      1. at 100kHz (the standard I2C) frequency, it would take a lot of wiring to add significant capacitance if you use the common 10K value for the pull-up resistors. How long are your wires ?
        Also check level compatibility if the sensors are 5V, you may need level translators as the STM32 is 3.3V.

        1. Hi,
          firstly electronic engineering is something that I “self-thought”, I am mechanical engineer that is now working his way through computer science PhD, therefore there are things I don’t know about electronic.
          I have suspicion that wires are the cause because if I connect the sensor I can communicate with it for some time (0.5 – 1second) than connection falls.
          I know I have more than double the recommended length of wires of the I2C – aprox. 0.5 m (they go from the STM on the top all the way to the foot’s base) for each foot sensor, therefore ~1m. My soldering skills at the time I was working on this weren’t that good also (big blobs of solder), therefore I think the problem is in capacitance.
          Regarding voltage compatibility I think it’s as is should be. (It’s over a year now since I had to pause the project) But thanks will double check that.
          Regarding pull-ups, I think that I read then that STM has internal pull-ups on the I2C port I am using.
          I had clock-speed maxed out at 400k looking back I should stick to the 100k.
          Thanks for the response

  5. One one of my setups, I just had to resort to using 2K external pullups to have decent waveforms at 400KHz. Internal pullups are 40K, clearly insufficient.

  6. Thank you very much for pointing out the obvious about left shifting the address with one bit. I changed the sensor in my project to a new one and spent 3 long nights debugging my I2C implementation to find the cause of why it was just timing out all communication. I felt rather stupid when I realised that the code for the old sensor had the <<1 behind the address… So added left shift, recompiled, programmed STM32F4 chip…. and voila. IT WORKED 🙂

  7. I was struck , without this bit shifting it wasn’t getting the Ack from Slave ( obviously it was addressing the wrong salve 🙂 ). After shifting it works perfectly.

    Note : I was trying to interface PCF8574 IC to STM32103c8t6.

    1. Np, glad that I helped. If I only would find more time to work with this stuff, I would write more blogs like this and I could continue this project … 🙁

  8. Does anyone know if this works for later versions (e.g. STM32F746)? As I am having problems trying to get the microcontroller to connect a Venus838FLPx (breakout board) GPS device through the HAL_driver.

Leave a Reply

Your email address will not be published. Required fields are marked *