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

Multiple I2C channels

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



Joined: 03 Aug 2012
Posts: 3

View user's profile Send private message

Multiple I2C channels
PostPosted: Fri Aug 03, 2012 7:48 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Aug 03, 2012 7:55 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Aug 03, 2012 8:05 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Aug 03, 2012 8:46 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Aug 03, 2012 9:18 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Aug 03, 2012 10:09 am     Reply with quote

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

View user's profile Send private message Visit poster's website

PostPosted: Tue Oct 04, 2016 4:33 pm     Reply with quote

I'm trying to use streams for 2 i2c channels using the exact same example you give here but its not compiling.
Code:
i2c_start (oled);

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

View user's profile Send private message

PostPosted: Tue Oct 04, 2016 6:32 pm     Reply with quote

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

View user's profile Send private message Visit poster's website

PostPosted: Tue Oct 04, 2016 6:36 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Oct 04, 2016 7:00 pm     Reply with quote

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

View user's profile Send private message Visit poster's website

PostPosted: Tue Oct 04, 2016 7:02 pm     Reply with quote

Tks, I will!
jeremiah



Joined: 20 Jul 2010
Posts: 1345

View user's profile Send private message

PostPosted: Wed Oct 05, 2016 11:08 am     Reply with quote

dpechman wrote:
I'm trying to use streams for 2 i2c channels using the exact same example you give here but its not compiling.
Code:
i2c_start (oled);

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

View user's profile Send private message Visit poster's website

PostPosted: Wed Oct 05, 2016 12:06 pm     Reply with quote

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.
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