Skip to main content
christoph23
Associate
April 28, 2015
Question

STM8 I2C Busy Bit is always 1

  • April 28, 2015
  • 2 replies
  • 1935 views
Posted on April 28, 2015 at 11:00

Hello,

I work with the

STM8S105K6

and

have tried

several

examples

of

ST

here

.

SDA

and SCL

have a

4.7K

pull-up

.

The line is

currently connected

only

with a

oscilloscope

.

Manually

I can let

toggling

the

corresponding pins

but

with

I2C

pins

remain

at 3.3V

.

After a long

debugging

I noticed

then that

the

Busy

bit is

always set

consistently

in all examples

.

Since I can not

find the problem

I

would appreciate

help

much.

Here's an

example of my

mind, I

should be able to

see

the broadcast

address on the

oscilloscope

.

Here a lidle Example

int main(void){

 I2C_Init();

 while(1){

 I2C_7BitAdresse();

 }

}

 void I2C_Init(){

 CLK->CKDIVR = 0x01;

 I2C->CR2 |=1 <<7;

 I2C->CR2 ^=1 <<7;        //Reset periphial clock

 GPIOB->ODR |= 0x30;             //define SDA, SCL outputs, HiZ, Open drain, Fast

  GPIOB->DDR |= 0x30;       //Bits 4 und 5 als Output,20MHz

  GPIOB->CR2 |= 0x30;

 #ifdef FAST_I2C_MODE

  I2C->FREQR = 16;               // input clock to I2C - 16MHz

  I2C->CCRL = 15;                // 900/62.5= 15, (SCLhi must be at least 600+300=900ns!)

  I2C->CCRH = 0x80;              // fast mode, duty 2/1 (bus speed 62.5*3*15~356kHz)

  I2C->TRISER = 5;               // 300/62.5 + 1= 5  (maximum 300ns)

 #else

  I2C->FREQR = 8;                // input clock to I2C - 8MHz

  I2C->CCRL = 40;                // CCR= 40 - (SCLhi must be at least 4000+1000=5000ns!)

  I2C->CCRH = 0;                 // standard mode, duty 1/1 bus speed 100kHz

  I2C->TRISER = 9;               // 1000ns/(125ns) + 1  (maximum 1000ns)

 #endif

  I2C->OARL = 0xA0;              // own address A0;

  I2C->OARH |= 0x40;

  //I2C->ITR = 1;                // enable error interrupts

  I2C->CR2 |= 0x04;              // ACK=1, Ack enable

  I2C->CR1 |= 0x01;              // PE=1

}

 void I2C_7BitAdresse(){

  while(I2C->SR3 &1 <<1){ //Busy Bit pollen

  I2C->CR2 |= 2;                           // STOP=1, generate stop

    while((I2C->CR2 & 2));              // wait until stop is performed

 }

  I2C->SR1 |=1; //Start Sequenz

  while(!(I2C->SR1 &1));  //wait for Start Sequenz   

  while(!(I2C->SR1 &1<<7)); 

  I2C->DR = (uint8_t)(SlaveAdress << 1); // Send Adress

  while(!(I2C->SR1 & 2));

 }

    This topic has been closed for replies.

    2 replies

    jro
    Associate III
    May 5, 2015
    Posted on May 05, 2015 at 10:33

    Hi there

    I'm using the STM8L, but if the hardware is similar then it looks as if you haven't enabled the peripheral clock:

    CLK->PCKENR1 |= CLK_PCKENR1_I2C1; // or something like that...

    If the peripheral isn't clocked none of the registers work!

    Cheers

    Jonathan

    Maddi.Mike
    Associate III
    June 25, 2015
    Posted on June 25, 2015 at 16:47

    UPDATE!!

    The problem turned out to be hardware. I am working on a prototype board and you know how EE's are. Us software guys always have to prove them wrong before they do anything. So I did not need the SWRST after all. Everything works great now.

    I am having the same problem with the BSY bit. I am using a STM8S208C which enables all peripheral clocks by default. The master clock is 16MHz. I can't get the I2C device to clock out anything. In the init function shown below, you will notice a line between the ''DEBUG'' comments. That's what I had to do to get the BSY bit to reset to zero.

    After the init, I try to send the address with:

       I2C->DR = 0x7C;

    and I see no clock output on the scope.

    Someone out there in STM8S land must have the I2C device working. Can you share your code?

    void I2C_Init()

    {

        // Set the input clock frequency (fmaster)

        I2C->FREQR = (u8)16;        // 16 MHz

        // Set the clock control register (CCR)

        I2C->CCRL = (u8)80;         // Provides an output clock of 100kHz...

        I2C->CCRH = (u8)0;          // ...at 50% duty cycle

        // Set the maximum rise time (1000 ns) + 1

        // 1000ns / clock Period + 1 = 0.000001 / (1/16000000) + 1 = 0.000001 / 0.0000000625 + 1 = 17

        I2C->TRISER = 17;

        // Enable the I2C device

        I2C->CR1 = I2C_CR1_PE;

        I2C->CR2 |= I2C_CR2_ACK;

    // ***************** DEBUG ++++++++++++++++++++++++++++++++++++++++

    I2C->CR2 |= I2C_CR2_SWRST;

    // ***************** DEBUG ----------------------------------------

        // Set the start bit to enter master mode

        PCF8566_start();

    }