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

PIC 18F26K40 i2C Variable Address [SOLVED]

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



Joined: 21 Jan 2020
Posts: 42

View user's profile Send private message

PIC 18F26K40 i2C Variable Address [SOLVED]
PostPosted: Mon Feb 10, 2020 7:11 am     Reply with quote

Hello,

I am communicating with i2c.
I need to use a variable slave address.

I will assign the address according to the key status.
But there are questions i want to ask.

Code:

#byte SSPADD = 0x0F93

void main()
{
      int8 slave_address;

      if(input_state(pin_a0)==1)
      slave_address = 0x10;

      if(input_state(pin_a1)==1)
      slave_address = 0x20;

      SSPADD = slave_address;
      while(1);
}


I use this structure.

RB1 = SCL2
RB2 = SDA2

RC3 = SCL1
RC4 = SDA1



I couldn't understand which address to choose according to what.
Which address should I use for SCL1 and SDA1?

0x0F93 - is this address correct?


Last edited by emaxxenon on Tue Feb 11, 2020 1:16 am; edited 2 times in total
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Mon Feb 10, 2020 8:01 am     Reply with quote

You don't have to fiddle. Just use the CCS functions.

i2c_address(address_to_use);

So:
Code:


      if(input_state(pin_a0)==1)
      I2C_address(0x10);

      if(input_state(pin_a1)==1)
      I2C_address(0x20);


However your approach seems slightly odd, since if A1 is high it'll
override whatever A0 is set to. You might want to think again....
emaxxenon



Joined: 21 Jan 2020
Posts: 42

View user's profile Send private message

PostPosted: Mon Feb 10, 2020 8:50 am     Reply with quote

Ttelmah wrote:
You don't have to fiddle. Just use the CCS functions.

i2c_address(address_to_use);

So:
Code:


      if(input_state(pin_a0)==1)
      I2C_address(0x10);

      if(input_state(pin_a1)==1)
      I2C_address(0x20);


However your approach seems slightly odd, since if A1 is high it'll
override whatever A0 is set to. You might want to think again....


Thanks for your answer.

- Undefined identifier -- I2C_address

Do i need to add anything to the i2c definitions?

Code:
#use i2c (SLAVE, SDA=PIN_C4, SCL=PIN_C3, force_hw, fast=500000)


My current settings are like this.
How should i make the i2c settings as you said?
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Mon Feb 10, 2020 9:11 am     Reply with quote

Apologies. The command is I2C_slaveaddr.
That'll teach me to post without checking....

Your syntax though is wrong. You are not using the hardware I2C.

You need:
Code:

#PIN_SELECT SCK1=PIN_C3
#PIN_SELECT SDA1=PIN_C4

#use i2c (SLAVE, I2C1, address=0x20)

void main()
{


   if(input_state(pin_a0)==1)
      I2C_slaveaddr(0x10);
   if(input_state(pin_a1)==1)
      I2C_slaveaddr(0x20);


The #use should always have an address. Make it the 'default', and then
change it to the new values you want.
If you don't specify an address you can get odd behaviour depending on
what is being sent on the bus. Safer to set it.
On chips using PPS, you have to select the port with PPS. #USE will
not reliably setup PPS for you (current compilers are partially doing it
but seem to get it wrong as often as right - again safer to use PPS
yourself).
gjs_rsdi



Joined: 06 Feb 2006
Posts: 468
Location: Bali

View user's profile Send private message Send e-mail

PostPosted: Mon Feb 10, 2020 9:46 pm     Reply with quote

Why not:
Code:

   if(input_state(pin_a0)==1)
   {
      I2C_slaveaddr(0x10);
   }
   else
  {
      I2C_slaveaddr(0x20);
  }


Best wishes
Joe
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Tue Feb 11, 2020 12:35 am     Reply with quote

Exactly.
Makes a lot more sense than what was being done. Very Happy
emaxxenon



Joined: 21 Jan 2020
Posts: 42

View user's profile Send private message

PostPosted: Tue Feb 11, 2020 12:59 am     Reply with quote

Thank you. Much better than before.
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Tue Feb 11, 2020 4:34 am     Reply with quote

In fact, assuming these inputs are just a jumper for example, then set the
default address in the #use, and just have it select the alternative is the
jumper is made. One jumper, and two addresses. Easy. Very Happy
emaxxenon



Joined: 21 Jan 2020
Posts: 42

View user's profile Send private message

PostPosted: Tue Feb 11, 2020 6:34 am     Reply with quote



There will be 8 slaves. All circuits are the same.
But they will be arranged in a certain order.
According to this order, their addresses will change.

I had to assign an address based on the switch location.
It worked the way you suggested.

Code:

   if(input_state(pin_a0)==1)
   {
      A=1;
   }
   if(input_state(pin_a1)==1)
   {
      B=2;
   }
   if(input_state(pin_a2)==1)
   {
      C=4;
   }

SWITCH = A+B+C;

   if(SWITCH==0)
   {
     I2C_slaveaddr(0x10);
   }
   if(SWITCH==1)
   {
     I2C_slaveaddr(0x12);
   }
   if(SWITCH==2)
   {
     I2C_slaveaddr(0x14);
   }
   if(SWITCH==3)
   {
     I2C_slaveaddr(0x16);
   }
   if(SWITCH==4)
   {
     I2C_slaveaddr(0x18);
   }
   if(SWITCH==5)
   {
     I2C_slaveaddr(0x20);
   }
   if(SWITCH==6)
   {
     I2C_slaveaddr(0x22);
   }
   if(SWITCH==7)
   {
     I2C_slaveaddr(0x24);
   }
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Tue Feb 11, 2020 8:04 am     Reply with quote

Too complex:
Code:

   A=0x20;

   if(input_state(pin_a0)==1)
   {
      A+=2;
   }
   if(input_state(pin_a1)==1)
   {
      A+=4;
   }
   if(input_state(pin_a2)==1)
   {
      A+=8;
   }
   I2C_slaveaddr(A);


You get 0x20 if the inputs are 000. Then 0x22 if they are 001. 0x24 if
they are 010 etc. Right up to 0x2E if they are 111.

8 addresses, just one variable instead of three, and no switch statement.
emaxxenon



Joined: 21 Jan 2020
Posts: 42

View user's profile Send private message

PostPosted: Wed Feb 12, 2020 1:32 am     Reply with quote

Ttelmah wrote:
Too complex:
Code:

   A=0x20;

   if(input_state(pin_a0)==1)
   {
      A+=2;
   }
   if(input_state(pin_a1)==1)
   {
      A+=4;
   }
   if(input_state(pin_a2)==1)
   {
      A+=8;
   }
   I2C_slaveaddr(A);


You get 0x20 if the inputs are 000. Then 0x22 if they are 001. 0x24 if
they are 010 etc. Right up to 0x2E if they are 111.

8 addresses, just one variable instead of three, and no switch statement.


Thanks for your answer.


A0 - A1 - A2
(0) - (0) - (0)
==> A=0x20;


A0 - A1 - A2
(0) - (0) - (1)
==> A=0x22;


A0 - A1 - A2
(0) - (1) - (0)
==> A=0x24;


A0 - A1 - A2
(0) - (1) - (1)
==> A=0x26;


A0 - A1 - A2
(1) - (0) - (0)
==> A=0x28;


A0 - A1 - A2
(1) - (0) - (1)
==> A=0x2A;


A0 - A1 - A2
(1) - (1) - (0)
==> A=0x2C;


A0 - A1 - A2
(1) - (1) - (1)
==> A=0x2E;


Will this be the case according to the code?

Code:

   if(input_state(pin_a0)==1)
   {
      A+=2;
   }


I don't understand how this part works? (A+=2;)
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Wed Feb 12, 2020 2:39 am     Reply with quote

In C, there is a standard shortcut.

Variable mathsoperator = val;

If you have a variable 'A', then

A*=2;

multiplies A by 2 and stores the result back in A.

So

A+=2;

Adds 2 to A.

It's equivalent to A=A+2, but the compiler can optimise it a little better.

Use it whenever you want to do any maths operation on a variable and
put the result back into the same variable.

A/=4;

etc.. etc..
emaxxenon



Joined: 21 Jan 2020
Posts: 42

View user's profile Send private message

PostPosted: Wed Feb 12, 2020 5:49 am     Reply with quote

I have a lot to learn.
Thanks for information. My code has gotten much better.
temtronic



Joined: 01 Jul 2010
Posts: 9225
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Feb 12, 2020 7:20 am     Reply with quote

Another possible way to do it as the address switches are on one port,in sequence..

Read the port, combine with a mask( lower 3 bits), the result should be the device address offset,so add it to the base address.

While I haven't tried it , it may produce shorter code, be quicker and be easier to understand.

Also, get into the habit of adding comments //at the end of a line of code

Comments cost nothing except the time to type them but hours or days from now you'll SEE what that line of code was supposed to do.

Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Wed Feb 12, 2020 7:52 am     Reply with quote

Potentially.
However it does mean having to do a byte wide read on B, which may
cause issues, and you have to multiply the result by two, since the I2C
address go up in twos.
I think given how small the test and additions are, the read, multiply and
add offset approach will probably be as large or larger, and given that
you probably don't want to do a whole port read, the existing approach
is probably the best way to go.
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