cancel
Showing results for 
Search instead for 
Did you mean: 

I2C master slave communication is not working properly

_kalpesh
Associate III

I have two MCU's one from F4 series and another from H7 series, Using F4 MCU for calculation of some data and want configured as I2C master which sends data to the H7 MCU. Where as H7 MCU is configured as slave and which responds to address from first MCU. 

The communication doesn't work on the first go, but when i manually restart the F4 Master MCU it starts working for some time and send data to H7 correctly but after few mins it stops
i have tried resetting master MCU I2C by checking HAL_I2C_IsDeviceReady but its not working either

using HAL_I2C_EnableListen_IT(hi2c); in the start itself for H7 and following enabling after each completion of transaction

extern void HAL_I2C_ListenCpltCallback (I2C_HandleTypeDef *hi2c)
{
	HAL_I2C_EnableListen_IT(hi2c);
}
void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c) {
    // Re-enable listening after transmission
    HAL_I2C_EnableListen_IT(hi2c);
}
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c)
{
	HAL_I2C_EnableListen_IT(hi2c);
}

How to fix this? can someone guide me in the right direction.
It works for the first few mins and thats why the circuit is correct ans im ruling out that. how to debug this issue?

6 REPLIES 6
Danish1
Lead III

I2C has a weakness in that you can stop communications at any instant e.g. part-way through a byte, then resume a *long* time later and expect things to carry on as if no delay. That’s fine under normal circumstances but if either end has been reset between times the communication will be upset.

One approach, which the I2C-alike SMBUS takes, is to have a time-out period after which master and slave may give up and release the bus.

The other approach is that at reset and to recover from error situations, the master will “clock out” to clear anything that might be incomplete on the bus. To do this, the SCL and SDA lines are temporarily changed to GPIO and then manually programmed to put an I2C stop-condition, followed by 9 clock pulses with SDA high then a second stop-condition. A correctly-behaved I2C slave will always release the bus in response to this.

——
One important question is whether the problem lies with the I2C Master or thr I2C slave. (There could be problems in both).If you have an alternative device you can use as a slave, does master+alternative-slave work reliably?

Edit: added separator

 

i have tested same setup with two DISC-F4 boards and saw the same behavior of I2C, i'm sending data from master to slave after every 4 seconds its like heartbeat message. 

and to ans your question.

i think the issues is on the slave side which is not accessible to the master on  HAL_I2C_IsDeviceReady  check.
i have used following block to reset the i2c on master side 

			if(HAL_I2C_IsDeviceReady(&hi2c2, 0x12<<1, 2, 100)!=HAL_OK){
			    HAL_I2C_DeInit(&hi2c2);
			    __HAL_RCC_I2C2_FORCE_RESET();
			    __HAL_RCC_I2C2_RELEASE_RESET();
			    HAL_I2C_Init(&hi2c2);
			}

I have different clocks frequencies given to the i2c peripheral for MCU1 and MCU2 i know it's not going to affect the peripheral as its going to work on 100KHz but is there chance this is the issue? 

Danish1
Lead III

Different clocks won’t matter at all. As long as they both have timing parameters appropriate to their clocks, they will both comply with the I2C specifications and therefore work.

I don’t think your recovery code is sufficient. I imagine that

HAL_I2C_IsDeviceReady

 just checks if the master’s peripheral thinks it has completed its previous transaction and that SCL and SDA are both high. What you do - telling RCC to reset the master’s peripheral - will not solve the problem if the slave happens to be pulling SDA low. Only the master “clocking out” the I2C bus will tell the slave to release SDA

okk let me try "clock out" method and get back
i have one more question, trying to send data after every 4 second which is counted by timer interrupt

this repeated data sending from the master can be the problem? or maybe this is causing the issue.

 


@Danish1 wrote:

I imagine that

HAL_I2C_IsDeviceReady

 just checks if the master’s peripheral thinks it has completed its previous transaction and that SCL and SDA are both high. 


It actually confirms that it gets an ACK from the addressed Slave.

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.

@_kalpesh wrote:

let me try "clock out" method 


That method is specified in the NXP (formerly Philips) specification - See here, which also has some other suggestions for recovering from STM32 / HAL I2C problems ...

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.