cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L151 + TMP100 temp sensor ==> I2C always busy

David Rodenas
Associate II
Posted on July 15, 2017 at 13:09

Hello everyone, 

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

I have a TI

http://www.ti.com/lit/ds/sbos231i/sbos231i.pdf

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

2 REPLIES 2
S.Ma
Principal
Posted on July 15, 2017 at 13:49

Check if the slave address value input to the function is properly shifted, a classic check. Then start first by sw i2c using gpios. There are examples of pseudo code for it. Then use the hw i2c and compare.

Posted on July 15, 2017 at 13:56

KIC8462852 EPIC204278916 wrote:

Check if the slave address value input to the function is properly shifted, a classic check. Then start first by sw i2c using gpios. There are examples of pseudo code for it. Then use the hw i2c and compare.

Hi, 

Thanks for your prompt reply... I just did so.. and yeah, I had to shift the address. It turns out that the correct address is 0x92... and not 0x49

Now, new problem, as I usually do when testing, the above code is followed by the termination of the i2c communications. Simply:

/* Wait until BTF Flag is set before generating STOP */

Timed(!I2C_GetFlagStatus(I2Cx, I2C_FLAG_BTF));

/* Send STOP Condition */

I2C_GenerateSTOP(I2Cx, ENABLE);

/* Test STOP flag */

Timed(I2C_GetFlagStatus(I2Cx, I2C_FLAG_STOPF));

BTF flag (

I2C_FLAG_BTF) 

seems to be always reset, so that I cannot send the stop condition. This is the very first time I see this kind of problem. Any insights?