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 CCS Technical Support

Pic to Pic with I2C

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



Joined: 15 Dec 2003
Posts: 51
Location: Italy

View user's profile Send private message

Pic to Pic with I2C
PostPosted: Fri May 12, 2006 12:28 am     Reply with quote

Sorry for my English,

I have connected 2 pic with i2c, master and slave.
I have used the code:

MASTER (similar 2401.C)

Code:
#ifndef EEPROM_SDA

#define EEPROM_SDA  PIN_C4
#define EEPROM_SCL  PIN_C3

#endif


#use i2c(master, sda=EEPROM_SDA, scl=EEPROM_SCL,RESTART_WDT)

#define EEPROM_ADDRESS BYTE
#define EEPROM_SIZE    128


void init_ext_eeprom() {
   output_float(EEPROM_SCL);
   output_float(EEPROM_SDA);
}

BOOLEAN ext_eeprom_ready() {
   int1 ack;
   i2c_start();            // If the write command is acknowledged,
   ack = i2c_write(0xa0);  // then the device is ready.
   i2c_stop();
   return !ack;
}
void write_ext_eeprom(BYTE address, BYTE data) {
   while(!ext_eeprom_ready());
   i2c_start();
   i2c_write(0xa0);
   i2c_write(address);
   i2c_write(data);
   i2c_stop();
}

BYTE read_ext_eeprom(BYTE address) {
   BYTE data;

   while(!ext_eeprom_ready());
   i2c_start();
   i2c_write(0xa0);
   i2c_write(address);
   i2c_start();
   i2c_write(0xa1);
   data=i2c_read(0);
   i2c_stop();
   buffer_i2c[0] = data;
   return(data);
}


void read_ext_eeprom_n(byte address_start, byte n)
{

      BYTE data;
      BYTE contatore;
      if (n <= LEN_BUFFER_I2C)
      {
         while(!ext_eeprom_ready());
         i2c_start();
         i2c_write(0xa0);
         i2c_write(address_start);
         i2c_start();
         i2c_write(0xa1);
         if(n>1)   // se n non è valio o se vale 1
         {
            for(contatore=0; contatore <=(n-1); contatore ++)
         {
               buffer_i2c[contatore] = i2c_read(1);
            }
         buffer_i2c[n] = i2c_read(0);
         }
         else
         {
         buffer_i2c[0] = i2c_read(0);
         }
         i2c_stop();
   }
}

void main()
{
  int8 data;
 int8 address;
 
 init();
 lcd_init();
 init_ext_eeprom();
 lcd_putc("\f");
 while(1)
 {
   lcd_putc("\f");
   address = 0xB8;
   data = 0xBB;
   write_ext_eeprom(address,data);
   delay_ms(6000);
   data = read_ext_eeprom(address);
   PutHex_lcd(data);
   delay_ms(500);
 }
}


SLAVE:

Code:

//SLAVE INTERRUPT HANDLER..............

#INT_SSP
interrupt_ssp()
{
   int bo,dummy;
   bo=0;

   if (bit_test(SSPCON,OVERFLOW_BIT))
   {
      // clear the buffer
      dummy = SSPBUF;

      // Clear the register
      bit_clear(SSPCON,OVERFLOW_BIT);
   }
   // we are done since we got a stop
   else if (bit_test(SSPSTAT,STOP_BIT))
   {
      // since we are done, lets just reset everything
//      pData = 0;
//      data = 0;
   }
   else
    {
      bo=0;
       switch(SSPSTAT & 0x2D)
       {  // Keep only bits D/A, S, R/W, BF
            case STATE1 :
              // Master write operation, address byte in SSPBUF
              // Clear the data buffer
              //for(rindex=0;rindex < 16; rindex++)
              //rbuf[rindex]=0;

                rindex = 0;

               SSPOV = 0; // Clear address overflow flag, could be set from last
               // time because after not /ack, SSPBUF was still full.
               addrbyte = SSPBUF; // Dummy read to clear BF (read only bit)
               break;
            case STATE2 :
              // Master write operation, data byte in SSPBUF
              // Get data byte (also clears BF)
              SSPOV = 0;
//              sbuf[sindex++]=SSPBUF; // rbuf[rindex++]=SSPBUF;
            rbuf[rindex++]=SSPBUF;
             if (rindex == 2)
                {
             bo = 0; // break =????
            }
             break;
          case STATE3 :
              // Master has begin new read operation by initiating a START or RESTART
              // then sending Slave address (read) byte (now in SSPBUF).
              // Looks like clock enable bit CKP cleared on interrupt, so must
              // set it again to allow Master to clock data byte out
              // SCL held low, Master can be kept waiting here if necessary
              sindex = 0; // Reset buffer index
            //     SSPBUF = sbuf[sindex++]; // Load 1st byte from data buffer
 //             SSPBUF = lati_longi[sindex++];         
            SSPBUF = *rbuf[0]++; 
             CKP = 1; // Enable SCL for Master to shift byte out
              break;
          case STATE4 :
              // Master read operation, last byte was data, SSPBUF empty
              // Move next byte to SSPBUF and SSPSR
              // Same comment for CKP bit as in STATE3
            //     SSPBUF = sbuf[sindex++]; // Get next byte from data buffer
//              SSPBUF = lati_longi[sindex++];             SSPBUF = *rbuf[0]++;
              CKP = 1; // Enable SCL for Master to shift byte out
             break;
          case STATE5 :
              // A not /ack (high) was received from Master in response to data
              // byte received from Slave (last byte). Slave i2c logic is reset,
              // and waits for next Master operation.
             bo=0;
             break;
          default:
              // Error, trap here. Watchdog will reset pic (must be enabled, and
              //watchdog timer cleared in other loops)
              //while(1);
             icbus_init();
             break;
           }
      }
}



the reading from master to Slave is corrected also sequential reading Very Happy

but I do not succeed in writes an address in the Slave
task lacks a code in interrupt Slave

Thanks in advance
rnielsen



Joined: 23 Sep 2003
Posts: 852
Location: Utah

View user's profile Send private message

PostPosted: Fri May 12, 2006 8:35 am     Reply with quote

You need to make sure that the Slave has enough time to service the interrupt before the Master tries to continue sending more i2c commands or else it might hang. It takes a bit for the Slave to save everything and get to the isr.

Try having a pin pulse, in the Slave isr routine, and put a scope on it. Monitor your i2c bus as well and look at the timing between the commands and the pulse signal. If the pulse occurs _after_ the Master starts sending the next i2c_write(), i2c_read() or i2c_stop() then you will need to put a delay between the commands to ensure the Slave has the time to do it's thing.

I've, also, had to monitor the SSPSTAT register and output it to a port, with LED's connected, to see what the Slave was seeing so I could tell what conditions to look for. I would have the Master single step it's commands when I did this.

Ronald
Max



Joined: 15 Dec 2003
Posts: 51
Location: Italy

View user's profile Send private message

PostPosted: Fri May 12, 2006 9:59 am     Reply with quote

Thanks,

task is not poblema of speed,
if, from the master I read one location (address) in the Slave, it works well.
I use ICD2.

I do not understand in the ruotine of interrupt where I can find the address and the data when use the masyer for write an address in the Slave

CODE MASTER:

Code:

void write_ext_eeprom(BYTE address, BYTE data) {
   while(!ext_eeprom_ready());
   i2c_start();
   i2c_write(0xa0);
   i2c_write(address);
   i2c_write(data);
   i2c_stop();
}


in that point of the routine interrupt Slave I find address and data sending
by master ?


Code:

//SLAVE INTERRUPT HANDLER..............

#INT_SSP
interrupt_ssp()
{
   int bo,dummy;
   bo=0;

   if (bit_test(SSPCON,OVERFLOW_BIT))
   {
      // clear the buffer
      dummy = SSPBUF;

      // Clear the register
      bit_clear(SSPCON,OVERFLOW_BIT);
   }
   // we are done since we got a stop
   else if (bit_test(SSPSTAT,STOP_BIT))
   {
      // since we are done, lets just reset everything
//      pData = 0;
//      data = 0;
   }
   else
    {
      bo=0;
       switch(SSPSTAT & 0x2D)
       {  // Keep only bits D/A, S, R/W, BF
            case STATE1 :
              // Master write operation, address byte in SSPBUF
              // Clear the data buffer
              //for(rindex=0;rindex < 16; rindex++)
              //rbuf[rindex]=0;

                rindex = 0;

               SSPOV = 0; // Clear address overflow flag, could be set from last
               // time because after not /ack, SSPBUF was still full.
               addrbyte = SSPBUF; // Dummy read to clear BF (read only bit)
               break;
            case STATE2 :
              // Master write operation, data byte in SSPBUF
              // Get data byte (also clears BF)
              SSPOV = 0;
//              sbuf[sindex++]=SSPBUF; // rbuf[rindex++]=SSPBUF;
            rbuf[rindex++]=SSPBUF;
             if (rindex == 2) // ho ricevuto indirizzo e dato da scrivere ?
                {
             bo = 0;
            }
             break;
          case STATE3 :
              // Master has begin new read operation by initiating a START or RESTART
              // then sending Slave address (read) byte (now in SSPBUF).
              // Looks like clock enable bit CKP cleared on interrupt, so must
              // set it again to allow Master to clock data byte out
              // SCL held low, Master can be kept waiting here if necessary
              sindex = 0; // Reset buffer index
            //     SSPBUF = sbuf[sindex++]; // Load 1st byte from data buffer
 //             SSPBUF = lati_longi[sindex++];          // qui scrivo il byte che voglio rimandare indietro
            SSPBUF = *rbuf[0]++; // leggo il contenuto della locazione richiesta
             CKP = 1; // Enable SCL for Master to shift byte out
              break;
          case STATE4 :
              // Master read operation, last byte was data, SSPBUF empty
              // Move next byte to SSPBUF and SSPSR
              // Same comment for CKP bit as in STATE3
            //     SSPBUF = sbuf[sindex++]; // Get next byte from data buffer
//              SSPBUF = lati_longi[sindex++];  // se la richiesta è una lettura sequenziale continuo
            SSPBUF = *rbuf[0]++;
              CKP = 1; // Enable SCL for Master to shift byte out
             break;
          case STATE5 :
              // A not /ack (high) was received from Master in response to data
              // byte received from Slave (last byte). Slave i2c logic is reset,
              // and waits for next Master operation.
             bo=0;
             break;
          default:
              // Error, trap here. Watchdog will reset pic (must be enabled, and
              //watchdog timer cleared in other loops)
              //while(1);
             icbus_init();
             break;
           }
      }
}


sorry and thanks
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