2013-09-06 08:41 PM
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?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 ;}2013-10-31 06:05 AM
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.2020-12-01 01:06 PM
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?