cancel
Showing results for 
Search instead for 
Did you mean: 

Verify if it is safe to continue I2C communication after I2C transaction instead of using HAL_Delay

bmn
Associate II

I made an I2C communication between STM32U585 uC to an I2C EEPROM and it works

I do the following

 0693W00000aIwB7QAK.png 

but if I remove the HAL_Delay(10) or minimizes it to less than 10msec things are not working well, the second call I2C_Master_Transmit fails.

Is there's a way to call the I2C_ISR register or anything else, in order to check if the writing process was completed before proceeding with the communication?

Thanks!

1 ACCEPTED SOLUTION

Accepted Solutions

Yes, these functions ignore the LSB and set it as appropriate. This is how the 2nd Master_Transmit() works with read address.

If the target device is eeprom, IIRC instead of fixed HAL_Delay poll the device until it responds.

I. e. call HAL_I2C_IsDeviceReady with needed timeout. If the device becomes ready sooner, it may return sooner.

View solution in original post

8 REPLIES 8
Foued_KH
ST Employee

Hello @bmn​,

 Before starting a new communication transfer, you need to check the current state of the peripheral; if it’s busy you need to wait for the end of current transfer before starting a new one.

You can add this function :

while (HAL_I2C_GetState(&hi2c2) != HAL_I2C_STATE_READY)
  {
  }

Foued

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Thank you so much! I tried it, as shown below

0693W00000aIwiVQAS.pngAnd it didn't work for me. Only after bringing back the HAL_Delay(10) the program worked properly, without it, again the second call to HAL_I2C_Master_Transmit fails.

Am I using it in the wrong way?

You are welcome :smiling_face_with_smiling_eyes:

When your question is answered, please close this topic by choosing Select as Best the answer that answered your question or solved your problem. This will help other users find that answer faster. 

Foued

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Bob S
Principal

A little premature :)

What do you mean "second call fails"? Does it return something other than HAL_OK? Or does it return HAL_OK but doesn't send the data to the EEPROM? Or does it send data to the EEPROM but it doesn't do what you expect it to do?

If you are trying to access an EEPROM, why not use HAL_I2C_Mem_Write() and HAL_I2C_Mem_Read(). Those functions encapsulate the writing of device address and memory address then repeated start (if needed) and reading/writing data.

I presume M4_ADDRESS_READ has the 7-bit address in the upper 7 bits and the LSB=1. That is not the format that the HAL_I2C_Master_Transmit/Receive functions expect. They expect the LSB=0 (or just plain ignore the LSB), and they set/clear the LSB based on whether you call a Transmit or Receive function (I think - I do not use those functions).

Yes, these functions ignore the LSB and set it as appropriate. This is how the 2nd Master_Transmit() works with read address.

If the target device is eeprom, IIRC instead of fixed HAL_Delay poll the device until it responds.

I. e. call HAL_I2C_IsDeviceReady with needed timeout. If the device becomes ready sooner, it may return sooner.

bmn
Associate II

I tried it and added the part "And it didn't work.." only after his "You are welcome" so it came out weird.

Be nice.

bmn
Associate II

Hi, thanks for the reply. "second call fails" means that it returns HAL_ERROR.

I switched according to your advise to the HAL_I2C_Mem_Read/Write() functions and called HAL_I2C_IsDeviceReady with a while empty loop. I found that it is the right choice here, since the state HAL_I2C_STATE_READY which is the one I would wait for by calling HAL_I2C_GetState() does not necessarily mean that the device is not busy, as can be understood from the HAL I2C code below:

0693W00000aJ1loQAC.png 

So the code which is working as I would expect is:

ret = HAL_I2C_Mem_Write(&hi2c1, M24_ADDRESS_WRITE, MemAddress, MemAddressSize, buf_out, DataSize, HAL_MAX_DELAY);
	
while(HAL_I2C_IsDeviceReady(&hi2c1, M24_ADDRESS_WRITE, 1, HAL_MAX_DELAY) != HAL_OK)
 {
 }
 if( ret == HAL_OK)
 {
  	ret = HAL_I2C_Mem_Read(&hi2c1, M24_ADDRESS_READ, MemAddress, MemAddressSize, buf_in, DataSize, HAL_MAX_DELAY);
  	if( ret == HAL_OK)
  	{

Thanks a lot!

S.Ma
Principal

SW delays kills the average bit rate and performance.

You should only need the delay after writing (transmitting) the data, the EEPROM will need 5 msec or less to be ready for a read, or another page write.

Actually, if you want to minimize the delay, you can try to read data after write, the slave will ACK, yet the data will be NACKED. loop up to 5 msec in 1 msec per loop delay and the lag will be minimal.