|
|
View previous topic :: View next topic |
Author |
Message |
Pukar Guest
|
I2C Communication Failure between PIC and another I2C device |
Posted: Thu Mar 07, 2002 9:50 pm |
|
|
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
|
Re: I2C Communication Failure between PIC and another I2C de |
Posted: Fri Mar 08, 2002 11:28 am |
|
|
:=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 |
Posted: Fri Mar 08, 2002 12:36 pm |
|
|
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
|
Re: I2C Communication Failure between PIC and another I2C de |
Posted: Fri Mar 08, 2002 1:04 pm |
|
|
:=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 |
Posted: Fri Mar 08, 2002 1:19 pm |
|
|
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
|
Re: I2C Communication Failure between PIC and another I2C de |
Posted: Mon Mar 11, 2002 11:12 am |
|
|
:=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 |
Posted: Thu Apr 18, 2002 6:22 am |
|
|
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 |
|
|
|
|
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
|