1. adrenalina

    Thread Starter Active Member

    Jan 4, 2011
    Hello everyone. I am trying to program an STM8S003F3 I2C in master mode. I have setup up all of the registers, but when I start a transmission the start bit is sent, but both SDA and SCL stay low. The address is never sent. Here is part of the I2C code. Using the debugger I noticed the ADDR bit is never set and therefore it never gets past the while loop. It stays there forever. Does anyone what what I am missing in my code?
    Code (Text):
    2. void I2C_Init(){
    3.     I2C->CR1 &= ~I2C_CR1_PE;    // Disable peripheral
    4.     I2C->FREQR = 16;        // value equal to clock frequency (16MHz)
    5.     I2C->CCRL = 80;
    6.     I2C->TRISER = 17;
    7.     I2C->OARH |= I2C_OARH_ADDCONF;        // Has to be set to 1
    8.     I2C->CR1 |= I2C_CR1_PE;    // Enable peripheral
    9. }
    11. I2C_Init();
    12. I2C->CR2 |= I2C_CR2_START;        // Send start condition
    13. while(!(I2C->SR1 | I2C_SR1_SB)){}
    14. dummy = I2C->SR1;                            // Read SR1 to clear SB bit
    15. I2C->DR = 0x3D<<1;                        // Transmit address
    16. while(!(I2C->SR1 & I2C_SR1_ADDR)){} // Wait until address transmission is finished
    17. Clear_I2C_ADDR_Bit();                    // Clear ADDR bit
    Last edited: Nov 14, 2015
  2. adrenalina

    Thread Starter Active Member

    Jan 4, 2011
    I just noticed in the debugger that the SB bit is not being cleared by reading the SR1 register and then writing the DR register. According the the datasheet this should clear the bit. I don't know if this is causing the I2C to lockup.

    The BUSY and SML bit are set in the SR3 register, so the peripheral is entering master mode.
  3. eeabe


    Nov 30, 2013
    Seems like this:

    should be:

    while(!(I2C->SR1 & I2C_SR1_SB)){}

    if you are waiting for the bit to be set.
    adrenalina likes this.
  4. adrenalina

    Thread Starter Active Member

    Jan 4, 2011
    You are completely right. I decided to change my code to use interrupts and with interrupts it worked correctly. I just tested my old code using the polling method changing the OR to an AND and it also worked.
    I can't believe I missed that.