|
|
View previous topic :: View next topic |
Author |
Message |
Olufola
Joined: 19 May 2009 Posts: 21
|
streaming data over I2C |
Posted: Thu Aug 06, 2009 12:33 pm |
|
|
Hi,
My sensor network (implemented with i2c) is now working fine with single axis accelerometers. I want to use tri-axial accelerometers for the final implementation but there is a problem I have to solve. Each node in the sensor network has a tri-axial accelerometer sending three bytes of data at a time. How can I read three bytes at a time from each of the i2c network nodes? The inbuilt i2c_read () and i2c_write () functions were designed to read a byte at a time. I tried using repeated i2c_write () functions in the slave and repeated read_i2c () functions in the master but I am not getting correct results. Only the first instance of these functions works correctly. The definition of the problem I have is to transfer data which is more than one byte over i2c interface. Streaming seems to be the solution but the “streaming code” I wrote is not working correctly. The code I wrote follows immediately:
Master code
Code: |
#include <18f4520.h>
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#use i2c(Master, sda=PIN_C4, scl=PIN_C3)
#define SLAVE1_WRT_ADDR 0x14
#define SLAVE1_READ_ADDR 0x15
void main()
{
int8 data1,data2,data3;
while(1)
{
i2c_start();
i2c_write(SLAVE1_READ_ADDR);
data1 = i2c_read(0);
data2 = i2c_read(0);
data3 = i2c_read(0);
i2c_stop();
delay_ms(10);
printf(" [%3U %3U %3U %3U %3U] \r\n", data1,data2,data3);
}
} |
Slave Code
Code: | #include <18F4520.h>
#device adc=8
#fuses HS,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=20000000)
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0x14)
int capture[3];
#INT_SSP
void ssp_interrupt()
{
int8 incoming, state;
state = i2c_isr_state();
if(state < 0x80) // Master is sending data
{
incoming = i2c_read();
}
if(state >= 0x80) // Master is requesting data from slave
{
i2c_write(capture[0]);
i2c_write(capture[1]);
i2c_write(capture[2]);
}
}
void main ()
{
setup_adc_ports(ALL_ANALOG|VSS_VDD);
setup_adc(ADC_CLOCK_DIV_8);
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
while(1)
{
set_adc_channel(0);
delay_us(20);
capture[0] = read_adc();
delay_ms(10);
set_adc_channel(1);
delay_us(20);
capture[1] = read_adc();
delay_ms(10);
set_adc_channel(2);
delay_us(20);
capture[2] = read_adc();
delay_ms(10);
}
} |
|
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Thu Aug 06, 2009 1:00 pm |
|
|
It's not correct to send 3 data bytes at once in the I2C slave ISR. An individual interrupt is generated for each data transfer and you have to send only one byte a time. |
|
|
Olufola
Joined: 19 May 2009 Posts: 21
|
|
Posted: Thu Aug 06, 2009 1:30 pm |
|
|
I am much aware of that fact. I have not been able to come up with any way of getting 3 data bytes sent from the slave. I need the master to get those three data bytes sent out over rs232 at once. It does not matter how those three data bytes get to the master itself. I need help on getting those three data bytes to the master by any means using i2c. |
|
|
mskala
Joined: 06 Mar 2007 Posts: 100 Location: Massachusetts, USA
|
|
Posted: Thu Aug 06, 2009 2:32 pm |
|
|
The easiest way, without learning more about the protocol, is to just do it the way ex_slave.c shows. Use a 'register' addressing scheme and have the master do 3 totally separate requests on each slave. This means all the commands from i2c_start to i2c_stop. In each request the master will send slave address, followed by our new register address, then read what the slave sends, then stop.
Then the slave code will look which register is being requested and only send that one byte in the ISR, which will be called 3 times. |
|
|
|
|
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
|