2024-03-12 05:35 PM
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].
I wrote some code using the built-in HAL functions to try and accomplish this:
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!
Solved! Go to Solution.
2024-03-13 06:03 AM
@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,
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" ...
2024-03-12 06:43 PM - edited 2024-03-12 06:43 PM
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
2024-03-12 07:45 PM
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.
2024-03-13 06:03 AM
@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,
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" ...
2024-03-13 09:03 AM
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?
2024-03-13 09:17 AM - edited 2024-03-13 09:26 AM
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.
https://www.nxp.com/docs/en/user-guide/UM10204.pdf
2024-03-13 09:25 AM
Thank you very much! This is definitely the key observation I was missing.