I2C STM8

Thread Starter

adrenalina

Joined Jan 4, 2011
78
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:
void I2C_Init(){
    I2C->CR1 &= ~I2C_CR1_PE;    // Disable peripheral
    I2C->FREQR = 16;        // value equal to clock frequency (16MHz)
    I2C->CCRL = 80;
    I2C->TRISER = 17;
    I2C->OARH |= I2C_OARH_ADDCONF;        // Has to be set to 1
    I2C->CR1 |= I2C_CR1_PE;    // Enable peripheral
}

I2C_Init();
I2C->CR2 |= I2C_CR2_START;        // Send start condition
while(!(I2C->SR1 | I2C_SR1_SB)){}
dummy = I2C->SR1;                            // Read SR1 to clear SB bit
I2C->DR = 0x3D<<1;                        // Transmit address
while(!(I2C->SR1 & I2C_SR1_ADDR)){} // Wait until address transmission is finished
Clear_I2C_ADDR_Bit();                    // Clear ADDR bit
i2c.png
 
Last edited:

Thread Starter

adrenalina

Joined Jan 4, 2011
78
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.
 

Thread Starter

adrenalina

Joined Jan 4, 2011
78
Seems like this:



should be:

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

if you are waiting for the bit to be set.
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.
 
Top