AnsweredAssumed Answered

STM32L151 + TMP100 temp sensor ==> I2C always busy

Question asked by David Rodenas on Jul 15, 2017
Latest reply on Jul 15, 2017 by David Rodenas

Hello everyone, 

 

I have looked up this issue but I am afraid I have been unable to find a solution. 

 

I have a TI TMP100 temperature sensor connected to a stm32l151 MCU by way of I2C1. The initialisation code of the I2C bus is fairly standard (I am using the STM32 standard library), as seen below:

 

I2C_InitTypeDef I2C_InitStructure;

GPIO_InitTypeDef GPIO_InitStructure;

 

/* Enable GPIOB (SDA and SCL) clocks */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);

 

/* Configure I2C clock and GPIO */
GPIO_StructInit(&GPIO_InitStructure);

 

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

 

/* Configure I2C1 SCL and SDA pins */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStructure);

 

/* Connect I2C1 pins to AF */
GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_I2C1); // SCL
GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_I2C1); // SDA

 

/* I2C1 Reset */
RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, ENABLE);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, DISABLE);

 

/* Configure I2C */

I2C_StructInit(&I2C_InitStructure);
I2C_InitStructure.I2C_ClockSpeed = 400000;
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
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_Init(I2C1, &I2C_InitStructure);

 

 

After executing the above code, I try to test the i2c bus by way of the following code:

/* Test on BUSY Flag */
Timed(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));

 

/* Enable the I2C peripheral */
I2C_GenerateSTART(I2C1, ENABLE);

 

/* Test on EV5 and clear it (cleared by reading SR1 then writing to DR) */
Timed(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));

 

/* Send device address for write */
I2C_Send7bitAddress(I2C1, slaveAddress, I2C_Direction_Transmitter);


/* Test on EV6 and clear it */
Timed(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

where:

#define Timed(x)                          \
   Timeout = 0xFFFF;                   \
   while ( x )                                   \
   {                                                 \
      if (Timeout-- == 0) return 1;    \
   } 

and slaveAddress is any of the following tmp100 addresses (0x48, 0x49, ..., 0x4F). At this point I am trying all of them, though it should be 0x4A.

 

Anyhow, as you might suspect, it is not working.

 

At the beginning, I wasn't able to generate the START condition, I2C_FLAG_BUSY seemed to be always set to RESET. Checking the datasheet, it turned out that pull-up resistors were necessary on SCL and SDA lines. I added two 4.7KOhm resistors, one connected to SCL and another to SDA, and both to VCC. Apparently, the problem was solved, However, 

Timed(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

always returns error ("fires" Timed).

 

My guess... perhaps I am trying to communicate with the device using the wrong address. But I am following the tmp100 datasheet, so I don't understand why it doesn't work.

 

I have tried this with two different TMP100 devices, and I always get the same result.

 

Any advice would be very welcome. Many thanks

 

Best wishes,

 

David

Outcomes