cancel
Showing results for 
Search instead for 
Did you mean: 

I2C: Wrong Slave address on STM32H743ZI (Nucleo board)

AGour
Associate II

This is more a bug report than an actual question.

I have experienced a wrong behavior of the I2C driver of STM32H743ZI MCU (Nucleo board).

What's happening? The driver is simply dividing by 2 the slave address passed as a parameter to the function HAL_I2C_Master_Transmit. This leads to an absence of communication between master and slave (which is here an aardvark I2C SPI adapter), since master is transmitting to an erroneous slave address.

The I2C handle is configured as follow:

hi2c1.Instance = I2C1;
  hi2c1.Init.Timing = 0x10707DBC;
  hi2c1.Init.OwnAddress1 = 0;
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c1.Init.OwnAddress2 = 0;
  hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_ENABLE;
  if (HAL_I2C_Init(&hi2c1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
 
    /**Configure Analogue filter
    */
  if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
 
    /**Configure Digital filter
    */
  if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

And the main function calls:

transmitReturn = HAL_I2C_Master_Transmit ( &hi2c1, (uint16_t) I2C1_SLAVE_ADDRESS,uint8_t*) aI2C_TxBuffer, I2C2_TXBUFFERSIZE, 10000);

Where I2C1_SLAVE_ADDRESS's value is 0x48 (bin: 1001000).

In the attached document scope_KO_I2C_slave_adr_0x48.bmp, you can see the transmitted slave address on the SDA that I captured with an oscilloscope. Instead of having bin1001000 as expected, we are reading bin0100100. This is actually the slave address shifted right, so it is divided by two.

Furthermore, I inspected the register where slave address is configured (I2C_CR2). The last byte of this register is dedicated to Slave address. As you can see in the attached register dump document register I2C.png , the correct slave address is written to the register (0x48). Somehow, the CPU divides this address by two afterward.

A simple correction for a developer is to multiply by two the desired slave address, before calling any HAL_I2C_*** function.

1 ACCEPTED SOLUTION

Accepted Solutions
Andreas Bolsch
Lead II

You stepped into the common pitfall regarding the I2C addresses 😉

Although I2C bus is 8-bit oriented (or actually 8+1), the slave address takes only 7 bits, the remaining bit is the R/W bit (and this happens to be the LSB bit, sigh ...).

Hence some people take the 7-bit address literally, some others silently append the R/W bit to the right, so the address is shifted one place to the left.

But here the register description of I2C_CR2 is quite clear, I think:

Bits 7:1 SADD[7:1]: Slave address bit 7:1 (master mode)

In 7-bit addressing mode (ADD10 = 0):

These bits should be written with the 7-bit slave address to be sent

So your 7-bit I2C address must be shifted left one position. Always beware of this confusion when people are talking about I2C addresses. If only the Phillips guys would have used the MSB for R/W ...

View solution in original post

5 REPLIES 5
David Littell
Senior III

Have you read the HAL documentation for HAL_I2C_Master_Transmit()?

Andreas Bolsch
Lead II

You stepped into the common pitfall regarding the I2C addresses 😉

Although I2C bus is 8-bit oriented (or actually 8+1), the slave address takes only 7 bits, the remaining bit is the R/W bit (and this happens to be the LSB bit, sigh ...).

Hence some people take the 7-bit address literally, some others silently append the R/W bit to the right, so the address is shifted one place to the left.

But here the register description of I2C_CR2 is quite clear, I think:

Bits 7:1 SADD[7:1]: Slave address bit 7:1 (master mode)

In 7-bit addressing mode (ADD10 = 0):

These bits should be written with the 7-bit slave address to be sent

So your 7-bit I2C address must be shifted left one position. Always beware of this confusion when people are talking about I2C addresses. If only the Phillips guys would have used the MSB for R/W ...

AGour
Associate II

Thank you for the fast answer!

I get it now! 🙂

Kolab
Senior

@Andreas Bolsch​ so, in this case I'm gonna shift the address 0x49 to the left and forget about the "x" ? I've got a 7+1 address sensor.0693W00000WKo0nQAD.png

Correct, you use 0x92, and the I2C peripheral controller deals with the -R/W bit based on the interaction you're engaging in.

You can tell if something is on the bus because it will ACK to it's address.

PHILIPS has ONE L

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..