|
|
View previous topic :: View next topic |
Author |
Message |
runemadsen
Joined: 03 Aug 2012 Posts: 3
|
Multiple I2C channels |
Posted: Fri Aug 03, 2012 7:48 am |
|
|
I shall use some sensors with hardcoded and equal i2c addresses.
I therefore try to make up more i2c channels like this:
Code: |
void select_sensor(int n){
if(n==1){
puts("Selecting 1...");
#use i2c(master,sda=PIN_C4, scl=PIN_C3,FORCE_SW)
}
if(n==2) {
puts("Selecting 2...");
#use i2c(master,sda=PIN_C1, scl=PIN_C2,FORCE_SW)
}
|
Put it always end up to use channel 2. Is it possible to make more channels like this? Or is there a better solution?
This way of coding is always OK for rs232 use.
Rune Madsen, Oslo, Norway |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19495
|
|
Posted: Fri Aug 03, 2012 7:55 am |
|
|
This is what stream names are for.
Code: |
#use i2c(master,sda=PIN_C4, scl=PIN_C3,FORCE_SW,STREAM=FIRST)
#use i2c(master,sda=PIN_C1, scl=PIN_C2,FORCE_SW,STREAM=SECOND)
I2C_WRITE(FIRST,0xA0);
val = I2C_READ(FIRST);
I2C_STOP(FIRST);
I2C_WRITE(SECOND,0xA0);
val = I2C_READ(SECOND);
I2C_STOP(SECOND);
//Obviously with suitable transactions for your hardware.
|
Best Wishes |
|
|
runemadsen
Joined: 03 Aug 2012 Posts: 3
|
|
Posted: Fri Aug 03, 2012 8:05 am |
|
|
Yes, but the stream must be a constant, not a variable.
Then I have to copy up the code for each stream, in my case at least five.
Is it a way to avoid that?
Rune |
|
|
runemadsen
Joined: 03 Aug 2012 Posts: 3
|
|
Posted: Fri Aug 03, 2012 8:46 am |
|
|
OK, I have fixed it.
In case others are interested here is what I did:
Code: |
#use i2c(master,sda=PIN_C4, scl=PIN_C3,FORCE_SW,STREAM=ST1)
#use i2c(master,sda=PIN_C1, scl=PIN_C2,FORCE_SW,STREAM=ST2)
.
.
.
void my_i2c_start(int sensor){
if (sensor==1) i2c_start(ST1);
if (sensor==2) i2c_start(ST2);
}
void my_i2c_write(int sensor,int n){
if (sensor==1) i2c_write(ST1,n);
if (sensor==2) i2c_write(ST2,n);
}
int my_i2c_read(int sensor, int ack){
if (sensor==1) return i2c_read(ST1,ack);
if (sensor==2) return i2c_read(ST2,ack);
}
void my_i2c_stop(int sensor){
if (sensor==1) i2c_stop(ST1);
if (sensor==2) i2c_stop(ST2);
}
.
.
.
for(n=1;n<=2;n++){
my_i2c_start(n); // start signal to sensor n
my_i2c_write(n,0b00110000); //adress+low SA+0 for writing
my_i2c_write(n,0x20); // CTRL_REG_A
my_i2c_write(n,0b00100111); // Normal mode, 50Hz, all axes
my_i2c_stop(n);
}
|
Rune |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19495
|
|
Posted: Fri Aug 03, 2012 9:18 am |
|
|
The reason it has to be a constant, is that the compiler is generating completely different code, to access the different pins. However there is nothing to stop you making it variable. So (for example):
Code: |
int1 channel=0;
int i2c_read_channel(int1 nack) {
int8 rval;
if (channel) {
rval=i2c_read(SECOND,nack);
}
else {
rval=i2c_read(FIRST,nack);
}
return rval;
}
//Then set 'channel' = 0/1 to select which stream to use, and call 'i2c_read_channel', instead of i2c_read.
|
Do the same for the other i2c functions, and the compiler will generate one copy of the code for each of the two channels, and you can just change 'channel' to select which one is to be used.
Best Wishes |
|
|
sseidman
Joined: 14 Mar 2005 Posts: 159
|
|
Posted: Fri Aug 03, 2012 10:09 am |
|
|
Depending on your design parameters, there's also the option of using an i2c bus switch like http://www.ti.com/lit/ds/scps169/scps169.pdf, for less than $1 (every time I need to do something odd on an i2c bus, it turns out there's a device for it already). |
|
|
dpechman
Joined: 04 Dec 2007 Posts: 43
|
|
Posted: Tue Oct 04, 2016 4:33 pm |
|
|
I'm trying to use streams for 2 i2c channels using the exact same example you give here but its not compiling.
says *** Error Undefined identifier oled
but it was previously declared in:
Code: | #use i2c(stream=oled,Master,Fast=8000000,sda=PIN_D2,scl=PIN_D0,force_sw)
#use i2c(stream=memory,Master,Fast=8000000,sda=RAM_DATA,scl=RAM_CLK,force_sw) |
if i dont specify the stream and comment the 2nd USE I2C it compiled and works but I need the second i2c to work too.
compiler: 5.050 |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Oct 04, 2016 6:32 pm |
|
|
You didn't post a test program or tell us your PIC. So I made the test
program below, installed PCH vs. 5.050 and it compiled without errors.
Code: | Executing: "C:\Program files\Picc\CCSC.exe" +FH "PCH_Test.c" +DF +LY -T -A +M -Z +Y=9 +EA #__18F46K22=TRUE
Memory usage: ROM=0% RAM=0% - 0%
0 Errors, 0 Warnings.
Build Successful.
Loaded C:\Program Files\PICC\Projects\PCH_Test\PCH_Test.cof.
BUILD SUCCEEDED: Tue Oct 04 17:30:09 2016 |
Test program:
Code: | #include <18F46K22.h>
#fuses INTRC_IO,NOWDT,PUT,BROWNOUT
#use delay(clock=4M)
#use rs232(baud=9600, UART1, ERRORS)
#define RAM_DATA PIN_D0
#define RAM_CLK PIN_D1
#use i2c(stream=oled,Master,Fast=8000000,sda=PIN_D2,scl=PIN_D0,force_sw)
#use i2c(stream=memory,Master,Fast=8000000,sda=RAM_DATA,scl=RAM_CLK,force_sw)
//======================================
void main(void)
{
i2c_start (oled);
while(TRUE);
} |
|
|
|
dpechman
Joined: 04 Dec 2007 Posts: 43
|
|
Posted: Tue Oct 04, 2016 6:36 pm |
|
|
tks for reply, I'm using 18F67J60
AND its compiling with the simple test program:
Code: | #include <18F67J60.h>
#fuses NOWDT, NODEBUG, HS, NOIESO, NOFCMEN, PRIMARY, ETHLED
#use delay(clock=4M)
#use rs232(baud=9600, UART1, ERRORS)
#define RAM_DATA PIN_D0
#define RAM_CLK PIN_D1
#use i2c(stream=oled,Master,Fast=8000000,sda=PIN_D2,scl=PIN_D0,force_sw)
#use i2c(stream=memory,Master,Fast=8000000,sda=RAM_DATA,scl=RAM_CLK,force_sw)
//======================================
void main(void)
{
i2c_start (oled);
while(TRUE);
} |
0 Errors, 0 Warnings. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Oct 04, 2016 7:00 pm |
|
|
OK, start commenting out parts of your large program until you find the
section that is causing the problem. |
|
|
dpechman
Joined: 04 Dec 2007 Posts: 43
|
|
Posted: Tue Oct 04, 2016 7:02 pm |
|
|
Tks, I will! |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1345
|
|
Posted: Wed Oct 05, 2016 11:08 am |
|
|
dpechman wrote: | I'm trying to use streams for 2 i2c channels using the exact same example you give here but its not compiling.
says *** Error Undefined identifier oled
but it was previously declared in:
Code: | #use i2c(stream=oled,Master,Fast=8000000,sda=PIN_D2,scl=PIN_D0,force_sw)
#use i2c(stream=memory,Master,Fast=8000000,sda=RAM_DATA,scl=RAM_CLK,force_sw) |
if i dont specify the stream and comment the 2nd USE I2C it compiled and works but I need the second i2c to work too.
compiler: 5.050 |
which example (there are multiple ones)? the example in the very first post is a very incorrect way to do it, so don't mimic that one.
That said, if you are getting an error saying the identifier doesn't exist, that means your code is ordered wrong. You are most likely trying to use i2c_start() before you have the #use i2c() directive with the oled stream in the code. The #use i2c() must occur before you can use any of the i2c functions. |
|
|
dpechman
Joined: 04 Dec 2007 Posts: 43
|
|
Posted: Wed Oct 05, 2016 12:06 pm |
|
|
Yeah, it was My first impression but after check it all i dont found yet the mistake. If i put i2c_start right after #use i2c it is compiling ok. If i put in main or inside a function it dont. |
|
|
|
|
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
|