AnsweredAssumed Answered

I2C read bytes problem

Question asked by wybranczyk.dominik on Oct 21, 2011
Latest reply on Oct 26, 2011 by wybranczyk.dominik
Hello, my name is Dominik. Im using STM32F103 for a long time, but 2 weeks ago i have to play with i2c for the first time.
Of course I have done my "homework" and read about it, use Reference manual, errata, examples etc.

After few days I manage to establish connection with sensors via I2C. But the problem is that while the initialization (sending init buffer to sensor) is going very good (because the led if blinking, with means that the sensor is doing the sampling), the reading is going very bad. I mean I receive only 1 byte, and the byte is 225 (decimal), and the 2nd byte is 0 whatever register I read.

The pull up : 4k7 to 3V3. 

The sequence (idea):
Init {
start();
send(addr_write);
send(register);
send(value); 
stop();
}

sensor_read{
enable_ack();
start()
send(addr_write);
send(register);
start(); // restart 
send(addr_read);
msb = read();
lsb = read();
disable_ack();
dummy = read();
stop();
enable_ack();
}


The real code : 

#define I2C_SPEED 1000
//todo przed chwila bylo 40 000


void I2C_Setup(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
    I2C_InitTypeDef  I2C_InitStructure;

    /*enable I2C*/
    I2C_Cmd(I2C1,ENABLE);

    /* I2C1 clock enable */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);

    /* I2C1 SDA and SCL configuration */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    //SCL is pin06 and SDA is pin 07 for I2C1


    /* I2C1 configuration */
    I2C_InitStructure.I2C_Mode = I2C_Mode_SMBusHost;
    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
    I2C_InitStructure.I2C_OwnAddress1 = 0x00;
    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    I2C_InitStructure.I2C_ClockSpeed = I2C_SPEED ;
    I2C_Init(I2C1, &I2C_InitStructure);

    /*!< Enable SMBus Alert interrupt */
    I2C_ITConfig(I2C1, I2C_IT_ERR, ENABLE);    //dont think this is necessary

}

void SFR08_GetChar(void)
{
     unsigned short zm1=0,zm2=0,zm3=0;

 /* ACK enable */
     I2C_AcknowledgeConfig(I2C1, ENABLE);
 /* Wait for i2c buss not bussy */
     while (I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY)); // Test on BUSY Flag

 /* Force sensor to get new values, and range in cm */
     I2C_GenerateSTART(I2C1,ENABLE);
          while(!I2C_GetFlagStatus(I2C1, I2C_FLAG_SB));


     I2C_SendData(I2C1, SFR_W); //same as I2C_Send7bitAddress(I2C1, SFR_W, I2C_Direction_Transmitter);
          while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));// Test on ADDR Flag


     I2C_SendData(I2C1, 0x00); // chose register 0x00
          while(!I2C_GetFlagStatus(I2C1,I2C_FLAG_TXE));


     I2C_SendData(I2C1, 0x51); // fill the 0x00 register with 0x51 to range in cm
          while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED));


     I2C_GenerateSTOP(I2C1, ENABLE);
          while(I2C_GetFlagStatus(I2C1, I2C_FLAG_STOPF)); // stop bit flag


     delay_ms(100); // minimum 64 ms, conversion time for sensor


  /* Get new values */

     zm1  = (uint16_t)SFR08ReadShort(0x01); // read form register 0x01 // just this one would be enough
     zm2  = (uint16_t)SFR08ReadShort(0x02); // read from register 0x02
     zm3  = (uint16_t)SFR08ReadShort(0x03); // read form register 0x03
}


long SFR08ReadShort(unsigned char address1)
{
     uint8_t msb=0, lsb=0; // unsigned char
     unsigned char dummy1;//dummy2;
     unsigned short data;


I2C_AcknowledgeConfig(I2C1, ENABLE);
// Test on BUSY Flag
while (I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY));


I2C_GenerateSTART(I2C1, ENABLE);
          while(!I2C_GetFlagStatus(I2C1, I2C_FLAG_ADDR));


I2C_SendData(I2C1,SFR_W);     // write 0xEE <- write
          // Test on ADDR Flag
          while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));


I2C_SendData(I2C1,address1);     // write register address
          while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED));


/* restart */
I2C_GenerateSTART(I2C1, ENABLE);
          while(!I2C_GetFlagStatus(I2C1, I2C_FLAG_SB));


I2C_SendData(I2C1,SFR_R);     // write 0xEF <- READ  // same as send 7bit add
          while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));

/* Receive */
     msb =     I2C_ReceiveData(I2C1);
          while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)); // wait for 


     lsb = I2C_ReceiveData(I2C1);
          while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));

// just in case , i get 3 bytes, but the 3rd is 0x00 too.

/* before last one, disable ACK */
          I2C_NACKPositionConfig(I2C1, I2C_NACKPosition_Current);
          I2C_AcknowledgeConfig(I2C1, DISABLE);


     dummy1 =     I2C_ReceiveData(I2C1);
          while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));


     I2C_GenerateSTOP(I2C1, ENABLE);
          while(I2C_GetFlagStatus(I2C1, I2C_FLAG_STOPF)); // stop bit flag


     data  = msb<<8;
     data |= lsb;

     return data;
}

Is there anything wrong? The same situation is with secound sensor on bus. But the values there are like -4010, while should me about +100 to +1200.

Thank you for your time.

Outcomes