cancel
Showing results for 
Search instead for 
Did you mean: 

Issues with I2C Direction Changes

DeemDeem52
Associate II

Hello;

I am working with STM32CubeIDE, trying to connect a Nucleo-L4R5ZI board to an ADCS chip using I2C. The method of communication is very strange, requiring: [start condition] - [controller sends two bytes] - [start condition] - [controller sends one byte] - [controller reads several bytes] - [stop condition].

DeemDeem52_0-1710289722807.png

I wrote some code using the built-in HAL functions to try and accomplish this:

DeemDeem52_1-1710289820964.png

 

 

while (HAL_I2C_GetState(hi2c) != HAL_I2C_STATE_READY) {} // delay until ready

 HAL_I2C_Master_Seq_Transmit_IT(hi2c, ADCS_I2C_ADDRESS << 1, buf, sizeof(buf)/sizeof(uint8_t), I2C_FIRST_AND_NEXT_FRAME);

while (HAL_I2C_GetState(hi2c) != HAL_I2C_STATE_READY) {}

 HAL_I2C_Master_Seq_Transmit_IT(hi2c, ADCS_I2C_ADDRESS << 1, read_buf, sizeof(read_buf)/sizeof(uint8_t), I2C_FIRST_AND_NEXT_FRAME);

while (HAL_I2C_GetState(hi2c) != HAL_I2C_STATE_READY) {}

// I2C_FIRST_AND_NEXT_FRAME has start condition, no stop condition, and allows for continuing on with another I2C Seq command

 HAL_I2C_Master_Seq_Receive_IT(hi2c, ADCS_I2C_ADDRESS << 1, temp_data, data_length, I2C_LAST_FRAME);

while (HAL_I2C_GetState(hi2c) != HAL_I2C_STATE_READY) {}

 

 

This code works perfectly when trying to send data to the chip (the first four lines of code). Unfortunately, it fails to receive any data at all using the last two lines; the peripheral device seems to not even be triggered to send any data, so HAL_I2C_GetState remains in HAL_I2C_STATE_BUSY_RX indefinitely.

Can anyone think of a way to fix this?

Thank you!

1 ACCEPTED SOLUTION

Accepted Solutions
Andrew Neil
Evangelist III

@DeemDeem52 wrote:

The method of communication is very strange


What's so strange about it?

As @TDK says, it's a common way to read "registers" in a slave; eg,

AndrewNeil_0-1710334599480.png

 

I find the ST documentation unhelpful in the way it classifies its I2C read functions as "IO" or "IO MEM" - without a clear description of the distinction between the two.

In fact, "IO MEM" is the type to use here - the "registers" in the slave are, effectively, "memory" ...

View solution in original post

6 REPLIES 6
Karl Yamashita
Lead II

An actual part number would help to check the datasheet.

But from the images, it looks like you can use HAL_I2C_Mem_Read_IT

TDK
Guru

Doesn't this code send more than is specified in the datasheet? It sends buf and then read_buf, but the datasheet only says to send TLM ID, presumably only a single byte.

Regardless, this is a common interface for reading/writing registers over I2C. HAL has this implemented in HAL_I2C_Mem_Read, including IT and DMA variants.

 

If you feel a post has answered your question, please click "Accept as Solution".
Andrew Neil
Evangelist III

@DeemDeem52 wrote:

The method of communication is very strange


What's so strange about it?

As @TDK says, it's a common way to read "registers" in a slave; eg,

AndrewNeil_0-1710334599480.png

 

I find the ST documentation unhelpful in the way it classifies its I2C read functions as "IO" or "IO MEM" - without a clear description of the distinction between the two.

In fact, "IO MEM" is the type to use here - the "registers" in the slave are, effectively, "memory" ...

That's good to know...  but in this case, the "Device Address" (0xAE the first time, and 0xAF the second time) is not the same as the actual device address (0x57). Does that change the function I need to use?

The Slave Address is 0x57 - it is 7 bits.

0xAE is a byte value with the Slave Address (0x57) in its top 7 bits, and its LSB (the R/W bit) set to 0;

0xAF is a byte value with the Slave Address (0x57) in its top 7 bits, and its LSB (the R/W bit) set to 1.

So, yes - they are all the same Slave Address.

 

AndrewNeil_0-1710346832986.png

https://www.nxp.com/docs/en/user-guide/UM10204.pdf 

 

Thank you very much! This is definitely the key observation I was missing.