AnsweredAssumed Answered

Connect with LM75 through I2C/DMA on ST32100B

Question asked by tumati.pradeep on Jul 16, 2012
Latest reply on Jul 29, 2012 by helton.dave

Hi,

I am try to develop a simple I2C “receive data” type of function; I took most of the code from the zip file that I was able to download from the st webpages.

The main function of interest getBytesI2C1DMA() sends a “0” to the onboard LM75 and receives two bytes that contain the temperature information. I see the two temperature related bytes in the logic analyzer, but I don’t see the value getting copied into the LM75_BufferRX buffer. LM75_BufferRX[0] and LM75_BufferRX[1] are both reporting 0x0B and the final value that is stored in “tmp” is wrong. It looks like the DMA copy is failing. I have spent hours trying to figure out whats going wrong here. Can you please point me to the flaw in this code?

Any suggestions/advice is highly appreciated.

typedef enum
{
  TX = 0,
  RX = 1
} DMADirection_TypeDef;


uint16_t getBytesI2C1DMA(int address, int totalBytes)   //  <---- Problem FUNCTION
{  
  uint8_t LM75_BufferRX[10] ={1,1,0,0,0,0,0,0,0,0};
    
    if (totalBytes>10)
        return 0;
     
    sendByteI2C1(address, 0);
     
  // Configure DMA Peripheral
  DMA_Config(RX, (uint8_t*)LM75_BufferRX, totalBytes); 
   
  // Enable DMA NACK automatic generation
  I2C_DMALastTransferCmd(I2C1, ENABLE);
     
    // Send START condition a second time  
  I2C_GenerateSTART(I2C1, ENABLE);
   
  /* Test on SB Flag */
  I1C1_Timeout = FLAG_TIMEOUT;
  while (!I2C_GetFlagStatus(I2C1, I2C_FLAG_SB)) {
    if((I1C1_Timeout--) == 0) return 0;
  }
   
  /* Send LM75 address for read */
  I2C_Send7bitAddress(I2C1, address, I2C_Direction_Receiver);
   
 
  /* Test on ADDR Flag */
  I1C1_Timeout = FLAG_TIMEOUT;
  while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) {
    if((I1C1_Timeout--) == 0) return 0;
  }
 
  // Enable I2C DMA request
  I2C_DMACmd(I2C1,ENABLE);
     
    // Enable DMA RX Channel
  DMA_Cmd(DMA1_Channel7, ENABLE);
     
    // Wait until DMA Transfer Complete
  I1C1_Timeout = LONG_TIMEOUT;
  while (!DMA_GetFlagStatus(DMA1_FLAG_TC7)) {
    if((I1C1_Timeout--) == 0)
            return 0;
  
     
    // Send STOP Condition
  I2C_GenerateSTOP(I2C1, ENABLE);
     
    // Disable DMA RX Channel
  DMA_Cmd(DMA1_Channel7, DISABLE);
     
    // Disable I2C DMA request  
  I2C_DMACmd(I2C1, DISABLE);
     
    // Clear DMA RX Transfer Complete Flag
  DMA_ClearFlag(DMA1_FLAG_TC7);
     
  //!< Store LM75_I2C received data
 
  tmp = (uint16_t)(LM75_BufferRX[0] << 8);   <------- LM75_BufferRX[0] & [1] contain 0x0B which is not the value I see in the logic analyzer
  tmp |= LM75_BufferRX[1];   
     
 //!< Return Temperature value
  tmp=(uint16_t)(tmp >> 7);
    return tmp;
}

static void DMA_Config(DMADirection_TypeDef Direction, uint8_t* buffer, uint8_t NumData)
{
  DMA_InitTypeDef DMA_InitStructure;
   
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
   
  /* Initialize the DMA_PeripheralBaseAddr member */
  DMA_InitStructure.DMA_PeripheralBaseAddr = I2C1_BASE;
  /* Initialize the DMA_MemoryBaseAddr member */
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)buffer;
   /* Initialize the DMA_PeripheralInc member */
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  /* Initialize the DMA_MemoryInc member */
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  /* Initialize the DMA_PeripheralDataSize member */
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
  /* Initialize the DMA_MemoryDataSize member */
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
  /* Initialize the DMA_Mode member */
  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
  /* Initialize the DMA_Priority member */
  DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
  /* Initialize the DMA_M2M member */
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
   
  /* If using DMA for Reception */
  if (Direction == RX)
  {
    /* Initialize the DMA_DIR member */
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
     
    /* Initialize the DMA_BufferSize member */
    DMA_InitStructure.DMA_BufferSize = NumData;
     
    DMA_DeInit(DMA1_Channel7);
     
    DMA_Init(DMA1_Channel7, &DMA_InitStructure);
  }
   /* If using DMA for Transmission */
  else if (Direction == TX)
  {
    /* Initialize the DMA_DIR member */
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
     
    /* Initialize the DMA_BufferSize member */
    DMA_InitStructure.DMA_BufferSize = NumData;
     
    DMA_DeInit(DMA1_Channel6);
     
    DMA_Init(DMA1_Channel6, &DMA_InitStructure);
  }
}
 
 
int sendByteI2C1(int address, int byte)    
{
     /* Test on BUSY Flag */
  I1C1_Timeout = LONG_TIMEOUT;
    while (I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY)) if((I1C1_Timeout--) == 0) return 0;
   
    /* Enable the I2C peripheral */
  I2C_GenerateSTART(I2C1, ENABLE);
   
    // Test on SB Flag
  I1C1_Timeout = FLAG_TIMEOUT;
  while (!I2C_GetFlagStatus(I2C1,I2C_FLAG_SB))
      if((I1C1_Timeout--) == 0) return 0;
   
  /* Send device address for write */
  I2C_Send7bitAddress(I2C1, address, I2C_Direction_Transmitter);
   
  /* Test on ADDR Flag */
  I1C1_Timeout = FLAG_TIMEOUT;
  while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
      if((I1C1_Timeout--) == 0) return 0;
   
  
    I2C_SendData(I2C1, byte);
     
    /* Test on ADDR Flag */
  I1C1_Timeout = FLAG_TIMEOUT;
  while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING))  // EV-8
      if((I1C1_Timeout--) == 0) return 0;
     
    return 1;
}


This is how I initialize the I2C interface
void initI2C()
{
    I2C_InitTypeDef   I2C_InitStructure;
     
    //---------------------------------------------------------
    //-------------- Initialize GPIO
     GPIO_InitTypeDef  GPIO_InitStructure;
 
  /*!< I2C1 Periph clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
     
  /*!< LM75_I2C_SCL_GPIO_CLK, LM75_I2C_SDA_GPIO_CLK
       and LM75_I2C_SMBUSALERT_GPIO_CLK Periph clock enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOB, ENABLE);
   
  /*!< Configure I2C1 pins: SCL */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
 
  /*!< Configure I2C1 pins: SDA */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
 
  /*!< Configure I2C1 pin: SMBUS ALERT */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
    //-----------------------------------------------------------
     
     I2C_DeInit(I2C1);
     
    /*!< I2C1 Init */
  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  = L2C_SPEED;
  I2C_Init(I2C1, &I2C_InitStructure);
     
    /*!< Enable SMBus Alert interrupt */
  I2C_ITConfig(I2C1, I2C_IT_ERR, ENABLE);
 
  /*!< I2C1 Init */
  I2C_Cmd(I2C1, ENABLE);
 
}


Outcomes