|
|
View previous topic :: View next topic |
Author |
Message |
01011
Joined: 21 Apr 2010 Posts: 6 Location: earth, solar system
|
i2c with 3 pic |
Posted: Wed Apr 21, 2010 9:04 am |
|
|
Hi,
I did a circuit with 3 pic (master is a 18F2550, one slave is a 18F2680 and another slave is a 18F2550), and I want to connect them using i2c
I don't know why but slaves don't answer to master request
If I modify the master to communicate with just one slave, it answers as expected.
I saw something similar here, but I don't know how to export the solution to my programs
programs are very simple; master send 2 bytes to each slave, 1st slave return the sum of these bytes plus 1, and 2nd slave return the sum of these bytes minus 1
here are my codes:
master.c
Code: | #include <18F2680.h>
#fuses NOMCLR,INTRC_IO,NOWDT,NOPROTECT,NOLVP,NOWRT,NOWRTD,PUT,STVREN,NODEBUG,NOWRTB
#use delay(clock=16000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#use i2c(fast, Master, sda=PIN_C4, scl=PIN_C3)
int data_in1 = 0;
int data_in2 = 0;
int data_out1 = 0;
int data_out2 = 16;
void main()
{
setup_oscillator(OSC_16MHZ);
SETUP_ADC(ADC_OFF);
SETUP_ADC_PORTS(NO_ANALOGS);
delay_ms(10);
while(TRUE)
{
delay_ms(100);
printf("\r\n-");
i2c_start ();
i2c_write (0x30);
i2c_write (data_out1);
i2c_write (data_out2);
i2c_stop();
i2c_start ();
i2c_write (0x31);
data_in1=i2c_read(0);
i2c_stop ();
delay_ms(1);
i2c_start ();
i2c_write (0x40);
i2c_write (data_out1);
i2c_write (data_out2);
i2c_stop();
i2c_start ();
i2c_write (0x41);
data_in2=i2c_read(0);
i2c_stop ();
printf("to 0x30:0x%X,0x%X - from 0x31: 0x%X,0x%X", data_out1, data_out2, data_in1, data_in2);
++data_out1;
++data_out2;
}
}
|
slave1.c
Code: |
#include <18F2550.h>
#fuses NOMCLR,INTRC_IO,NOWDT,NOPROTECT,NOLVP,NOWRT,NOWRTD,PUT,STVREN,NODEBUG,NOWRTB
#use delay(clock=16000000)
#use rs232(baud=57600, xmit=PIN_C6, rcv=PIN_C7)
#use i2c(fast, Slave, SDA=PIN_b0, SCL=PIN_b1, address=0x30)
int data=0;
int i2c_state;
#INT_SSP
void ssp_interupt ()
{
i2c_state = i2c_isr_state();
if(i2c_state < 0x80)
{
if(i2c_state == 0)
i2c_read();
if(i2c_state == 1)
data = i2c_read();
if(i2c_state == 2)
data += i2c_read();
}
else
//if(i2c_state >= 0x80)
{
data++;
if(i2c_state == 0x80)
{
i2c_write(data);
}
}
}
void main()
{
setup_oscillator(OSC_16MHZ);
setup_adc(ADC_OFF);
setup_adc_ports(NO_ANALOGS);
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
delay_ms(10);
while(TRUE)
{
}
}
|
slave2.c
Code: |
#include <18F2550.h>
#fuses NOMCLR,INTRC_IO,NOWDT,NOPROTECT,NOLVP,NOWRT,NOWRTD,PUT,STVREN,NODEBUG,NOWRTB
#use delay(clock=16000000)
#use rs232(baud=57600, xmit=PIN_C6, rcv=PIN_C7)
#use i2c(fast, Slave, SDA=PIN_b0, SCL=PIN_b1, address=0x40)
int data=0;
int i2c_state;
#INT_SSP
void ssp_interupt ()
{
i2c_state = i2c_isr_state();
if(i2c_state < 0x80)
{
if(i2c_state == 0)
i2c_read();
if(i2c_state == 1)
data = i2c_read();
if(i2c_state == 2)
data += i2c_read();
}
else
//if(i2c_state >= 0x80)
{
data--;
if(i2c_state == 0x80)
{
i2c_write(data);
}
}
}
void main()
{
setup_oscillator(OSC_16MHZ);
setup_adc(ADC_OFF);
setup_adc_ports(NO_ANALOGS);
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
delay_ms(10);
while(TRUE)
{
}
}
|
Last edited by 01011 on Wed Apr 21, 2010 2:36 pm; edited 1 time in total |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Apr 21, 2010 11:27 am |
|
|
Quote: | // talk with first slave
i2c_start ();
i2c_start (); |
You are doing two 'starts' at the beginning of each sequence. That's not
part of the i2c protocol. There is only supposed to be one 'start'.
Quote: | if(i2c_state < 0x80)
{
if(i2c_state == 0)
i2c_read(0);
if(i2c_state == 1)
data = i2c_read(0);
if(i2c_state == 2)
data += i2c_read(0); |
Here you are giving the i2c_read() function a parameter of 0, while inside
the #int_ssp interrupt routine. CCS never does this in any example. |
|
|
rnielsen
Joined: 23 Sep 2003 Posts: 852 Location: Utah
|
|
Posted: Wed Apr 21, 2010 11:36 am |
|
|
Quote: | data += i2c_read(0); |
As PCM programmer has pointed out, you don't need to have the '0' parameter in this i2c_read() command. The place a '0' does belong is in the Master routine. You place the '0' in the i2c_read command so that the master can tell the slave that the master is finished reading data from the slave.
I might suggest you place a slave in your circuit, one at a time, and make sure you can talk to each of them, separately. Then, try adding both slaves to the circuit. Also, make sure your master is not sending commands too fast. Each slave needs a certain amount of time to respond to each command, fetch whatever data you're requesting and then send it back out to the bus for the master to receive.
Ronald |
|
|
01011
Joined: 21 Apr 2010 Posts: 6 Location: earth, solar system
|
|
Posted: Wed Apr 21, 2010 2:46 pm |
|
|
Sorry for these 2 mistakes, I was trying some codes and I posted the wrong programs.
I've edited my 1st post to correct these mistakes (I use fast i2c, in slave I use i2c_read(), and there is no double start condition).
But my circuit still not work.
When I modify the main loop of master.c as below:
Code: | while(TRUE)
{
delay_ms(100);
printf("\r\n-");
i2c_start ();
i2c_write (0x30);
i2c_write (data_out1);
i2c_write (data_out2);
i2c_stop();
i2c_start ();
i2c_write (0x31);
data_in1=i2c_read(0);
i2c_stop ();
delay_ms(1);
printf("to 0x30:0x%X,0x%X - from 0x31: 0x%X,0x%X", data_out1, data_out2, data_in1, data_in2);
++data_out1;
++data_out2;
}
|
the program work correctly, (i.e. when communicating with just one slave, there is no problem).
But when my master try to communicate with 2 slave, that is what happens:
- 1st time it writes/reads in/from 0x30/0x31, I notice no problem.
- Then, when it tries for the first time to write/read in/from 0x40/0x41, slave interrupts don't happen.
- After that, neither 0x30/0x31 nor 0x40/0x41 answer to any request.
why? |
|
|
01011
Joined: 21 Apr 2010 Posts: 6 Location: earth, solar system
|
|
Posted: Mon Apr 26, 2010 5:13 am |
|
|
hi,
no one has an idea? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Apr 26, 2010 12:23 pm |
|
|
Your test programs are too complicated. You're using i2c FAST mode,
which may not work with a slave. You need to simplify it and strip it
down.
Try the test program shown in this post. Create a 2nd slave. Put it at
address 0x14. See if you can make it work:
http://www.ccsinfo.com/forum/viewtopic.php?t=39242&start=6
Note how, farther along in that thread, he was able to use that code
and make a multi-slave i2c system that worked. It's a 2-page thread. |
|
|
|
|
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
|