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

i2c between two 16F873

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



Joined: 14 Jan 2008
Posts: 2
Location: Westerham UK

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

i2c between two 16F873
PostPosted: Wed Jan 16, 2008 8:23 am     Reply with quote

Hi All,
I'm new to this list and have a problem using i2c. I have connected two 16F873 together, C3 toC3, C4 to C4. I have put the ex_slave code in one chip and some simple code copied from the posts in the master. I output the data received by the master on port b. If I make the slave i2c_write (0x55) e.g. it appears on the master, but if I try to index the buffer all I get is 0xFF. Looking on a dual trace scope it all looks OK (even the 0xFF.
Hope you can help.Compiler v 3.234

MASTER
Code:
// Program master.c

// Fuses: LP,XT,HS,RC,NOWDT,WDT,NOPUT,PUT,PROTECT,PROTECT_5%
// Fuses: PROTECT_50%,NOPROTECT,BROWNOUT,NOBROWNOUT,LVP,NOLVP,CPD
// Fuses: NOCPD,WRT,NOWRT,DEBUG,NODEBUG

#include <16F873.h>

#fuses HS,NOWDT,NOPUT,NOPROTECT,NOBROWNOUT,NOLVP,NOCPD,NOWRT,NODEBUG

#use delay (clock=20000000)
#use i2c (master, sda=pin_c4, scl=pin_c3, force_hw)

#define led pin_b0
#define scl pin_c3
#define sda pin_c4

int x;

void main()
   {
      output_float (scl);
      output_float (sda);
      output_b (0x00);
      delay_ms (1000);
      while (1)
         {
            for (x=0;x<=15;x++)
               {
                  output_high (pin_c6);      //scope trigger
                  delay_us(5);
                  output_low (pin_c6);

                  i2c_start ();
                  i2c_write (0xA0);
                  i2c_write (x);             //buffer address = 0..15
                  i2c_start ();
                  i2c_write (0xA1);          // read from slave
                  output_b (i2c_read (0));   // read data
                  i2c_stop ();
                  delay_ms (1000);
               }
         }
   }


SLAVE
Code:
// program name slave.c

// Fuses: LP,XT,HS,RC,NOWDT,WDT,NOPUT,PUT,PROTECT,PROTECT_5%
// Fuses: PROTECT_50%,NOPROTECT,BROWNOUT,NOBROWNOUT,LVP,NOLVP,CPD
// Fuses: NOCPD,WRT,NOWRT,DEBUG,NODEBUG

#include <16F873.h>

#fuses HS,NOWDT,NOPUT,NOPROTECT,NOBROWNOUT,NOLVP,NOCPD,NOWRT,NODEBUG

#use delay (clock=4000000)
#use i2c (slave, scl=pin_c3, sda=pin_c4,address=0xA0, force_hw)

#define sda pin_c4
#define scl pin_c3
#define led pin_b5

unsigned int x;
byte address, buffer[0x10];

#int_ssp
void ssp_isr ()
   {
     byte incoming, state;
     state = i2c_isr_state ();

     if (state < 0x80)      //Master is sending data
      {
        incoming = i2c_read ();
        if (state == 1)
           address = incoming;    //First received byte is address
        if (state == 2)
           buffer[address] = incoming;   //Second received byte is data
      }
   if (state == 0x80)      //Master is requesting data
     {
      i2c_write (buffer[address]);// works if i2c_write (0x55); ie not indexed
     }
  }

void main()
   {
      for (x=0;x<=15;x++)
          {
            buffer[x] = 0x74;        // Put data in buffer
          }
      enable_interrupts (int_ssp);
      enable_interrupts (global);
      output_low (led);
      while (1)
         {
         }
   }
Ttelmah
Guest







PostPosted: Wed Jan 16, 2008 9:35 am     Reply with quote

Just try one test.
Switch the _master_ to using software I2C.
There was a problem, which I, and a few other users have met in the past, where an I2C 'restart', does not work reliably on the hardware I2C on some chips....
You can also try with:
Code:

                  i2c_start ();
                  i2c_write (0xA0);
                  i2c_write (x);             //buffer address = 0..15
                  i2c_stop();
                  i2c_start ();
                  i2c_write (0xA1);          // read from slave
                  output_b (i2c_read (0));   // read data
                  i2c_stop ();

Here, the 'stop', gets round this.
Well done by the way, in posting complete but reasonably sized 'test' programs. Smile

Best Wishes
rnielsen



Joined: 23 Sep 2003
Posts: 852
Location: Utah

View user's profile Send private message

PostPosted: Wed Jan 16, 2008 10:08 am     Reply with quote

You didn't state if you had pull-up resistors on your SDA or SCL lines. If you don't, make sure they are installed. Things won't work properly if they are missing.

Your Master is running at 20MHZ while your Slave is running at 4MHZ. This can cause a timing issue. The Master can be sending commands faster than the Slave can process them. Try placing small delays, in your Master code, to see if that gets things going.

If you have a scope available you can have the ISR, in the Slave, make an extra output change state upon entery and then reset the state of the output before exiting the ISR. Monitoring the SDA & SCL lines while monitoring this output will tell you what timing issues you may have.

Ronald
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jan 16, 2008 12:20 pm     Reply with quote

The master and slave PICs can run at different oscillator frequencies
without problem. The compiler sees the frequency in the #use delay()
statement and calculates the correct value for the i2c baud rate register.

One case where the oscillator frequency can make a difference is
with a master that uses software i2c. The default baud rate is nominally
100 KHz with the software library. But that's probably only really
acheived with a 20 MHz oscillator. If you run the master at say, 4 MHz,
the real baud rate for software i2c will be considerably slower than
100 KHz. It might be less than 50 KHz.

But the most important point is this:
In my tests, I've found that the minimum oscillator frequency for the
slave PIC, using the CCS Ex_Slave.c code, is 8 MHz. I don't think it
works reliably at 4 MHz. You need to fix that.
Staffagm



Joined: 14 Jan 2008
Posts: 2
Location: Westerham UK

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

i2c between two 16F873
PostPosted: Thu Jan 17, 2008 3:45 am     Reply with quote

Well done, changing the xtal to 20MHz cured the problem.It now does exactly what it says on the tin. Thanks for your help guys.
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