Question
STM32F10xxx - I2C master receiving 2 bytes - NACK after first read byte
Posted on November 09, 2015 at 14:59
Hello,
I'm trying to write an I2C application that should read/write one or more bytes as master with polling mode. I'm able to write one ore more bytes and read one byte, but when I try to read 2 bytes after a single byte read the first call goes wrong; next 2 bytes read works! I'm try to explain better:- Perform a read of a byte.
- Start bit -> Send address 7bit (W) -> (receive ACK) -> Write register (1byte) -> (receive ACK) -> Stop
- Start bit -> Send address 7bit (R) -> (receive ACK) -> (Read value (1byte)) -> send NACK -> Stop
- Perform a read of two bytes. (This FAIL)
- Start bit -> Send address 7bit (W) -> (receive ACK) -> Write register (1byte) -> (receive ACK) -> Stop
- Start bit -> Send address 7bit (R) -> (receive ACK) -> (Read value (1byte)) ->
send NACK (WRONG) -> (Read value (1byte) => WRONG)
-> send NACK -> Stop
- Perform a read of two bytes. (Same request now works)
- Start bit -> Send address 7bit (W) -> (receive ACK) -> Write register (1byte) -> (receive ACK) -> Stop
- Start bit -> Send address 7bit (R) -> (receive ACK) -> (Read value (1byte)) ->
send ACK (OK) -> (Read value (1byte))
-> send NACK -> Stop
- Send START
- Send ADDR
Set POS and ACK
Wait ADDR flag
- Clear ADDR and ACK
- Wait BTF flag
- Program STOP
- Read DR twice
- Send START
- Send ADDR
Wait ADDR flag
Set POS
- Disable interrupts
- Clear ADDR and ACK
- Enable interrupts
- Wait BTF flag
- Disable interrupts
- Program STOP
- Read DR (byte 1)
- Enable interrupts
- Read DR (byte 2)
- Wait STOP flag is cleared
- Reset POS
- Set ACK
I2Cx->CR2 |= I2C_IT_ERR;
I2C_GenerateSTART(I2Cx, ENABLE);
WAIT_FOR_CONDITION_OR_RESET_ON_TIMEOUT(I2C_GetFlagStatus(I2Cx, I2C_FLAG_SB) == SET);
I2C_Send7bitAddress(I2Cx, (uint8_t)(i2c_addr <<
1
), dir);
WAIT_FOR_CONDITION_OR_RESET_ON_TIMEOUT(I2C_GetFlagStatus(I2Cx, I2C_FLAG_ADDR) == SET);
/* Clear ACK bit */
I2C_AcknowledgeConfig(I2Cx, DISABLE);
/* Disable all active IRQs around ADDR clearing and STOP programming because the EV6_3
software sequence must complete before the current byte end of transfer */
__disable_irq();
/* Clear ADDR flag */
CLEAR_REGISTER(I2Cx->SR1); //TODO:BASCETTA:TEST: Aggiunto da me
CLEAR_REGISTER(I2Cx->SR2);
/* Program the STOP */
I2C_GenerateSTOP(I2Cx, ENABLE);
/* Re-enable IRQs */
__enable_irq();
WAIT_FOR_CONDITION_OR_TIMEOUT(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BTF) == SET);
/* Disable IRQs around STOP programming and data reading because of the limitation ?*/
__disable_irq();
/* Program the STOP */
I2C_GenerateSTOP(I2Cx, ENABLE);
/* Read first data */
bytes[i] = I2C_ReceiveData(I2Cx);
i++;
/* Re-enable IRQs */
__enable_irq();
/* Read second data */
bytes[i] = I2C_ReceiveData(I2Cx);
i++;
/* Make sure that the STOP bit is cleared by Hardware before CR1 write access */
//WAIT_FOR_CONDITION_OR_TIMEOUT((I2Cx->CR1 & I2C_CR1_STOP) == I2C_CR1_STOP);
WAIT_FOR_CONDITION_OR_TIMEOUT((I2Cx->CR1 & I2C_CR1_STOP) == 0);
/* Enable Acknowledgement to be ready for another reception */
I2C_AcknowledgeConfig(I2Cx, ENABLE);
/* Clear POS bit */
I2C_NACKPositionConfig(I2Cx, I2C_NACKPosition_Current);
Could you help me to find my mistake??
Thank you for your replies,
Regards
#i2c #master-receiving #stm32