Keith Howell says:
"There are several critical points: Chiefly the R/W flag only holds the R/W bit of the slave address just after that byte has been received. After that, it holds the ACK bit of the last data byte received. Knowing this allows you to have interrupt-driven I2C (you have to keep a copy of the R/W bit to know the message direction on the next I2C interrupt). Also note that the SSP will interupt the CPU after every byte read by the I2C master is acknowledged. So your I2C master MUST remember to NACK the final byte. Otherwise your slave will lock up, thinking "hey, I sent the last message byte for the protocol, whats this interrupt for?". My I2C master (written by a colleague) does not, so I had to unstick the SSP by loading a dummy byte before operating the CKP bit. The first bit (MSB) of the an outgoing byte appear on the SDA pin as soon as the SSPBUF is loaded, so the MSB of the dummy byte must be high. While discovering that, I found that SCL rises as soon as CKP is operated, so I also needed a delay between loading SSPBUF and operating CKP, to satisfy the I2C data setup time. Microchip's app notes are a total crock. Use them as a 'spot the stupid mistake' exercise. These tips should save you the huge arseache of finding them out yourself. Believe me, it was a _long_ struggle."
I just had to provide feedback to the comments I just came accross for: 'Keith Howell says: '
His comments are wrong.1. An interrupt is generated by a slave PIC after every data byte sent. No matter if /ACK=1 or /ACK=0 by the Master. For example even on the last byte of data being sent from the slave the master will give /ACK=1 to signal no more. However, an interrupt will still be generated. The interrupt is just thought of as a signal to notify that an I2C event occurred.
2. The R/W bit DOES NOT change to last /ACK value. That statement is wrong. For example, during a transmission from the slave R/W=1 while the master is acknowledging /ACK=0. R/W =0 only when the master does not acknowledge /ACK=1.
I tested this out - and it is documented in AN734 application note and the 16c77x datasheet for example. (And my bench test).
Keith Howell says:
I was initially alarmed to find Michael''s message: if people found I'd made a mistake, I'd lose all respect as an engineer. Dogs would cross the street when the saw me coming. People might leave a loaded wire-wrap gun on my desk and expect me to do the honourable thing and wire-wrap my brains out!I made my statement around 1998, before AN734 was published. So I downloaded it and checked it out.
First of all, there is nothing in my statement that denies that interrupts happen after every byte transfer from PIC slave to I2C master. I said:
"SSP will interrupt the CPU after every byte read by the I2C master is acknowledged".
This statement is true whether this is a _positive_ or _negative_ acknowledgement (i.e. the /ACK pin is 0 or 1).
It might be argued that /ACK low means acknowledged, and /ACK floating means not-acknowledged. Personally I think it was just badly named: it doesn't mean acknowledgement in the conventional sense of "I the master acknowledge receipt of this byte". It is arguably better to think of it as a final-byte flag, that the slave can use to know whether to send another byte or not.
Secondly, when MB said
"The R/W bit DOES NOT change to last /ACK value."
He is right, but I never said that it did. What I said was:
"After that, it holds the ACK bit of the last data byte received".
Notare Bene: I did not write the '/' character!
This was not a mistake. I try to take meticulous attention to detail, as all good engineers should. When working with programmable logic, active signal levels are generally swept to the pin descriptors. Thus when a pin described as /ACK is pulled low, the internal logic descriptions can be expressed using the signal ACK which will be true (logic 1).
So my statement does not conflict with MB's observations. That bit of the SSP is 1 while ACK = 1 (and the /ACK pin is TTL level Low). 0 when ACK = 0 (and the /ACK pin is TTL level High).
So yes, that bit of the SSP _DOES_ have a different function depending on whether the SSP has just transferred an incoming address byte (when it means R/W) or outgoing data byte (when it means ACK).
Microchip do not improve matters by persisting on referring it as the R/W bit even when it is indicating the ACK state. In AN734a, they say
State 4: Master read, last byte was data S = 1 (START condition occured last) R/W = 1 (Master Reading data from the Slave) D/A = 1 (Last byte sent was a data byte) BF = 0 (The buffer is empty) State 5: Master NACK S = 1 (START condition occured last) R/W = 0 (R/W bit rest by Slave logic) D/A = 1 (Last byte sent was a data byte) BF = 0 (The buffer is empty)Which is misleading because it implies that SSPSTAT<2> is indicating the transfer direction in state 4, or NACK in state 5. If the PIC knew what state it was in, it wouldn't have to read this bit!
I think they should have wrote this as:
State 4: Master read, last byte was data and and Master ACK S = 1 (START condition occured last) SSPSTAT<2> = 1 (Master ACK, byte last transferred not last in I2C message) D/A = 1 (Last byte sent was a data byte) BF = 0 (The buffer is empty) State 5: Master read, last byte was data and Master NACK S = 1 (START condition occured last) SSPSTAT<2> = 0 (Master NACK, byte last transferred was last in I2C message) D/A = 1 (Last byte sent was a data byte) BF = 0 (The buffer is empty)Microchip seem to have got away with their flaky explanation, because when SSPSTAT<2> = 1 in state 4, the PIC is also being reading.
As you can see, only SSPSTAT<2> differs between states 4 and 5. One bit of data can only answer one question at one time. Either "is this a read or a write", OR "do I need to send another byte or not?"
The guy at the Microchip fabrication facility told me that in a Master read, and last byte was data, SSPSTAT<2> state reads the ACK condition. That's as close to the horse's mouth as you can get, and the PIC behaves as per this statement.
My warning that you must NACK the final byte still stands, because although you would be forgiven for thinking that a STOP condition would clear evrything back to the idle state, the PIC will not. The PIC must have some internal state machine that is only reset by the NACK condition, because it will lock up.
The interrupt after the NACK is not pointless. Even though the PIC does not need to re-load the data buffer, it may need to know that the last byte has transferred.
Microchip's app notes are still a crock, and I think AN734 is a long overdue attempt to explain how to do an I2C slave in the SSP in response to the many people having a very hard time with it. Even then, they have had to use state variables because they haven't completely seen how to use the SSP registers alone.
I would say Keith's posts are very hard to follow, and if it needs such a long explanation of what he 'really meant' it should just be summed up in an easy few lines. Maybe he understood or now understands things after reading an734, but his posts are too poorly written, so just post the corrections and leave it. For example, when I read his first post I am totaly mislead into thinking that the master has to nack to prevent and int (which is wrong). Maybe he knew better, but the post was still written wrong. In his first post Keith said this. "Also note that the SSP will interupt the CPU after every byte read by the I2C master is acknowledged. So your I2C master MUST remember to NACK the final byte. Otherwise your slave will lock up, thinking "hey, I sent the last message byte for the protocol, whats this interrupt for?". " He just said to prevent getting an interrupt that you don't know what to do with have the master not acknowledge. NACK has NOTHING to do with getting another interrupt. So his statement is wrong. You always get an interrupt, a nack signal will not stop one from happening, as he put it "whats this interrupt for". In his second post he is right, it is CAN be used for other house keeping stuff; but the SSP flags can easily be reset anyways. However, he didn't say this in your first post. So again, maybe he knows what his is talking about but his post wasn't clear, so why post all this extra stuff trying to explain what he 'really meant' etc. James
Questions: