AnsweredAssumed Answered

Busy flag Set in I2C

Question asked by sd.pranathi on Nov 29, 2012
Latest reply on Feb 29, 2016 by gutierrez.guillermo
Hello all,

I am using STm32f2 series. I am programing Temperature sensor TMP006 interfaced to STM with I2C. The problem is ADDR bit is not set, though I am sending 0x40 which is the slave address of TMP006, and always the busy flag will be set.

Below is my I2C Configuration

void I2C_Config(void)
{

GPIO_InitTypeDef GPIO_InitStruct;
I2C_InitTypeDef  I2C_InitStruct;

GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_Pin =TEMP_I2C_SCL|TEMP_I2c_SDA;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStruct);

GPIO_PinAFConfig(GPIOB,GPIO_PinSource6,GPIO_AF_I2C1);
GPIO_PinAFConfig(GPIOB,GPIO_PinSource7,GPIO_AF_I2C1);

I2C_InitStruct.I2C_ClockSpeed=I2C_SPEED;
I2C_InitStruct.I2C_Mode=I2C_Mode_I2C;
I2C_InitStruct.I2C_DutyCycle=I2C_DutyCycle_2;
I2C_InitStruct.I2C_OwnAddress1=0x00;
I2C_InitStruct.I2C_Ack=I2C_Ack_Enable;
I2C_InitStruct.I2C_AcknowledgedAddress=I2C_AcknowledgedAddress_7bit;
I2C_Init(I2C1,&I2C_InitStruct);
I2C_Cmd(I2C1,ENABLE);

}




uint32_t I2C_WrData(uint8_t DevAddr, uint8_t RegAddr, uint32_t data){
  //Write a single byte data to the given register address
 
  //Generate a Start condition
 I2C_GenerateSTART(I2C1,ENABLE);
 
  //Send I2C device Address and clear ADDR
I2C_Send7bitAddress(I2C1,TMP006_SLAVE_ADDRESS,I2C_Direction_Transmitter);
  (void) I2C1->SR2;   //EV6
 
  //Send Data
 I2C1->DR = data;  //EV8_1
  WaitSR1FlagsSet(I2C_SR1_BTF);  //wait till the data is actually written.
 
  //Generate Stop
I2C_GenerateSTOP(I2C1,ENABLE);
 
  //Wait to be sure that line is idle
  WaitLineIdle();
 
  return 0;
}

uint32_t I2C_RdData(uint8_t DevAddr, uint8_t RegAddr, uint8_t *buf, uint32_t cnt)
{
  //Reads "cnt" number of data starting from RegAddr
 
  //Send the Register Addres
 I2C_GenerateSTART(I2C1,ENABLE);
I2C_Send7bitAddress(I2C1,TMP006_SLAVE_ADDRESS,I2C_Direction_Transmitter);
  (void) I2C1->SR2;
  I2C1->DR = RegAddr;
  WaitSR1FlagsSet(I2C_SR1_BTF);
 
  //Start Reading
  I2C_RdBuf(DevAddr, buf, cnt);
 
  return 0;
}

uint32_t I2C_RdBuf (uint8_t DevAddr, uint8_t *buf, uint32_t cnt)
 {

 I2C_GenerateSTART(I2C1,ENABLE);
 
  //Send I2C Device Address
  I2C_Send7bitAddress(I2C1,TMP006_SLAVE_ADDRESS,I2C_Direction_Transmitter);
 
  if (cnt==1) {//We are going to read only 1 byte
    //Before Clearing Addr bit by reading SR2, we have to cancel ack.
    I2C1->CR1 &= (uint16_t)~((uint16_t)I2C_CR1_ACK);
   
    //Now Read the SR2 to clear ADDR
    (void)I2C1->SR2;
   
    //Order a STOP condition
    //If it is done before ADDR is set, a STOP is generated immediately as the clock is being streched
    I2C1->CR1 |= I2C_CR1_STOP;
    //Be carefull that till the stop condition is actually transmitted the clock will stay active even if a NACK is generated after the next received byte.
   
    //Read the next byte
    I2C_Read(buf);
   
    //Make Sure Stop bit is cleared and Line is now Iddle
    WaitLineIdle();
   
    //Enable the Acknowledgement again
    I2C1->CR1 |= ((uint16_t)I2C_CR1_ACK);
  }
 
  else if (cnt==2) {  //We are going to read 2 bytes (See: Spec_p584)
    //Before Clearing Addr, reset ACK, set POS
    I2C1->CR1 &= (uint16_t)~((uint16_t)I2C_CR1_ACK);
    I2C1->CR1 |= I2C_CR1_POS;
   
    //Read the SR2 to clear ADDR
    (void)I2C1->SR2;
   
    //Wait for the next 2 bytes to be received (1st in the DR, 2nd in the shift register)
    WaitSR1FlagsSet(I2C_SR1_BTF);
    //As we don't read anything from the DR, the clock is now being strecthed.
   
    //Order a stop condition (as the clock is being strecthed, the stop condition is generated immediately)
    I2C1->CR1 |= I2C_CR1_STOP;
   
    //Read the next two bytes
    I2C_Read(buf++);
    I2C_Read(buf);
   
    //Make Sure Stop bit is cleared and Line is now Iddle
    WaitLineIdle();
   
    //Enable the ack and reset Pos
    I2C1->CR1 |= ((uint16_t)I2C_CR1_ACK);
    I2C1->CR1 &= (uint16_t)~((uint16_t)I2C_CR1_POS);
  }
  else { //We have more than 2 bytes.
    //Read the SR2 to clear ADDR
    (void)I2C1->SR2;
    
    while((cnt--)>3) {//Read till the last 3 bytes
      I2C_Read(buf++);
    }
   
    //3 more bytes to read. Wait till the next to is actually received
    WaitSR1FlagsSet(I2C_SR1_BTF);
    //Here the clock is strecthed. One more to read.
   
    //Reset Ack
    I2C1->CR1 &= (uint16_t)~((uint16_t)I2C_CR1_ACK);
   
    //Read N-2
    I2C_Read(buf++);
    //Once we read this, N is going to be read to the shift register and NACK is generated
   
    //Wait for the BTF
    WaitSR1FlagsSet(I2C_SR1_BTF); //N-1 is in DR, N is in shift register
    //Here the clock is stretched
   
    //Generate a stop condition
    I2C1->CR1 |= I2C_CR1_STOP;
   
    //Read the last two bytes (N-1 and N)
    //Read the next two bytes
    I2C_Read(buf++);
    I2C_Read(buf);
   
    //Make Sure Stop bit is cleared and Line is now Iddle
    WaitLineIdle();
   
    //Enable the ack
    I2C1->CR1 |= ((uint16_t)I2C_CR1_ACK);
  }
 
  return 0;
}

static uint32_t I2C_Read(uint8_t *pBuf) {
    uint32_t err;
   
    //Wait till new data is ready to be read
    err=WaitSR1FlagsSet(I2C_SR1_RXNE);
       
    if (!err) {
      *pBuf = I2C1->DR;   //This clears the RXNE bit. IF both RXNE and BTF is set, the clock stretches
      return 0;
    }
    else {return err;}
 }

 

static uint32_t WaitLineIdle(void)
  //Wait till the Line becomes idle.
  {
  uint32_t TimeOut = HSI_VALUE;
  //Check to see if the Line is busy
  //This bit is set automatically when a start condition is broadcasted on the line (even from another master)
  //and is reset when stop condition is detected.
  while((I2C1->SR2) & (I2C_SR2_BUSY)) {
    if (!(TimeOut--)) {
      return I2C_TIMEOUT_ERROR;
    }
  }
   return 1;
  }

Any help in resolving the issue will be appreciated.

Thanks

Outcomes