cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4 - I2C Stuck Waiting for ADDR Bit

jookhai
Associate
Posted on September 07, 2013 at 05:41

Hi All,

I am having an issue with I2C transmission on the STM32F4. After successfully transmitting an address byte with values of 0xE.. , the ADDR bit (Address Transmission Complete) in the SR1 register is set.

However, this is not the case when transmitting address bytes starting with 0xF.. (e.g. 0xF0, 0xF2, 0xF4 - corresponding to I2C device addresses 0x78, 0x79, 0x80) - the ADDR bit does not get set, despite the slave acknowledging the I2C transaction.

Here are the specifics of the system under test ...

A scope shot and a code snippet of the transmit routine can be found below.

Note the invalid logic level after the ACK bit (Bus Master i.e. STM32F4 pulls the line low after a short line-idle spike).

To rule out pull-up issues or latch-up, I have attempted: (a) Pulling-up the lines to +3.3V from the STM32F4DISCOVERY, (b) Pulling-up the lines to the clean +5V rail that is powering the SRF08, (c) Using a proper level converter for I2C lines (i.e. Texas Instruments' PCA9306). There is no change in the symptoms observed.

Has anyone encountered such an issue, and how do I go about resolving it?

0690X00000602jNQAQ.jpg

CODE SNIPPET

void i2c_readAsMst (I2C_TypeDef* I2Cx, uint8_t slvBusAddr, uint8_t readAddr, uint8_t noOfBytes, uint8_t i2cRxData[])

{

uint8_t  byteCnt ;

uint16_t rubbish ;

/* Assert I2C START condition */

I2Cx->CR1 |= I2C_CR1_START ;

/* Wait for START condition to have been asserted */

while (!(I2Cx->SR1 & I2C_SR1_SB)) ;

/* Transmit I2C address of slave device */

/* This transaction is a WRITE operation */

I2Cx->DR = slvBusAddr << 1 ;

/* Wait for transmission to complete */

while (!(I2Cx->SR1 & I2C_SR1_ADDR)) ;

/* Clear ADDR flag to activate the internal Tx shift register */

rubbish = I2Cx->SR2 ;

/* Transmit the address of the first register for sequential reading */

I2Cx->DR = readAddr ;

/* Wait for I2C transmission to complete */

while (!(I2Cx->SR1 & I2C_SR1_BTF)) ;

/* Assert I2C RESTART condition */

I2Cx->CR1 |= I2C_CR1_START ;

/* Perform a dummy read to ensure the channel is clear for reception */

rubbish = I2Cx->DR ;

/* Wait for RESTART condition to have been asserted */

while (!(I2Cx->SR1 & I2C_SR1_SB)) ;

/* Transmit I2C address of slave device */

/* This transaction is a READ operation */

I2Cx->DR = ((slvBusAddr << 1) | 0x01) ;

/* Wait for transmission to complete */

while (!(I2Cx->SR1 & I2C_SR1_ADDR)) ;

/* Clear ADDR flag to activate the internal Rx shift register */

rubbish = I2Cx->SR2 ;

for (byteCnt=0; byteCnt<noOfBytes; byteCnt++)

{

// If there is only 1 byte left to read, send a NACK after reception of the byte

// Else, acknowledge the incoming received byte

if (noOfBytes - byteCnt == 1) I2Cx->CR1 &= ~(I2C_CR1_ACK) ;

else                          I2Cx->CR1 |= I2C_CR1_ACK    ;

/* Wait for a byte to be received over the I2C line */

while (!(I2Cx->SR1 & I2C_SR1_RXNE)) ;

i2cRxData[byteCnt] = I2Cx->DR ;

}

/* Set STOP bit in order to free I2C line after the receive transaction */

I2Cx->CR1 |= I2C_CR1_STOP ;

}

2 REPLIES 2
kai
Associate II
Posted on October 31, 2013 at 14:05

Hi,

the Slave Address is your the Problem. The valid Address Range for 8-Bit is from 0x08 to 0x77. The Range from 0x78 to 0x7f is reserved. The STM32 recongnize your Address automatical as 10-Bit Address. From there it will send in the next Byte the following 8-Bit from the Address (2-Bit are in the first Byte). I thing between this to Bytes the Master does not expect the Aknowledge from the Slave, therefore the internal State Machine from the I2C Master in the STM32 hangs-up.

​Hi,

we are facing the same issue on our device and we also think the reason is that we are using a reserved code for 10-Bit Address.

However, I don't understand why you say : I think between this to Bytes the Master does not expect the Aknowledge from the Slave, therefore the internal State Machine from the I2C Master in the STM32 hangs-up.

In I2C specification is said that slave sends an acknowledge every byte, so why should master not expect it?