AnsweredAssumed Answered

Reading 2 bytes from ADT7410 via I2C

Question asked by Mike U on May 6, 2014
Latest reply on May 12, 2014 by Mike U
I've been working for a few days to get a STM32F401 Discovery top talk to an external ADT7410 temperature sensor. I'm just about there. I'm able to read a byte at a time from the device. The last thing I'm having a hard time with is reading 16 bits at a time. The device has this capability, I just need to give it the address of the high byte and I can read the low byute right after the high byte. I don't think I quite understand what calls to use in the Standard Periph Library to do this. Here is the code to do this, I left out some of the beginning part to keep it short.


     /* Send ADT7410 register address */
     I2C_SendData(I2C1,addr);
 
     /* Test on I2C1 EV8 and clear it */
     timeout = ADT7410_TIMEOUT_MAX; /* Initialize timeout value */
     while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
     {
          /* If the timeout delay is exeeded, exit with error code */
          if ((timeout--) == 0) 
          {
               return ERROR;
          }
     }
 
  /* Generate the Start Condition */
  I2C_GenerateSTART(I2C1, ENABLE);
 
  /* Test on I2C1 EV6 and clear it */
  timeout = ADT7410_TIMEOUT_MAX; /* Initialize timeout value */
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT))
  {
    /* If the timeout delay is exeeded, exit with error code */
          if ((timeout--) == 0) 
          {
               return ERROR;
          }
  } 
 
  I2C_Send7bitAddress(I2C1, ADT7410_ADDRESS, I2C_Direction_Receiver);
 
  /* Test on I2C1 EV6 and clear it */
  timeout = ADT7410_TIMEOUT_MAX; /* Initialize timeout value */
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
  {
    /* If the timeout delay is exeeded, exit with error code */
          if ((timeout--) == 0) 
          {
               return ERROR;
          }
  }  
 
If I was only doing one byte I would use I2C_Acknowledge here as is shown commented out and that works.

Is this the right call to use? I think it is based on info from the Reference Manual and from commenst in stm32f4xx_i2c.c.


     I2C_NACKPositionConfig(I2C1, I2C_NACKPosition_Next);
  /* Prepare an NACK for the next data received */
  // I2C_AcknowledgeConfig(I2C1, DISABLE);  
 
  /* Test on I2C1 EV7 and clear it */
  timeout = ADT7410_TIMEOUT_MAX; /* Initialize timeout value */
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED))
  {
    /* If the timeout delay is exeeded, exit with error code */
          if ((timeout--) == 0) 
          {
               return ERROR;
          }
  }
 
  /* Receive high byte of Data */
  data_high = I2C_ReceiveData(I2C1);
 
     // Read low byte of Data
     
  /* Prepare an NACK for the next data received */
Do I need to call this again?
  I2C_AcknowledgeConfig(I2C1, DISABLE);  
 
  /* Test on I2C1 EV7 and clear it */
  timeout = ADT7410_TIMEOUT_MAX; /* Initialize timeout value */
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED))
  {
    /* If the timeout delay is exeeded, exit with error code */
          if ((timeout--) == 0) 
          {
               return ERROR;
          }
  }
 
  /* Receive the Data */
  data_low = I2C_ReceiveData(I2C1);
     
     // Build 16 bit data word
     *read_data = (uint16_t) data_high;
     *read_data <<= 8;
     *read_data += (uint16_t) data_low;
     
  I2C_GenerateSTOP(I2C1, ENABLE);


  /* return the read data */
  return SUCCESS;     
}

Hopefully the comments I made in red and italicized will show up.

I'd appreciate any comments on this.

Thanks.

Mike



Outcomes