cancel
Showing results for 
Search instead for 
Did you mean: 

I2C: How to generate a delay between NACK and STOP?

norbert2
Associate II
Posted on November 17, 2008 at 06:38

I2C: How to generate a delay between NACK and STOP?

1 REPLY 1
norbert2
Associate II
Posted on May 17, 2011 at 12:52

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