CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

I2C Communication Failure between PIC and another I2C device

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Pukar
Guest







I2C Communication Failure between PIC and another I2C device
PostPosted: Thu Mar 07, 2002 9:50 pm     Reply with quote

I am trying to establish I2C communication between PIC and another I2C device. PIC is the Slave and the other device the Master. When the I2C device tries to write to the PIC, it works fine and I have rigorously tested this. But when the I2C device wants to read from the PIC, the communication proceeds all the way until PIC receives the READ address. SCL is held low forever and PIC is holding it low. The communication fails as a result. Has anyone faced similar problem or has a solution?

Thanks.

Regards,
Pukar
___________________________
This message was ported from CCS's old forum
Original Post ID: 3039
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

Re: I2C Communication Failure between PIC and another I2C de
PostPosted: Fri Mar 08, 2002 11:28 am     Reply with quote

:=I am trying to establish I2C communication between PIC and another I2C device. PIC is the Slave and the other device the Master. When the I2C device tries to write to the PIC, it works fine and I have rigorously tested this. But when the I2C device wants to read from the PIC, the communication proceeds all the way until PIC receives the READ address. SCL is held low forever and PIC is holding it low. The communication fails as a result. Has anyone faced similar problem or has a solution?
:=
:=Thanks.
:=
:=Regards,
:=Pukar

I currently use PIC's in a multimaster enviroment. We implemented a modified ACCESS.bus protocol where an ACK is read back from a device (slave mode). Here is a snippet of code:

/* were we addressed in read mode so set up for data to be read
from us - slave mode.
*/
if (bit_test(*SSPSTAT, READ_WRITE))
{
if (Rx_Msg.hdr.stat == CHECKSUM_OK)
{
Rx_Msg.hdr.stat = PROCESS_OK;
/* Load acknowledgement value */
(UINT8)*SSPBUF = MSGACK;
}
else
{
(UINT8)*SSPBUF = MSGNACK;
}
/* Setup to allow data to be read from us */
bit_set(*SSPCON, CKP);
I2CStatus = I2CSLAVETxING;
I2C_Timeout = 25;
rx_count = 1;
}

The important things to note are:
1. Loading SSBUF with the data being read
2. Setting the Clock Polarity Select bit. In I2C slave mode this is the SCK release control. When addressed as a slave device, the clock is held low to allow time for you to load the SSBUF. YOU MUST SET THIS BIT to allow the master device to clock the data from the slave device.


Mark
___________________________
This message was ported from CCS's old forum
Original Post ID: 3062
BA
Guest







Re: I2C Communication Failure between PIC and another I2C de
PostPosted: Fri Mar 08, 2002 12:36 pm     Reply with quote

There's a bit you must clear that will free the clock line. How are you handling the transactions? Take a look at the SSPSTAT, SSPCON, and SSPCON2 registers and make sure their settings are correct, and that you are paying attention to the bits in these registers correctly.

:=I am trying to establish I2C communication between PIC and another I2C device. PIC is the Slave and the other device the Master. When the I2C device tries to write to the PIC, it works fine and I have rigorously tested this. But when the I2C device wants to read from the PIC, the communication proceeds all the way until PIC receives the READ address. SCL is held low forever and PIC is holding it low. The communication fails as a result. Has anyone faced similar problem or has a solution?
:=
:=Thanks.
:=
:=Regards,
:=Pukar
___________________________
This message was ported from CCS's old forum
Original Post ID: 3070
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

Re: I2C Communication Failure between PIC and another I2C de
PostPosted: Fri Mar 08, 2002 1:04 pm     Reply with quote

:=There's a bit you must clear that will free the clock line. How are you handling the transactions? Take a look at the SSPSTAT, SSPCON, and SSPCON2 registers and make sure their settings are correct, and that you are paying attention to the bits in these registers correctly.
:=

The bit is SSPCON.4 or SSPCON1.4 (CKP). You must set this bit instead of clearing it. The SSP module clears this bit when addressed in read mode.

:=:=I am trying to establish I2C communication between PIC and another I2C device. PIC is the Slave and the other device the Master. When the I2C device tries to write to the PIC, it works fine and I have rigorously tested this. But when the I2C device wants to read from the PIC, the communication proceeds all the way until PIC receives the READ address. SCL is held low forever and PIC is holding it low. The communication fails as a result. Has anyone faced similar problem or has a solution?
:=:=
:=:=Thanks.
:=:=
:=:=Regards,
:=:=Pukar
___________________________
This message was ported from CCS's old forum
Original Post ID: 3072
pukar
Guest







Re: I2C Communication Failure between PIC and another I2C de
PostPosted: Fri Mar 08, 2002 1:19 pm     Reply with quote

Hi,

Both of you seem to agree that the CKP bit of the SSPCON register needs to be set after the SSPBUF is written to with the value to be sent from the Slave to the Master. I tried that but it still does not help. Here is my code, which is a slight modification of the ex_slave.c available as an I2C CCS compiler example:

#INT_SSP
void ssp_isr ()
{
byte incoming;
if (!(i2c_poll())) {
if (fState == ADDRESS_READ) {

fState = NOTHING;
//i tried neither i2c_write(data) nor *SSPBUF = data works
//i2c_write (buffer[address]);
*SSPBUF=0x0f;
bit_set(*SSPCON, CKP);
}
}else {
incoming = i2c_read();

if (fState == NOTHING){
fState = CONTROL_READ;
}
else if (fState == CONTROL_READ) {
fState = ADDRESS_READ;
}
else if (fState == ADDRESS_READ) {
buffer[address] = incoming;
fState = NOTHING;
}
}
}
___________________________
This message was ported from CCS's old forum
Original Post ID: 3073
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

Re: I2C Communication Failure between PIC and another I2C de
PostPosted: Mon Mar 11, 2002 11:12 am     Reply with quote

:=Hi,
:=
:=Both of you seem to agree that the CKP bit of the SSPCON register needs to be set after the SSPBUF is written to with the value to be sent from the Slave to the Master. I tried that but it still does not help. Here is my code, which is a slight modification of the ex_slave.c available as an I2C CCS compiler example:
:=
:=#INT_SSP
:=void ssp_isr ()
:={
:= byte incoming;
:= if (!(i2c_poll())) {
:= if (fState == ADDRESS_READ) {
:=
:= fState = NOTHING;
:=//i tried neither i2c_write(data) nor *SSPBUF = data works
:=//i2c_write (buffer[address]);
:= *SSPBUF=0x0f;
:= bit_set(*SSPCON, CKP);
:= }
:= }else {
:= incoming = i2c_read();
:=
:= if (fState == NOTHING){
:= fState = CONTROL_READ;
:= }
:= else if (fState == CONTROL_READ) {
:= fState = ADDRESS_READ;
:= }
:= else if (fState == ADDRESS_READ) {
:= buffer[address] = incoming;
:= fState = NOTHING;
:= }
:= }
:=}

Try the following code and let me know if it works. I didn't use fstate, so if its needed elsewhere you will have to add it in.

/* Note that you should have code similar to this to setup the port
the important thing is to be in slave mode.

(UINT8)*SSPCON = (ABUS_SLAVE_MASK);
(UINT8)*SSPCON = (ABUS_SLAVE_MASK | ABUS_CLK_ENABLE | ABUS_MODE_SETUP);
dummy = *SSPBUF;
bit_clear(*SSPCON,OVERFLOW_BIT);
(UINT8)*SSPADD = I2C_Address;
bit_set(*PIR1, SSPIF);
bit_set(*PIE1, SSPIE);

*/


//#define SSPSTAT Address depends on device
#define READ_WRITE 0x02
#define BF_BIT 0x00

//#define SSPCON Address depends on device
#define SSPOV 0x06
#define CKP 0x04

#INT_SSP
void ssp_isr ()
{
byte incoming;

/* Make sure the buffer has not overflowed */
if (bit_test(*SSPCON, SSPOV))
{
incoming = (UINT8)*SSPBUF;
/* Clear the register */
bit_clear(*SSPCON,SSPOV);
}

else if (bit_test(*SSPSTAT,STOP_BIT))
{
/* The message was complete - do any message processing here */
}

else
{
/* were we addressed in read mode so set up for data to be read
from us - slave mode.
*/
if (bit_test(*SSPSTAT, READ_WRITE))
{
/* Load acknowledgement value - Note the casting. I had a problem
with the new compiler treating the pointers as 16 bit data which
overwrote other memory locations.
*/
(UINT8)*SSPBUF = 0x0F;
/* Setup to allow data to be read from us */
bit_set(*SSPCON, CKP);
}
/* Note that there is errata with the PIC18CXX2 clearing the
BF bit when the BSR is pointed to 0x0F and an instruction
contains 0xC9 in its 8 least significant bits */
else if (bit_test(*SSPSTAT,BF_BIT))
{
/* continue recieving bytes */
/* process the first byte */
if (!bit_test(*SSPSTAT,ADDRESS_BIT))
{
/* Read the data */
incoming = (UINT8)*SSPBUF;
address = 0;
}
else
{
/* Read the data */
incoming = (UINT8)*SSPBUF;

/* Store the data if our buffer in large enough */
if (address < sizeof(buffer))
{
buffer[address] = incoming;
++address;
}
}
}
}
}
___________________________
This message was ported from CCS's old forum
Original Post ID: 3140
Jay
Guest







Re: (Mark) I2C Communication Failure between PIC and another
PostPosted: Thu Apr 18, 2002 6:22 am     Reply with quote

Mark,

In the SSP_int routine below, why do you check for a Stopbit first? I think this can cause errors:

Let us take a simple slave i2c_read as example:
1) the slave receives the address byte
2) the slave receives several data bytes
3) the slave receives the last data byte, immediately followed by a stop condition
4) this causes the INT_SSP to be called

In your routine, the stop condition would make you think the message is completed and it can be processed. But this isn't true! The last byte is still in SSPBUF and is not read out.

Correct me if i'm wrong!

Regards,
Jay.


:=:=Hi,
:=:=
:=:=Both of you seem to agree that the CKP bit of the SSPCON register needs to be set after the SSPBUF is written to with the value to be sent from the Slave to the Master. I tried that but it still does not help. Here is my code, which is a slight modification of the ex_slave.c available as an I2C CCS compiler example:
:=:=
:=:=#INT_SSP
:=:=void ssp_isr ()
:=:={
:=:= byte incoming;
:=:= if (!(i2c_poll())) {
:=:= if (fState == ADDRESS_READ) {
:=:=
:=:= fState = NOTHING;
:=:=//i tried neither i2c_write(data) nor *SSPBUF = data works
:=:=//i2c_write (buffer[address]);
:=:= *SSPBUF=0x0f;
:=:= bit_set(*SSPCON, CKP);
:=:= }
:=:= }else {
:=:= incoming = i2c_read();
:=:=
:=:= if (fState == NOTHING){
:=:= fState = CONTROL_READ;
:=:= }
:=:= else if (fState == CONTROL_READ) {
:=:= fState = ADDRESS_READ;
:=:= }
:=:= else if (fState == ADDRESS_READ) {
:=:= buffer[address] = incoming;
:=:= fState = NOTHING;
:=:= }
:=:= }
:=:=}
:=
:=Try the following code and let me know if it works. I didn't use fstate, so if its needed elsewhere you will have to add it in.
:=
:=/* Note that you should have code similar to this to setup the port
:= the important thing is to be in slave mode.
:=
:= (UINT8)*SSPCON = (ABUS_SLAVE_MASK);
:= (UINT8)*SSPCON = (ABUS_SLAVE_MASK | ABUS_CLK_ENABLE | ABUS_MODE_SETUP);
:= dummy = *SSPBUF;
:= bit_clear(*SSPCON,OVERFLOW_BIT);
:= (UINT8)*SSPADD = I2C_Address;
:= bit_set(*PIR1, SSPIF);
:= bit_set(*PIE1, SSPIE);
:=
:=*/
:=
:=
:=//#define SSPSTAT Address depends on device
:= #define READ_WRITE 0x02
:= #define BF_BIT 0x00
:=
:=//#define SSPCON Address depends on device
:= #define SSPOV 0x06
:= #define CKP 0x04
:=
:=#INT_SSP
:=void ssp_isr ()
:={
:= byte incoming;
:=
:= /* Make sure the buffer has not overflowed */
:= if (bit_test(*SSPCON, SSPOV))
:= {
:= incoming = (UINT8)*SSPBUF;
:= /* Clear the register */
:= bit_clear(*SSPCON,SSPOV);
:= }
:=
:= else if (bit_test(*SSPSTAT,STOP_BIT))
:= {
:= /* The message was complete - do any message processing here */
:= }
:=
:= else
:= {
:= /* were we addressed in read mode so set up for data to be read
:= from us - slave mode.
:= */
:= if (bit_test(*SSPSTAT, READ_WRITE))
:= {
:= /* Load acknowledgement value - Note the casting. I had a problem
:= with the new compiler treating the pointers as 16 bit data which
:= overwrote other memory locations.
:= */
:= (UINT8)*SSPBUF = 0x0F;
:= /* Setup to allow data to be read from us */
:= bit_set(*SSPCON, CKP);
:= }
:= /* Note that there is errata with the PIC18CXX2 clearing the
:= BF bit when the BSR is pointed to 0x0F and an instruction
:= contains 0xC9 in its 8 least significant bits */
:= else if (bit_test(*SSPSTAT,BF_BIT))
:= {
:= /* continue recieving bytes */
:= /* process the first byte */
:= if (!bit_test(*SSPSTAT,ADDRESS_BIT))
:= {
:= /* Read the data */
:= incoming = (UINT8)*SSPBUF;
:= address = 0;
:= }
:= else
:= {
:= /* Read the data */
:= incoming = (UINT8)*SSPBUF;
:=
:= /* Store the data if our buffer in large enough */
:= if (address < sizeof(buffer))
:= {
:= buffer[address] = incoming;
:= ++address;
:= }
:= }
:= }
:= }
:=}
___________________________
This message was ported from CCS's old forum
Original Post ID: 3877
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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