user505160
user505160

Reputation: 1216

STM32 HAL_I2C_Master_Transmit - Why we need to shift address?

after stumbling upon very strange thing I would like to find out if anyone could provide reasonable explanation.

I have SHT31 humidity sensor running on I2C and after trying to run it on STM32F2 it didn't work.

uint8_t __data[5]={0};

__data[0] = SHT31_SOFTRESET >> 8;
__data[1] = SHT31_SOFTRESET & 0xFF;


HAL_I2C_Master_Transmit(&hi2c3,((uint16_t)0x44)<<1,__data,2,1000);

I have opened the function and saw:

/**
  * @brief  Transmits in master mode an amount of data in blocking mode.
  * @param  hi2c Pointer to a I2C_HandleTypeDef structure that contains
  *                the configuration information for the specified I2C.
  * @param  DevAddress Target device address: The device 7 bits address value
  *         in datasheet must be shifted to the left before calling the interface
  * @param  pData Pointer to data buffer
  * @param  Size Amount of data to be sent
  * @param  Timeout Timeout duration
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
  /* Init tickstart for timeout management*/
  uint32_t tickstart = HAL_GetTick();

  if (hi2c->State == HAL_I2C_STATE_READY)
  ....... and it goes ....

So I followed the comment and frustration from my scope (looking why my bits are not going on the wire) and did:

HAL_I2C_Master_Transmit(&hi2c3,((uint16_t)0x44)<<1,__data,2,1000);

Finally my bits are going out and device ACKs me back - voila it works!

But why?? What would be the reason behind putting burden on the programmer to shift the address?

Upvotes: 2

Views: 13415

Answers (3)

Charles Maxim
Charles Maxim

Reputation: 1

Sorry for the late reply, I just bumped my head against this myself. This should be considered a bug but ST refuses to acknowledge it as such. If you research the reference manual for the I2C section, the OAR1 register states that the address is stored in bits 7:1 for 7 bit mode. Bits 0, 8 and 9 are ignored. The HAL routine that sets the address should then shift the 7 LSB's so that bits 6:0 of your address get written to bits 7:1 of the OAR1 register. This doesn't happen. Essentially, because the code was released, it is now a "feature" and not a bug. Another way to look at it is that the address byte that you send to the HAL is left aligned. This is extremely irritating as it is not consistent for 7 and 10 bit addresses.

Upvotes: 0

Codo
Codo

Reputation: 78915

It has never been agreed whether an I2C address is to be specified:

  1. such that it needs to be shifted for transmission, or
  2. such that it does not need to be shifted for transmission.

Therefore some device datasheets specify it in variant 1 and some in variant 2. Similarly, some I2C APIs take the address in variant 1 and some in variant 2.

If the device and the API use a different variant, it's the programmer's burden to shift the address.

It creates a lot of confusion and is quite annoying. I doubt it will every be clarified.

Upvotes: 3

Michael Heil
Michael Heil

Reputation: 18505

Because the programmer should probably be made aware if he wants to read or write data to or from the I2C slave device.

In common I2C communication the first seven bits of the "address byte" contains the slave address, whereas the last bit is a read/write bit. 0 is write and 1 is read.

In your case, you want to write data to the device (to perform a soft reset) and therefore a simple left shift will do the trick.

Upvotes: 2

Related Questions