|
|
View previous topic :: View next topic |
Author |
Message |
Staffagm
Joined: 14 Jan 2008 Posts: 2 Location: Westerham UK
|
i2c between two 16F873 |
Posted: Wed Jan 16, 2008 8:23 am |
|
|
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
|
|
Posted: Wed Jan 16, 2008 9:35 am |
|
|
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.
Best Wishes |
|
|
rnielsen
Joined: 23 Sep 2003 Posts: 852 Location: Utah
|
|
Posted: Wed Jan 16, 2008 10:08 am |
|
|
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
|
|
Posted: Wed Jan 16, 2008 12:20 pm |
|
|
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
|
i2c between two 16F873 |
Posted: Thu Jan 17, 2008 3:45 am |
|
|
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. |
|
|
|
|
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
|