Go Down

Topic: I2C slave read directly after write NAK'ing (Read 95 times) previous topic - next topic

beenjaminnn

Jul 22, 2015, 12:59 am Last Edit: Jul 22, 2015, 01:13 am by beenjaminnn
Hi there,

I'm using an Arduino Uno as an I2C slave and I'm having trouble getting it working. If I initiate a read directly after a write from the master I always receive a NAK. I have attached my code and a screenshot of the communication.

Code: [Select]

#include <Wire.h>

void setup()
{
  Wire.begin(0x0E);
  Wire.onRequest(requestEvent); // register event
  Wire.onReceive(receiveEvent); // register event
}

void loop()
{
}

void requestEvent()
{
  uint8_t reply = 0x01;
  Wire.write(&reply, sizeof(reply));
}

void receiveEvent(int howMany)
{
  while (Wire.available() > 1)
  {
    char c = Wire.read(); // receive byte as a character
  }
}




The bus is running at 400kHz. Individual reads and writes seem to work fine.

Thanks!
Ben

RayLivingston

I2C and SPI devices vary all over the map in terms of what sequences of operations they support.  You need to read the data sheet for that specific device, and see what I2C sequences it allows.

Regards,
Ray L.

beenjaminnn

The chip I'm using (ATMEGA328) has an I2C peripheral supports Fast Mode. What do you mean by sequences?

RayLivingston

The chip I'm using (ATMEGA328) has an I2C peripheral supports Fast Mode. What do you mean by sequences?
You say individual reads and writes work fine, but a read immediately following a write does not work.  Perhaps the chip does not ALLOW a read to immediately follow a write.  As I said, I2C devices vary all over the map in terms of which specific features of I2C they support.  Some are VERY basic and, for instance, may only allow a single read per transaction, with not burst reads.  Others may not allow a read and write within the same transaction.  You have to read the data sheet for the slave device to see what it supports, and what it does not support.

Regards,
Ray L.

chucktodd

Hi there,

I'm using an Arduino Uno as an I2C slave and I'm having trouble getting it working. If I initiate a read directly after a write from the master I always receive a NAK. I have attached my code and a screenshot of the communication.

The bus is running at 400kHz. Individual reads and writes seem to work fine.

Thanks!
Ben
Ben,
   The Default Wire library sets the I2C to 100khz.  Change the TWBR for 400k

Code: [Select]


void setup(){
  Wire.begin(0x0e);
 
  TWBR = ((F_CPU / 400000L) - 16) / 2;
}


It could be missing the bit spacing, where it detects the transitions.

I don't know if the hardware will change the sample point base on the received clock, or the defined bitclock?

chuck.
 

beenjaminnn

Hi there,

I think the problem is that the Wire library is too slow. There isn't any difference between what I'm doing and doing individual reads and writes except the time between transactions.



The reason I believe the Wire library is too slow is because it seems to be holding SCLA low for quite a long time between bytes in the picture I posted.

Chuck: I tried it changing TWBR with no luck. I think that register defines the bitrate for a master.

Thanks!
Ben

RayLivingston

Unless it's a poorly designed slave, it should not care about timing.  I2C operates entirely based on clock edges.  Timing should be irrelevent, as long as it is not too fast for the slave.  ANY I2C should work correctly at 100kHz.  There is no guarantee any slave will work at a higher clock rate unless the manufacturer data sheet indicates it will.

Regards,
Ray L.

beenjaminnn

#7
Jul 22, 2015, 03:12 am Last Edit: Jul 22, 2015, 03:13 am by beenjaminnn
The code I posted is the only code I am running and the data sheet for the chip I'm using claims that the I2C peripheral supports Fast Mode (400 kHz) operation. I'm not sure what else could be going wrong.

Thanks!
Ben

chucktodd

The code I posted is the only code I am running and the data sheet for the chip I'm using claims that the I2C peripheral supports Fast Mode (400 kHz) operation. I'm not sure what else could be going wrong.

Thanks!
Ben
Ben,
   I think you are correct.  To test your conjecture the library is too slow, put a digitalWrite() at each end of the receiveEvent() function and monitor that pin with your logic analyzer.

Until the receiveEvent() returns, the TWI interface is not placed back into the 'ready' state.  So your Write/read sequence is starting the read sequence while the TWI hardware is still process the last Write packet. the 'NAK' is just that no one is minding the store (I2C) buss while it is processing the prior packet.

Each clock cycle of the I2C bus (400k) is only 40 CPU clock cycles.  most opcodes use 1..2 cycles to execute so you are only executing maybe 300..400 opcodes during that extended clock cycle.

you might have to change the library code to speed up.

Chuck.

Go Up