2008-11-16 09:38 PM
I2C: How to generate a delay between NACK and STOP?
2011-05-17 03:52 AM
Hello,
I'm frustrated since I can't make running correctly my I2C comminication between the STM32 and a MCP23016 I/O Expander. I tried it for some days. Writing the MCP23016's registers is possible but reading is a problem: The MCP23016 is designed to write/read 16-bit registers (pairs of two 8-bit registers). It isn't possible to read or write a single 8-bit register. And it needs a delay of 12 microseconds (us) at least after every 9th clock pulse. (The bus must remain free in this time.) - I can generate this delay in the writing sequence. In the reading sequence it is possible too, unless between the second (= last) data byte and the STOP condition. How can I do that?? When I set the STOP bit before Event 7 occurs then the STOP condition is generated by the STM32 after the 9th clock pulse (NACK) immediately. The MCP23016 doesn't seem to care about the STOP. A further communication isn't possible. Thats the code: ----------------------------- I2C_GenerateSTART( I2C1, ENABLE ); while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_MODE_SELECT ) ); // EV5 Wait15us(); I2C_Send7bitAddress( I2C1, I2C_ADR_IOEXPANDER, I2C_Direction_Receiver ); while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED ) ); // EV6 Wait15us(); while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED ) ); // EV7 *DatenbyteReg1 = I2C_ReceiveData( I2C1 ); Wait15us(); I2C_AcknowledgeConfig( I2C1, DISABLE ); // Disable Ack. for closing the comm. with NACK I2C_GenerateSTOP( I2C1, ENABLE ); while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED ) ); // EV7 *DatenbyteReg2 = I2C_ReceiveData( I2C1 ); Wait15us(); I2C_AcknowledgeConfig(I2C1, ENABLE); // For further communication ----------------------------- See the attached scope screenshot StopBeforeEV7.gif! Channel A is the SDA line and ch. B is the SCL line. I2C_ADR_IOEXPANDER is 0x44 (0100010x). The first register holds 0x55, the second register 0x3F. When I set the STOP bit after reading the second data byte then after the 8 data bits and the 9th clock pulse (NACK) follows a 10th clock pulse immediately, then a pause of about 30 us with SCL = Low and SDA = High, then further 8 clock pulses followed by a STOP. - The STM32 seems to request the NACK'd byte once more. Thats the code: ----------------------------- I2C_GenerateSTART( I2C1, ENABLE ); while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_MODE_SELECT ) ); // EV5 Wait15us(); I2C_Send7bitAddress( I2C1, I2C_ADR_IOEXPANDER, I2C_Direction_Receiver ); while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED ) ); // EV6 Wait15us(); while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED ) ); // EV7 *DatenbyteReg1 = I2C_ReceiveData( I2C1 ); Wait15us(); I2C_AcknowledgeConfig( I2C1, DISABLE ); // Disable Ack. for closing the comm. with NACK while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED ) ); // EV7 *DatenbyteReg2 = I2C_ReceiveData( I2C1 ); Wait15us(); I2C_GenerateSTOP( I2C1, ENABLE ); I2C_AcknowledgeConfig(I2C1, ENABLE); // For further communication ----------------------------- See the attached scope screenshot StopAfterRead.gif! Same Addresses and register content like above. The first part of the address sending is cropped at the screenshot. Is there any possibility to generate the needed sequence for the last data byte (8 data bits, NACK at 9th clock pulse, > 12 us delay, STOP)?? Any help is appreciated. Thanks in advance, Norbert