cancel
Showing results for 
Search instead for 
Did you mean: 

How can I use i2c to communicate two STM32F103

kadir ustun1
Senior

I want to i2c to communicate two STM32F103. one of them will be a slave and other will be master. But program is stop on this :

void SendI2CByteData (I2C_TypeDef* I2Cx, uint8_t SlaveAddr, uint8_t Data)

{

 __IO uint8_t temp = 0;

 I2C_GenerateSTART(I2Cx, ENABLE);                                           /* NOTE: Generate Start Condition*/

 while ((I2Cx->SR1&0x0001) != 0x0001);

 I2C_Send7bitAddress(I2Cx, SlaveAddr<<1, I2C_Direction_Transmitter);                          /* NOTE: Send Slave Addres. Slave addr'yi 1 sola kaydiriyorum ki write biti yazilsin*/

 while ((I2Cx->SR1 &0x0002) != 0x0002);                                        /* NOTE: Wait Data to transgfer*/

 temp = I2Cx->SR2;

 while(!I2C_GetFlagStatus(I2C2,I2C_FLAG_TXE))

 I2C_SendData(I2Cx, Data);                                               /* NOTE: Sending Data */

 while ((I2Cx->SR1 & 0x00004) != 0x000004);                                      /* NOTE: Wait data sending */

 I2C_GenerateSTOP(I2Cx, ENABLE);                                            /* NOTE: Is All Data transfering, then generate stop otherwise i2c bus is hang*/

 while ((I2Cx->CR1&0x200) == 0x200);

}

program stop this line :

 while ((I2Cx->SR1 & 0x00004) != 0x000004);                                      /* NOTE: Wait data sending

Please can you help me ?

13 REPLIES 13

First of all, check the physical layer and pin and peripherals initialization routines.

This is only the master's part, where is the slave's part?

Also, please use proper bit names instead of magic values like 0x0002, I don't want to open the reference manual and check if your magic values are correct. See this working example: https://github.com/Catethysis/stm32_i2c/blob/master/I2C.c

Ozone
Lead II

ST's I2C peripheral is notoriously complex and awkward.

I would have choosen SPI instead.

The most important thing with any project like this in not to try to do it all at once!

If you just write a load of Slave code, and a load of Master, connect it together, and it doesn't work - you have no idea whether the problem is in the Slave, or the Master or both!

So start with one end of the link, and get that fully debugged and working before moving on to the other end.

Since being that Master is by far the commonest use case for a Microcontroller, I suggest that you start with that; get it talking to some standard I2C peripheral.

Make sure you thoroughly test & debug your Master to cope with common problems such as missing slave, no ACK, unexpected NAK, no pullups, etc

Learn to recognise what effects these situations have on your code.

Make sure you carefully instrument your Master to report problems such as no ACK, unexpected NAK, no pullups, etc.

You will need an oscilloscope and/or analyser so that you can see what is happening on the I2C lines.

Study ST's examples.

Then, once you have a good, solid, well-understood Master, you can move on to implementing the Slave.

Use the 'Code Snippet' button to properly post source code:

0690X00000AQTkKQAX.png

kadir ustun1
Senior

Hello,

Thank you for answered. Actually I want to learn how can ı do stm32f103 as slave? how configure stm32f103 as slave?

kadir ustun1
Senior

I configured slave device like master. But ı enabled interrupt of slave device. The code is in interrupt :

   switch (I2C_GetLastEvent(I2C2))

   { 

    case I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED:

     i=I2C2->SR1;

     i=I2C2->SR2;      

     I2C_SendData(I2C2, 0xAA);  

     break;  

     case I2C_EVENT_SLAVE_BYTE_TRANSMITTED:

     I2C_SendData(I2C2, 0xAA); 

     break;

     case I2C_EVENT_SLAVE_STOP_DETECTED:

     //I2C_CleanADDRandSTOPF();

     break;      

    case I2C_EVENT_SLAVE_ACK_FAILURE:

     I2C2->SR1&=0x1111101111111111;

    break;

   case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED:

      regVal = I2C_ReadRegister(I2C2,I2C_Register_DR);

      /* Clear SR1Register SR2Register variables to prepare for next IT*/

      SR1Register = 0;

      SR2Register = 0;

      Tx_Idx2 = 0;

       

      Rx_Idx2 = 0;

      Buffer_Rx2[0] = I2C2->DR;

fs = I2C_GetFlagStatus(I2C2,I2C_FLAG_TRA);

    /* If TXE = 1: EV3 */

    if ((SR1Register & 0x0080) == 0x0080)

    {

      /* Write data in data register */

      I2C2->DR = Buffer_Tx2[Tx_Idx2++];

      SR1Register = 0;

      SR2Register = 0;

    }

    /* If RXNE = 1: EV2 */

    if (I2C_GetLastEvent(I2C2) == I2C_EVENT_SLAVE_BYTE_RECEIVED)

    {

      /* Read data from data register */

      Buffer_Rx2[Rx_Idx2++] = I2C2->DR;

      SR1Register = 0;

      SR2Register = 0;

    }

    /* If STOPF =1: EV4 (Slave has detected a STOP condition on the bus */

    if (( SR1Register & 0x0010) == 0x0010)

    {

      I2C2->CR1 |= 0x001;

      SR1Register = 0;

      SR2Register = 0;

    }

  

       

     break;

    case I2C_EVENT_SLAVE_BYTE_RECEIVED:

      

      Buffer_Rx2[Rx_Idx2++] = I2C2->DR;

      SR1Register = 0;

      SR2Register = 0;

      break;

  }

0690X00000AQTkKQAX.png

Again, have you looked at the examples that ST provide?

Have you studied the Manual for the chip?

Have you looked for Application Notes?

https://www.st.com/en/microcontrollers-microprocessors/stm32f103.html#resource

kadir ustun1
Senior

   switch (I2C_GetLastEvent(I2C2))
 
 
 
 
 
   { 
 
 
 
 
 
    case I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED:
 
 
 
 
 
     i=I2C2->SR1;
 
 
 
 
 
     i=I2C2->SR2;      
 
 
 
 
 
     I2C_SendData(I2C2, 0xAA);  
 
 
 
 
 
     break;  
 
 
 
 
 
     case I2C_EVENT_SLAVE_BYTE_TRANSMITTED:
 
 
 
 
 
     I2C_SendData(I2C2, 0xAA); 
 
 
 
 
 
     break;
 
 
 
 
 
     case I2C_EVENT_SLAVE_STOP_DETECTED:
 
 
 
 
 
     //I2C_CleanADDRandSTOPF();
 
 
 
 
 
     break;      
 
 
 
 
 
    case I2C_EVENT_SLAVE_ACK_FAILURE:
 
 
 
 
 
     I2C2->SR1&=0x1111101111111111;
 
 
 
 
 
    break;
 
   case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED:
 
      regVal = I2C_ReadRegister(I2C2,I2C_Register_DR);
 
 
 
 
 
      /* Clear SR1Register SR2Register variables to prepare for next IT*/
 
 
 
 
 
      SR1Register = 0;
 
 
 
 
 
      SR2Register = 0;
 
      Tx_Idx2 = 0;
 
       
 
      Rx_Idx2 = 0;
 
      Buffer_Rx2[0] = I2C2->DR;
 
 
 
fs = I2C_GetFlagStatus(I2C2,I2C_FLAG_TRA);
 
    /* If TXE = 1: EV3 */
 
 
 
 
 
    if ((SR1Register & 0x0080) == 0x0080)
 
 
 
 
 
    {
 
 
 
 
 
      /* Write data in data register */
 
 
 
 
 
      I2C2->DR = Buffer_Tx2[Tx_Idx2++];
 
 
 
 
 
      SR1Register = 0;
 
 
 
 
 
      SR2Register = 0;
 
 
 
 
 
    }
 
 
 
 
 
    /* If RXNE = 1: EV2 */
 
 
 
 
 
    if (I2C_GetLastEvent(I2C2) == I2C_EVENT_SLAVE_BYTE_RECEIVED)
 
 
 
 
 
    {
 
 
 
 
 
      /* Read data from data register */
 
 
 
 
 
      Buffer_Rx2[Rx_Idx2++] = I2C2->DR;
 
 
 
 
 
      SR1Register = 0;
 
 
 
 
 
      SR2Register = 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
    }
 
 
 
 
 
    /* If STOPF =1: EV4 (Slave has detected a STOP condition on the bus */
 
 
 
 
 
    if (( SR1Register & 0x0010) == 0x0010)
 
 
 
 
 
    {
 
 
 
 
 
      I2C2->CR1 |= 0x001;
 
 
 
 
 
      SR1Register = 0;
 
 
 
 
 
      SR2Register = 0;
 
 
 
 
 
    }
 
 
 
 
 
  
 
       
 
     break;
 
    case I2C_EVENT_SLAVE_BYTE_RECEIVED:
 
      
 
      Buffer_Rx2[Rx_Idx2++] = I2C2->DR;
 
 
 
 
 
      SR1Register = 0;
 
 
 
 
 
      SR2Register = 0;
 
      break;
 
  }

Go on - does that code look clear and easy to read to you?