AnsweredAssumed Answered

I want to make I2C communication between two stm32l073 mcu

Question asked by Praveen Kumar on Jul 11, 2017
Latest reply on Jul 15, 2017 by Praveen Kumar

Hai, i want to make I2C communication between two stm32l073 mcu. i want to make one board as slave and other as master. I have attached the full code down please say where have i done mistake. For connection i used 2 10kohm resistor as external pull up.

Master code:

int main()
{
    uint32_t I2C3_OWN_ADDRESS = 0x5A;
    I2C3_Master_Init();
    Gpio_config();
    while(1)
    {
        I2C_Read_Reg(I2C3_OWN_ADDRESS,I2C3->TXDR);
        if(I2C3->RXDR == 0xA5)
        {
            GPIOC->ODR ^= (1 << 6);
        }
    }

}

void I2C3_Master_Init(void){
    
/* Enable the peripheral clock of GPIOC */
  RCC->IOPENR |= RCC_IOPENR_GPIOCEN;
    
  /* (1) PU for I2C signals */
  /* (2) open drain for I2C signals */
  /* (3) AF5 for I2C signals */
  /* (4) Select AF mode (10) on PB13 and PB14 */
  GPIOC->OTYPER |= GPIO_OTYPER_OT_0 | GPIO_OTYPER_OT_1; /* (2) */
  GPIOC->AFR[0] = (GPIOC->AFR[0] & ~((0xF << ( 5 * 4 )) | (0xF << ( 6 * 4 )))) \
                  | (7 << ( 5 * 4 )) | (7 << ( 6 * 4 )); /* (3) */
  GPIOC->MODER = (GPIOC->MODER & ~(GPIO_MODER_MODE0 | GPIO_MODER_MODE1)) \
                 | (GPIO_MODER_MODE0_1 | GPIO_MODER_MODE1_1); /* (4) */                                                    /*(3)*/
    
/** GPIOB Setup
    *    Standard Mode @100kHz with I2CCLK = 16MHz, rise time = 100ns, fall time = 10ns.(1)
    *    Enable I2C1 peripheral.........................................................(2)
    */
    RCC->APB1ENR |= RCC_APB1ENR_I2C3EN; /* (1) */
  RCC->CCIPR &= ~RCC_CCIPR_I2C3SEL;
    I2C3->TIMINGR = (uint32_t)0x00300619;    /*(1)*/
    I2C3->CR1 |= I2C_CR1_PE;                            /*(2)*/
}

 

/**
  \fn                void Reset_I2C(void)
  \brief        I2C Reset, clears and then sets I2C_CR1_PE
*/

 

void Reset_I2C(void){
    int x = 0;        //1 to set bit, 0 to clear bit
    
    I2C3->CR1 ^= (-x ^ I2C3->CR1) & I2C_CR1_PE;        //Clear bit for reset
    I2C3->CR1 |= I2C_CR1_PE;
}

 

/**
  \fn                    uint32_t I2C_Read_Reg(uint32_t Register)
  \brief            Reads a register, the entire sequence to read (at least for HTS221)
    \param            uint32_t Device: The slave address of the device
    \param            uint32_t Register: The Register to read from
    \returns        uint32_t I2C1_RX_Data: The data read
*/

 

uint32_t I2C_Read_Reg(uint32_t Device,uint32_t Register){
    
    //Reset CR2 Register
    I2C3->CR2 = 0x00000000;
    
    //Check to see if the bus is busy
    while((I2C3->ISR & I2C_ISR_BUSY) == I2C_ISR_BUSY);
    
    //Set CR2 for 1-byte transfer for Device
    I2C3->CR2 |=(1UL<<16) | (Device<<1);
    
    //Start communication
    I2C3->CR2 |= I2C_CR2_START;
    
    //Check Tx empty before writing to it
    if((I2C3->ISR & I2C_ISR_TXE) == (I2C_ISR_TXE)){
        I2C3->TXDR = Register;
    }
    
    //Wait for transfer to complete
    while((I2C3->ISR & I2C_ISR_TC) == 0);

 

    //Clear CR2 for new configuration
    I2C3->CR2 = 0x00000000;
    
    //Set CR2 for 1-byte transfer, in read mode for Device
    I2C3->CR2 |= (1UL<<16) | I2C_CR2_RD_WRN | (Device<<1);
    
    //Start communication
    I2C3->CR2 |= I2C_CR2_START;
    
    //Wait for transfer to complete
    while((I2C3->ISR & I2C_ISR_TC) == 0);
    
    //Send Stop Condition
    I2C3->CR2 |= I2C_CR2_STOP;
    
    //Check to see if the bus is busy
    while((I2C3->ISR & I2C_ISR_BUSY) == I2C_ISR_BUSY);

 

    //Clear Stop bit flag
    I2C3->ICR |= I2C_ICR_STOPCF;
    
    return(I2C3_RX_Data);
}

Slave code:

int main(void)
{
  Configure_GPIO_I2C3();
  Configure_I2C3_Slave();
  while (1)
  {
        if(I2C3->RXDR == I2C3_OWN_ADDRESS)
        {
            if(I2C3->TXDR != I2C_BYTE_TO_SEND )
            {
            I2C3->TXDR = I2C_BYTE_TO_SEND;
            }
    }
  }
}

 


/**
  * Brief   This function :
             - Enables GPIO clock
             - Configures the I2C1 pins on GPIO PB6 PB7
  * Param   None
  * Retval  None
  */
__INLINE void Configure_GPIO_I2C3(void)
{
  /* Enable the peripheral clock of GPIOB */
  RCC->IOPENR |= RCC_IOPENR_GPIOCEN;

 

  /* (1) PU for I2C signals */
  /* (2) open drain for I2C signals */
  /* (3) AF1 for I2C signals */
  /* (4) Select AF mode (10) on PB6 and PB7 */
  GPIOC->AFR[0] = (GPIOC->AFR[0] & ~((0xF << ( 0 * 4 )) | ((uint32_t)0xF << ( 1 * 4 )))) \
                  | (7 << ( 0 * 4)) | (7 << (1 * 4)); /* (3) */
  GPIOC->MODER = (GPIOC->MODER & ~(GPIO_MODER_MODE0 | GPIO_MODER_MODE1)) \
                 | (GPIO_MODER_MODE0_1 | GPIO_MODER_MODE1_1); /* (4) */

 

}

 

/**
  * Brief   This function configures I2C1, slave.
  * Param   None
  * Retval  None
  */
__INLINE void Configure_I2C3_Slave(void)
{
  /* Configure RCC for I2C1 */
  /* (1) Enable the peripheral clock I2C1 */
  /* (2) Use APBCLK for I2C CLK */
  RCC->APB1ENR |= RCC_APB1ENR_I2C3EN; /* (1) */
  RCC->CCIPR &= ~RCC_CCIPR_I2C3SEL;
  /* Configure I2C1, slave */
  /* (3) Timing register value is computed with the AN4235 xls file,
         fast Mode @400kHz with I2CCLK = 16MHz, rise time = 100ns,
         fall time = 10ns */
  /* (4) Periph enable, address match interrupt enable, receive interrupt enable */
  /* (5) 7-bit address = 0x5A */
  /* (6) Enable own address 1 */
  I2C3->TIMINGR = (uint32_t)0x00300619; /* (3) */
  I2C3->CR1 = I2C_CR1_PE | I2C_CR1_ADDRIE; /* (4) */
  I2C3->OAR1 |= (uint32_t)(I2C3_OWN_ADDRESS << 1); /* (5) */
  I2C3->OAR1 |= I2C_OAR1_OA1EN; /* (6) */
 
}

Outcomes