cancel
Showing results for 
Search instead for 
Did you mean: 

i2c master and slave communication problem

sanju
Senior

Hi all,

i have two nucleo-f103rb boards, i am trying to use one board as i2c master and second one is as i2c slave.

the boards communicates well if slave is reset first and master is reset after slave reset i.e.master is reset when slave is running.

lets suppose communication is going good, master is transmitting and slave is receiving well, no problem there , now if i reset the slave during this, slave stops receiving data.

and HAL_I2C_Slave_Receive returns HAL_ERROR status.

to get it working again i need to reset master (note : no need to reset slave again).

please refer below code:

master :

int main(void)

{

 /* USER CODE BEGIN 1 */

 /* USER CODE END 1 */

 /* MCU Configuration--------------------------------------------------------*/

 /* Reset of all peripherals, Initializes the Flash interface and the Systick. */

 HAL_Init();

 /* USER CODE BEGIN Init */

 /* USER CODE END Init */

 /* Configure the system clock */

 SystemClock_Config();

 /* USER CODE BEGIN SysInit */

 /* USER CODE END SysInit */

 /* Initialize all configured peripherals */

 MX_GPIO_Init();

 MX_I2C2_Init();

 /* USER CODE BEGIN 2 */

HAL_Delay(1000);

 /* USER CODE END 2 */

 /* Infinite loop */

 /* USER CODE BEGIN WHILE */

 while (1)

 {

delay++;

if(delay >= 4000000)

{

delay = 0;

}

else;

if(delay == 1)

{

txValue++;

if(txValue >= 127)

{

txValue = 33;

}

else;

if(HAL_I2C_Master_Transmit(&hi2c2,SLAVE_ADDR,(uint8_t*)&txValue,1,100) == HAL_OK)

{

txFlag = 1;

}

else

{

txFlag = 2;

}

HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_SET);

}

else;

if(delay >= 1000000)

{

HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_RESET);

}

else;

  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */

 }

 /* USER CODE END 3 */

}

slave :

int main(void)

{

 /* USER CODE BEGIN 1 */

 /* USER CODE END 1 */

 /* MCU Configuration--------------------------------------------------------*/

 /* Reset of all peripherals, Initializes the Flash interface and the Systick. */

 HAL_Init();

 /* USER CODE BEGIN Init */

 /* USER CODE END Init */

 /* Configure the system clock */

 SystemClock_Config();

 /* USER CODE BEGIN SysInit */

 /* USER CODE END SysInit */

 /* Initialize all configured peripherals */

 MX_GPIO_Init();

 MX_I2C2_Init();

 /* USER CODE BEGIN 2 */

 /* USER CODE END 2 */

 /* Infinite loop */

 /* USER CODE BEGIN WHILE */

 while (1)

 {

i2cStatus = HAL_I2C_Slave_Receive(&hi2c2,(uint8_t*)&rcvValue,1,10000);

if(i2cStatus == HAL_OK)

{

rcvFlag = 1;

}

else

{

rcvFlag = 2;

}

  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */

 }

 /* USER CODE END 3 */

}

please guide what mistake i am making.

thanks in advance.

Post edited to adhere community guidelines.

3 REPLIES 3
Foued_KH
ST Employee

Hi @sanju​,

I think that this is a normal behavior to reset the master as (you provide an explanation).

Could you please explain what do you consider wrong?

Are there any error flags set in I2C_SR register when there is an abnormal behavior?

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.

I think that this is a normal behavior to reset the master as (you provide an explanation).

Ok

Could you please explain what do you consider wrong?

I considered wrong that i have two different board, one as i2c master and second one is i2c slave.

if slave is powered on after master then slave will never receive data until i reset the master.

By considering this situation i changed master code as

master :

int main(void)

{

 /* USER CODE BEGIN 1 */

 /* USER CODE END 1 */

 /* MCU Configuration--------------------------------------------------------*/

 /* Reset of all peripherals, Initializes the Flash interface and the Systick. */

 HAL_Init();

 /* USER CODE BEGIN Init */

 /* USER CODE END Init */

 /* Configure the system clock */

 SystemClock_Config();

 /* USER CODE BEGIN SysInit */

 /* USER CODE END SysInit */

 /* Initialize all configured peripherals */

 MX_GPIO_Init();

 MX_I2C2_Init();

 /* USER CODE BEGIN 2 */

HAL_Delay(1000);

 /* USER CODE END 2 */

 /* Infinite loop */

 /* USER CODE BEGIN WHILE */

 while (1)

 {

delay++;

if(delay >= 4000000)

{

delay = 0;

}

else;

if(delay == 1)

{

txValue++;

if(txValue >= 127)

{

txValue = 33;

}

else;

if(HAL_I2C_Master_Transmit(&hi2c2,SLAVE_ADDR,(uint8_t*)&txValue,1,100) == HAL_OK)

{

txFlag = 1;

}

else

{

txFlag = 2;

HAL_I2C_Init(&hi2c2); // added this line to reinitialize the master

}

HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_SET);

}

else;

if(delay >= 1000000)

{

HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_RESET);

}

else;

  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */

 }

 /* USER CODE END 3 */

}

slave code is same as previous.

now the problem got solved i.e. slave is powered on after master or slave is accidently reset . then because of communication error master will reinitialize i2c and communication will be established.

Is it the right solution that i have done. or is there any better solution .

Are there any error flags set in I2C_SR register when there is an abnormal behavior?

i will look at it.

@KHALSI_Foued​ 

S.Ma
Principal

The bus is free if both sda and scl are high level, so a start bit can be generated. I2C bus side, 18 stop bits generated by io bit bang is another way for bus error recovery.