Communication EFR32FG14 with SI7021 using I2C

Status
Not open for further replies.

yefj

Advanced Member level 5
Joined
Sep 12, 2019
Messages
1,505
Helped
1
Reputation
2
Reaction score
5
Trophy points
38
Activity points
9,113
Hello,I have tried to follow the I2C diagram of Si7021 bellow step by step .
first from the starter kit manuak my SDA and SCL is P13 and P12 on my board respectivly which is location 15 in the datasheet page 150 table shown bellow.
I have been writing and reading exactly by the registers in the reference manual shown bellow.
i have test if one step accomplished before going to the next step as shown in the code bellow every line has a comment regarding which step its in the I2C diagram.
the real connection is shown bellow.I am sending this whole procedure over and over in while(1) loop.
And i get only Noise no digital behavior at all on my scope.
Where did i go wrong?
Thanks.
EFR32FG14 starter kit manual
Si7021 sensor page 20
Efr32fg14 reference manual
Efr32fg14 data sheet page 150











Code:
#include <stdio.h>
#include "em_device.h"
#include "em_chip.h"
#include "em_i2c.h"
#include "em_cmu.h"
#include "em_emu.h"
#include "em_gpio.h"
#include "bsp.h"


// Buffers
uint8_t i2c_txBuffer[] = "Gecko";
uint8_t i2c_txBufferSize = sizeof(i2c_txBuffer);
uint8_t MS_Byte;
uint8_t LS_Byte;
uint8_t checksum;
int flag_2nd_step=0;
int flag_3rd_step=0;

/**************************************************************************//**
* @brief  Starting oscillators and enabling clocks
*****************************************************************************/
void initCMU(void)
{
  // Enabling clock to the I2C, GPIO, LE
  CMU_ClockEnable(cmuClock_I2C0, true);
  CMU_ClockEnable(cmuClock_GPIO, true);
  CMU_ClockEnable(cmuClock_HFLE, true);

  // Starting LFXO and waiting until it is stable
  CMU_OscillatorEnable(cmuOsc_LFXO, true, true);
}



/**************************************************************************//**
* @brief  Setup I2C
*****************************************************************************/
void initI2C(void)
{
  // Using default settings
  I2C_Init_TypeDef i2cInit = I2C_INIT_DEFAULT;
  // Use ~400khz SCK
  i2cInit.freq = I2C_FREQ_FAST_MAX;

  // Using PC10 (SDA) and PC11 (SCL)
  GPIO_PinModeSet(gpioPortC, 10, gpioModeWiredAndPullUp, 1);
  GPIO_PinModeSet(gpioPortC, 11, gpioModeWiredAndPullUp, 1);

  //Si7021 switch on
  GPIO_PinModeSet(gpioPortD, 15, gpioModePushPull, 1);

  // Enable pins at location 15 as specified in datasheet
  I2C0->ROUTEPEN = I2C_ROUTEPEN_SDAPEN | I2C_ROUTEPEN_SCLPEN;
  I2C0->ROUTELOC0 = (I2C0->ROUTELOC0 & (~_I2C_ROUTELOC0_SDALOC_MASK)) | I2C_ROUTELOC0_SDALOC_LOC15;
  I2C0->ROUTELOC0 = (I2C0->ROUTELOC0 & (~_I2C_ROUTELOC0_SCLLOC_MASK)) | I2C_ROUTELOC0_SCLLOC_LOC15;

  // Initializing the I2C
  I2C_Init(I2C0, &i2cInit);


  }



int main(void)
{
  // Chip errata
  CHIP_Init();

  // Configuring clocks in the Clock Management Unit (CMU)
  initCMU();



  // Setting up i2c
  initI2C();
while(1)
{
  I2C0->CMD=I2C0->CMD|(1<<0); //step 1 start CMD

  I2C0->TXDATA=((I2C0->TXDATA)&(0xFF00))|(0x80); //step 2 sending sensor address with 0 write bit
  while(((I2C0->IF)&(1<<4))!=1){}//wait till command transfer ends TXBL flag

  if (((I2C0->IF)&(1<<6))==1)//if we recieve ACK send measure and read command //3rd step
        {
           I2C0->TXDATA=((I2C0->TXDATA)&(0xFF00))|(0xE3); //step 4 in diagram
           while(((I2C0->IF)&(1<<4))!=1){}//wait till command transfer ends TXBL flag


              if (((I2C0->IF)&(1<<6))==1)//if we recieve ACK after Measure CMD
              {
                 flag_2nd_step=1;
              }
        }

  else                       //if we recieve NACK  we send the previos command again
  {
      I2C0->TXDATA=((I2C0->TXDATA)&(0xFF00))|(0x80); //step 2 sending sensor adress with 0 write bit
      while(((I2C0->IF)&(1<<4))!=1){}//wait till command transfer ends TXBL flag
      flag_2nd_step=0;
  }

  if (flag_2nd_step==1) //step 3 second slave adress sending
  {
      I2C0->CMD=I2C0->CMD|(1<<0); //step 5 start CMD
      I2C0->TXDATA=((I2C0->TXDATA)&(0xFF00))|(0x81); //step 6 sending sensor adress with 1 read bit
      while(((I2C0->IF)&(1<<4))!=1){}//wait till command transfer ends TXBL flag
      flag_3rd_step=1;
  }

  if (flag_3rd_step==1)
    {
      while (((I2C0->IF)&(1<<11))==1){} // step 7 while bushold flag in high and We still in clock streching
    MS_Byte=I2C0->RXDATA; //step 8
    while(((I2C0->IF)&(1<<5))==1){}//wait till recieving is complete RXDATAV will turn to 0
    I2C0->CMD=I2C0->CMD|(1<<2); //send ACK to SLAVE
    LS_Byte=I2C0->RXDATA; //step 9
    while(((I2C0->IF)&(1<<5))==1){}//wait till recieving is complete RXDATAV will turn to 0
    I2C0->CMD=I2C0->CMD|(1<<2); //send ACK to SLAVE
    checksum=I2C0->RXDATA;//recieve Checksum byte
    I2C0->CMD=I2C0->CMD|(1<<3); //send NACK to SLAVE
    I2C0->CMD=I2C0->CMD|(1<<1); //send STOP to SLAVE
    }//end step 3 end


}//end while
}//end main
 

Attachments

  • 1604690331800.png
    90.9 KB · Views: 90

Hello, I have found one error where i did not check correctly the bit field of the IF register.
I have written the code in the basic low level fasion and i posted every link to the manual i used.
And i still miss something because its not responding.
Where did i go wrong?
Thanks.

Code:
#include <stdio.h>
#include "em_device.h"
#include "em_chip.h"
#include "em_i2c.h"
#include "em_cmu.h"
#include "em_emu.h"
#include "em_gpio.h"
#include "bsp.h"


// Buffers
uint8_t i2c_txBuffer[] = "Gecko";
uint8_t i2c_txBufferSize = sizeof(i2c_txBuffer);
uint8_t MS_Byte;
uint8_t LS_Byte;
uint8_t checksum;
int flag_2nd_step=0;
int flag_3rd_step=0;

/**************************************************************************//**
 * @brief  Starting oscillators and enabling clocks
 *****************************************************************************/
void initCMU(void)
{
  // Enabling clock to the I2C, GPIO, LE
  CMU_ClockEnable(cmuClock_I2C0, true);
  CMU_ClockEnable(cmuClock_GPIO, true);
  CMU_ClockEnable(cmuClock_HFLE, true);

  // Starting LFXO and waiting until it is stable
  CMU_OscillatorEnable(cmuOsc_LFXO, true, true);
}



/**************************************************************************//**
 * @brief  Setup I2C
 *****************************************************************************/
void initI2C(void)
{
  // Using default settings
  I2C_Init_TypeDef i2cInit = I2C_INIT_DEFAULT;
  // Use ~400khz SCK
  i2cInit.freq = I2C_FREQ_FAST_MAX;

  // Using PC10 (SDA) and PC11 (SCL)
  GPIO_PinModeSet(gpioPortC, 10, gpioModeWiredAndPullUp, 1);
  GPIO_PinModeSet(gpioPortC, 11, gpioModeWiredAndPullUp, 1);

  //Si7021 switch on
  GPIO_PinModeSet(gpioPortD, 15, gpioModePushPull, 1);

  // Enable pins at location 15 as specified in datasheet
  I2C0->ROUTEPEN = I2C_ROUTEPEN_SDAPEN | I2C_ROUTEPEN_SCLPEN;
  I2C0->ROUTELOC0 = (I2C0->ROUTELOC0 & (~_I2C_ROUTELOC0_SDALOC_MASK)) | I2C_ROUTELOC0_SDALOC_LOC15;
  I2C0->ROUTELOC0 = (I2C0->ROUTELOC0 & (~_I2C_ROUTELOC0_SCLLOC_MASK)) | I2C_ROUTELOC0_SCLLOC_LOC15;

  // Initializing the I2C
  I2C_Init(I2C0, &i2cInit);


  }



int main(void)
{
  // Chip errata
  CHIP_Init();

  // Configuring clocks in the Clock Management Unit (CMU)
  initCMU();
  


  // Setting up i2c
  initI2C();
while(1)
{
  I2C0->CMD=I2C0->CMD|(1<<0); //step 1 start CMD

  I2C0->TXDATA=((I2C0->TXDATA)&(0xFF00))|(0x80); //step 2 sending sensor address with 0 write bit
  while(((I2C0->IF)&(1<<4))!=1){}//wait till command transfer ends TXBL flag

  if (((I2C0->IF)&(1<<6))==1)//if we recieve ACK send measure and read command //3rd step
        {
           I2C0->TXDATA=((I2C0->TXDATA)&(0xFF00))|(0xE3); //step 4 in diagram
           while(((I2C0->IF)&(1<<4))!=1){}//wait till command transfer ends TXBL flag


              if (((I2C0->IF)&(1<<6))==1)//if we recieve ACK after Measure CMD
              {
                 flag_2nd_step=1;
              }
        }

  else                       //if we recieve NACK  we send the previos command again
  {
      I2C0->TXDATA=((I2C0->TXDATA)&(0xFF00))|(0x80); //step 2 sending sensor adress with 0 write bit
      while(((I2C0->IF)&(1<<4))!=1){}//wait till command transfer ends TXBL flag
      flag_2nd_step=0;
  }

  if (flag_2nd_step==1) //step 3 second slave adress sending
  {
      I2C0->CMD=I2C0->CMD|(1<<0); //step 5 start CMD
      I2C0->TXDATA=((I2C0->TXDATA)&(0xFF00))|(0x81); //step 6 sending sensor adress with 1 read bit
      while(((I2C0->IF)&(1<<4))!=1){}//wait till command transfer ends TXBL flag
      flag_3rd_step=1;
  }

  if (flag_3rd_step==1)
    {
      while (((I2C0->IF)&(1<<11))==1){} // step 7 while bushold flag in high and We still in clock streching
    MS_Byte=I2C0->RXDATA; //step 8
    while(((I2C0->IF)&(1<<5))==1){}//wait till recieving is complete RXDATAV will turn to 0
    I2C0->CMD=I2C0->CMD|(1<<2); //send ACK to SLAVE
    LS_Byte=I2C0->RXDATA; //step 9
    while(((I2C0->IF)&(1<<5))==1){}//wait till recieving is complete RXDATAV will turn to 0
    I2C0->CMD=I2C0->CMD|(1<<2); //send ACK to SLAVE
    checksum=I2C0->RXDATA;//recieve Checksum byte
    I2C0->CMD=I2C0->CMD|(1<<3); //send NACK to SLAVE
    I2C0->CMD=I2C0->CMD|(1<<1); //send STOP to SLAVE
    }//end step 3 end


}//end while
}//end main
 

Hi,

Do you have a scope? Or can you lend one?
It would be very useful to see the signal levels and timing.

Klaus
 

Hello Klauss,I have Have tried to test SDA and SCL with a scope but it only gives me the steady 3.3V vdd of GPIO,but as for the I2C its not sending anything at all threw those pins.
no action whatsoever ,i cant see why?
Thanks.



Code:
#include <stdio.h>
#include "em_device.h"
#include "em_chip.h"
#include "em_i2c.h"
#include "em_cmu.h"
#include "em_emu.h"
#include "em_gpio.h"
#include "bsp.h"


// Buffers
uint8_t i2c_txBuffer[] = "Gecko";
uint8_t i2c_txBufferSize = sizeof(i2c_txBuffer);
uint8_t MS_Byte;
uint8_t LS_Byte;
uint8_t checksum;
int flag_2nd_step=0;
int flag_3rd_step=0;

/**************************************************************************//**
* @brief  Starting oscillators and enabling clocks
*****************************************************************************/
void initCMU(void)
{
  // Enabling clock to the I2C, GPIO, LE
  CMU_ClockEnable(cmuClock_I2C0, true);
  CMU_ClockEnable(cmuClock_GPIO, true);
  CMU_ClockEnable(cmuClock_HFLE, true);

  // Starting LFXO and waiting until it is stable
  CMU_OscillatorEnable(cmuOsc_LFXO, true, true);
}



/**************************************************************************//**
* @brief  Setup I2C
*****************************************************************************/
void initI2C(void)
{
  // Using default settings
  I2C_Init_TypeDef i2cInit = I2C_INIT_DEFAULT;
  // Use ~400khz SCK
  i2cInit.freq = I2C_FREQ_FAST_MAX;

  // Using PC10 (SDA) and PC11 (SCL)
  GPIO_PinModeSet(gpioPortC, 10, gpioModeWiredAndPullUp, 1);
  GPIO_PinModeSet(gpioPortC, 11, gpioModeWiredAndPullUp, 1);

  //Si7021 switch on
  GPIO_PinModeSet(gpioPortD, 15, gpioModePushPull, 1);

  // Enable pins at location 15 as specified in datasheet
  I2C0->ROUTEPEN = I2C_ROUTEPEN_SDAPEN | I2C_ROUTEPEN_SCLPEN;
  I2C0->ROUTELOC0 = (I2C0->ROUTELOC0 & (~_I2C_ROUTELOC0_SDALOC_MASK)) | I2C_ROUTELOC0_SDALOC_LOC15;
  I2C0->ROUTELOC0 = (I2C0->ROUTELOC0 & (~_I2C_ROUTELOC0_SCLLOC_MASK)) | I2C_ROUTELOC0_SCLLOC_LOC15;

  // Initializing the I2C
  I2C_Init(I2C0, &i2cInit);


  }



int main(void)
{
  // Chip errata
  CHIP_Init();

  // Configuring clocks in the Clock Management Unit (CMU)
  initCMU();
 


  // Setting up i2c
  initI2C();
while(1)
{
  I2C0->CMD=I2C0->CMD|(1<<0); //step 1 start CMD

  I2C0->TXDATA=((I2C0->TXDATA)&(0xFF00))|(0x80); //step 2 sending sensor address with 0 write bit
  while(((I2C0->IF)&(1<<4))!=1){}//wait till command transfer ends TXBL flag

  if (((I2C0->IF)&(1<<6))==1)//if we recieve ACK send measure and read command //3rd step
        {
           I2C0->TXDATA=((I2C0->TXDATA)&(0xFF00))|(0xE3); //step 4 in diagram
           while(((I2C0->IF)&(1<<4))!=1){}//wait till command transfer ends TXBL flag


              if (((I2C0->IF)&(1<<6))==1)//if we recieve ACK after Measure CMD
              {
                 flag_2nd_step=1;
              }
        }

  else                       //if we recieve NACK  we send the previos command again
  {
      I2C0->TXDATA=((I2C0->TXDATA)&(0xFF00))|(0x80); //step 2 sending sensor adress with 0 write bit
      while(((I2C0->IF)&(1<<4))!=1){}//wait till command transfer ends TXBL flag
      flag_2nd_step=0;
  }

  if (flag_2nd_step==1) //step 3 second slave adress sending
  {
      I2C0->CMD=I2C0->CMD|(1<<0); //step 5 start CMD
      I2C0->TXDATA=((I2C0->TXDATA)&(0xFF00))|(0x81); //step 6 sending sensor adress with 1 read bit
      while(((I2C0->IF)&(1<<4))!=1){}//wait till command transfer ends TXBL flag
      flag_3rd_step=1;
  }

  if (flag_3rd_step==1)
    {
      while (((I2C0->IF)&(1<<11))==1){} // step 7 while bushold flag in high and We still in clock streching
    MS_Byte=I2C0->RXDATA; //step 8
    while(((I2C0->IF)&(1<<5))==1){}//wait till recieving is complete RXDATAV will turn to 0
    I2C0->CMD=I2C0->CMD|(1<<2); //send ACK to SLAVE
    LS_Byte=I2C0->RXDATA; //step 9
    while(((I2C0->IF)&(1<<5))==1){}//wait till recieving is complete RXDATAV will turn to 0
    I2C0->CMD=I2C0->CMD|(1<<2); //send ACK to SLAVE
    checksum=I2C0->RXDATA;//recieve Checksum byte
    I2C0->CMD=I2C0->CMD|(1<<3); //send NACK to SLAVE
    I2C0->CMD=I2C0->CMD|(1<<1); //send STOP to SLAVE
    }//end step 3 end


}//end while
}//end main
 

Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…