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 master/slave, 2 pic and an eeprom

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



Joined: 14 May 2004
Posts: 330

View user's profile Send private message

i2c master/slave, 2 pic and an eeprom
PostPosted: Wed Oct 08, 2008 4:01 pm     Reply with quote

Hi,

I am building a device that has 2 pic and an eeprom in the same i2c bus. The code works until I write to the other device, for example:

Master Pic.
Code:
#use i2c(MASTER, SDA=PIN_C4, SCL=PIN_C3, FORCE_HW)

int1 i2c_ready (char device) {
   int1 ack;

   i2c_start();              // If the write command is acknowledged,
   ack = i2c_write(device);  // then the device is ready.
   i2c_stop();
   return !ack;
}
// readings from the i2c bus
// S=start
// 60=address
// A=ack
// P=stop
i2c_ready(0x60); // S 60 A P
i2c_ready(0x60); // S 60 A P
i2c_ready(0x60); // S 60 A P
i2c_ready(0x60); // S 60 A P
i2c_ready(0xA0); // S A0 A P
i2c_ready(0xA0); // S A0 A P
i2c_ready(0x60); // S 60 N P
i2c_ready(0xA0); // S A0 A P


The slave pic works fine until I send something to another address, then it will nak forever.

slave pic:
Code:
char read_i2c(void);
void i2c_interrupt_handler(void);
void i2c_initialize(void);
void write_i2c(unsigned char transmit_byte);

#INT_SSP
void ssp_interupt () {
  i2c_interrupt_handler();
}

#define RX_BUF_LEN  64
#define NODE_ADDR   0x60 /* I2C address of the slave node (avoid addr masking) */

unsigned char slave_buffer[RX_BUF_LEN];

int buffer_index;
int comms_error;
int debug_state;

void i2c_initialize (void) {
  debug_state = 0;

  /* Set up SSP module for 7-bit */
  while (SSPCON2 & 0x1F); // ACKEN RCEN PEN RSEN SEN all must be zero

  SSPSTAT = 0x00;      /* Clear the SSPSTAT register. */
  SSPCON1 = 0x36;      /* 0011 0110 */
  SSPADD = NODE_ADDR;  /* Set the slave's address */
                       /* init buffers */
  buffer_index = 0;

  enable_interrupts(INT_SSP);  /* Enable MSSP interrupts. */
}

void i2c_interrupt_handler (void) {
    unsigned char temp_sspstat;
    unsigned char this_byte;
    unsigned char tx_byte;
    int x;

    /* Mask out the unnecessary bits */
    temp_sspstat = SSPSTAT & 0x2D; /* 0010 1101 */

    switch (temp_sspstat)
    {
          case 0x09: /* 0000 1001 */                /* Write operation, last byte was an address, buffer is full */
            buffer_index = 0;                       /* Clear the buffer index */
            this_byte = read_i2c();                 /* Do a dummy read of PIC_SSPBUF */
            debug_state = 1;
            break;

          case 0x29: /* 0010 1001 */                /* Write operation, last byte was data, buffer is full */
            this_byte = read_i2c();                 /* Get the byte from the SSP */
            slave_buffer[buffer_index] = this_byte; /* Put it into the buffer */
            buffer_index++;                         /* Increment the buffer pointer */
            debug_state = 2;
            break;

          case 0x0D: /* 0000 1101 */                /* Read operation; last byte was address, buffer is full */
            this_byte = read_i2c();                 /* Do a dummy read of PIC_SSPBUF to clear it */
//          while(SSPSTATbits.BF);

          case 0x0C: /* 0000 1100 */                /* Read operation; last byte was an address, buffer is empty */
            buffer_index = 0;                       /* Clear the buffer index */
            tx_byte = slave_buffer[buffer_index];   /* Get byte from the buffer */
            write_i2c(tx_byte);                     /* Write the byte to PIC_SSPBUF */
            buffer_index++;                         /* increment the buffer index */
            debug_state = 3;
            break;

          case 0x2C: /* 0010 1100 */                /* Read operation; last byte was data, buffer is empty */
            tx_byte = slave_buffer[buffer_index];
            write_i2c(tx_byte);                     /* Write to PIC_SSPBUF */
            buffer_index++;                         /* increment the buffer index */
            debug_state = 4;
            break;

          case 0x28: /* 0010 1000 */                /* A NACK was received when transmitting data back [to] the master. */
            debug_state = 5;                        /* Slave logic is reset in this case. R_W=0, D_A=1, and BF=0. */
            break;                                  /* If we don't stop in this state, then something is wrong!! */

          default:
            debug_state = 0xE;
            break;
    }
}

void write_i2c(unsigned char transmit_byte) {
   unsigned char write_collision = 1;

   while (SSPSTATbits.BF); /* Is BF bit set in PIC_SSPSTAT? */

   while (write_collision)
   {
       /* If not, then do the i2c_write. */
       SSPCON1bits.WCOL = 0;  /* Clear the WCOL flag */
       SSPBUF = transmit_byte;

       /* Was there a write collision? */
       if (SSPCON1bits.WCOL)
       {
           /* Yes there was a write collision. */
           write_collision = 1;
       }
       else
       {
           /* NO, there was no write collision. */
           /* The transmission was successful */
           write_collision = 0;
       }
   }
   SSPCON1bits.CKP = 1;  /* Release the clock. */
}

/* This function returns the byte in SSPBUF */
unsigned char read_i2c(void) {
   return SSPBUF;

}


I can not see what I am doing wrong. Any tips would be welcome.

Thank you.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Oct 08, 2008 4:22 pm     Reply with quote

1. Post your PICs and your compiler version.

2. Post the #fuses and #use delay() statements for both PICs.

3. Try it without the FORCE_HW on the master.
future



Joined: 14 May 2004
Posts: 330

View user's profile Send private message

PostPosted: Wed Oct 08, 2008 4:59 pm     Reply with quote

ok,

two 18f4620 running at 40mhz. compiler version 3.249.

master fuses:
#fuses H4,NOWDT,NOPROTECT,NOLVP
#use delay(clock=40000000)
#use i2c(MASTER, SDA=PIN_C4, SCL=PIN_C3, FORCE_HW)

slave fuses:
#fuses H4,NOWDT,NOPROTECT,NOLVP
#use delay(clock=40000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

the slave pic does not have the #use i2c directive because it does not use the compilerĀ“s library.

Using the software i2c didnĀ“t help. The communication seems to be fine but something at the end of transaction is left in a wrong state.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Oct 08, 2008 5:11 pm     Reply with quote

1. Slow down your master. Change the H4 to HS, and change the
#use delay() to 10 MHz.

2. Put delays between the master's i2c statements.


If there is a problem where some process in the slave PIC doesn't have
time to finish, these tests will help to show it.
MicroManiac



Joined: 21 Aug 2008
Posts: 34

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

PostPosted: Thu Oct 09, 2008 3:23 am     Reply with quote

Try using the Force Software because i faced some problems with the Force hardware previously and when i used the force SW it worked fine
_________________
"Any intelligent fool can make things bigger, more complex, and more violent. It takes a touch of genius -- and a lot of courage -- to move in the opposite direction."
Albert Einstein
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