Skip to main content
Associate II
March 13, 2024
Solved

Issues with I2C Direction Changes

  • March 13, 2024
  • 3 replies
  • 3844 views

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!

This topic has been closed for replies.
Best answer by Andrew Neil

@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" ...

3 replies

Karl Yamashita
Lead III
March 13, 2024

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

If a reply has proven helpful, click on Accept as Solution so that it'll show at top of the post.CAN Jammer an open source CAN bus hacking toolCANableV3 Open Source
TDK
Super User
March 13, 2024

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
Andrew NeilBest answer
Super User
March 13, 2024

@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" ...

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.
Associate II
March 13, 2024

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?

Andrew Neil
Super User
March 13, 2024

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 

 

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.