|
|
View previous topic :: View next topic |
Author |
Message |
JH1987
Joined: 22 Jan 2011 Posts: 11
|
i2c_read() CCS Function Problem |
Posted: Wed Jan 26, 2011 1:42 pm |
|
|
PIC- 18F4520
Compiler- PCH 4.085
I was playing around with an example I2C master and slave provided by PCM Programmer using two PICs on different PCBs. The examples work great but I discovered a problem with the CCS i2c_read() function. Whether you tell the slave to ACK (i2c_read(), i2c_read(1)) or not ack (i2c_read(0)), the slave still ACKs. I can see this on a logic analyzer- low voltage on 9th clk rising edge of slave address byte. The rest of the transaction looks normal and the master sends both bytes because it believes the slave ACKed. This is the only problem I observed. I'm using 4.7K pull-ups on SCL/SDA. This should be adequate for 100KHz and 400KHz modes, and I do see the problem in both modes.
Here is the modified version of PCM Programmer's example:
Master:
Code: | /*
I2C Master Test Program
For Use on the PICDem 2 Board
*/
#include <18F4520.h>
#device PASS_STRINGS = IN_RAM
#include "fuses.h"
#use delay(INTERNAL=8M, clock=16M)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#use i2c(Master, sda=PIN_C4, scl=PIN_C3, Fast)
#define SLAVE1_WRITE_ADDR 0x12
#define SLAVE1_READ_ADDR 0x13
//====================================
void main()
{
int8 data;
while(1)
{
/*i2c_start();
i2c_write(SLAVE1_READ_ADDR);
delay_ms(50);
data = i2c_read(0);
i2c_stop();
printf("read %X \r\n", data); */
i2c_start();
if(i2c_write(SLAVE1_WRITE_ADDR)==0) {
delay_ms(50);
i2c_write(0xAA);
delay_ms(50);
}
i2c_stop();
delay_ms(100);
}
}
|
Slave:
Code: | /*
I2C Slave Test Program
For Use on the PICDem 2 Board
*/
#include <18F4520.h>
#device PASS_STRINGS = IN_RAM
#include "fuses.h"
#use delay(INTERNAL=8M, clock=16M)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#use i2c(Slave, SDA=Pin_C4, SCL=Pin_C3, address=0x12, Fast)
#INT_SSP
void ssp_interrupt()
{
int8 incoming, state;
state = i2c_isr_state();
if(state < 0x80) // Master is sending data
{
//incoming = i2c_read();
printf("State= %X, Read %X\r\n",state,i2c_read(0));
}
if(state >= 0x80) // Master is requesting data from slave
{
i2c_write(0x55);
}
}
//======================================
void main () {
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
while(1)
delay_ms(500);
}
|
Anyone know what could be happening?
Thanks for your time. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Jan 26, 2011 2:32 pm |
|
|
This diagram for a "Slave Receiver" shows that it does an ACK on
every byte that it gets from the master:
Quote: |
FIGURE 15-8: I2C SLAVE MODE TIMING WITH SEN = 0 (RECEPTION, 7-BIT ADDRESS)
|
From the 18F452 data sheet on page 140 (pg. 142 in the Acrobat reader):
http://ww1.microchip.com/downloads/en/DeviceDoc/39564c.pdf
The i2c spec (vs. 2.1) says a receiver must ACK each byte that it gets:
Quote: |
7.2 Acknowledge
Usually, a receiver which has been addressed is obliged to
generate an acknowledge after each byte has been
received, except when the message starts with a CBUS
address (see Section 10.1.3).
|
See page 10 in the i2c spec (in the column on the right side):
http://www.nxp.com/acrobat_download2/literature/9398/39340011.pdf |
|
|
JH1987
Joined: 22 Jan 2011 Posts: 11
|
Mediocre CCS Documentation |
Posted: Wed Jan 26, 2011 6:34 pm |
|
|
Thanks for the info. The NXP spec is helpful. I also just learned from skimming it that I2C reserves certain addresses.
But CCS really should have made it clear that only the master can NAK in their manual. Its obvious that the master would NAK to tell the slave not to write any more bytes out and end the slave -> master write transaction. But it also seemed reasonable that the slave could NAK the master to abort the master -> slave write process, like the way a failure in full duplex rs232 will cause a lot of chips to bail on a transaction. The only reason you can't do that is because the PIC firmware locks you into it. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19510
|
|
Posted: Thu Jan 27, 2011 5:46 am |
|
|
Not firmware. Hardware....
It is the slave hardware that generates this.
You can actually trigger a NACK, by setting the SSPOV bit on most of the PIC MSSP's (no warranty that this works on all.....). Or, by not reading the character from the input, and manually releasing the clock (CKP bit). You will then need to have 'recovery' code on the slave, to get the hardware out of the 'overflow' condition.
Best Wishes |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|