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 support@ccsinfo.com

Using built-in I2C functions with 1 clock and multiple data

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







Using built-in I2C functions with 1 clock and multiple data
PostPosted: Tue Oct 15, 2002 7:46 am     Reply with quote

Hi,
I have a project in which eight 2-wire EEPROM devices are connected to 1 clock line and 4 data lines, and will driven in software. Four of the devices have the A1 line pulled high, and the other 4 have it grounded.

My question is:

Can the functions in the CCS I2C library be used to communicate with EEPROM in this configuration or would I have to write my own serial routines? I already wrote some (untested routines) but when I called CCS I was told I could use theirs, and I would rather use the CCS routines if possible as I assume they should be completely tested.

I was told that each I invoke the #USE I2C directive it remains in effect till the next #use I2C is encountered.

If that is the case, I assume I would have to make 4 versions of the driver routines as follows? (just 2 versions for a 24c128 shown below)


#use i2c(master,sda=PIN_B0, scl=PIN_A5) // config for EEPROM 0

void init_ext_eeprom0()
{
int i;

output_float(scl);
output_float(sda);
delay_us(4);
for (i=0;i<3;i++) {
i2c_start();
i2c_write(0xa0);
i2c_write(0xff);
i2c_write(0xff);
if(i==2)
i2c_write(0x2);
else
i2c_write(0x2+i);
i2c_stop();
}
}



void write_ext_eeprom0(long int address, byte data)
{
i2c_start();
i2c_write(((0xa0)|(hi(address)>>5))&0xfe);
i2c_write(hi(address)&0x3f);
i2c_write(address);
i2c_write(data);
i2c_stop();
delay_ms(10);
}

byte read_ext_eeprom0(long int address) {
byte data;

i2c_start();
i2c_write(((0xa0)|(hi(address)>>5))&0xfe);
i2c_write(hi(address)&0x3f);
i2c_write(address);
i2c_start();
i2c_write((0xa1)|(hi(address)>>5));
data=i2c_read(0);
i2c_stop();
return(data);
}

#use i2c(master,sda=PIN_B1, scl=PIN_A5) // config for EEPROM 1

void init_ext_eeprom1()
{
int i;

output_float(scl);
output_float(sda);
delay_us(4);
for (i=0;i<3;i++) {
i2c_start();
i2c_write(0xa0);
i2c_write(0xff);
i2c_write(0xff);
if(i==2)
i2c_write(0x2);
else
i2c_write(0x2+i);
i2c_stop();
}
}


void write_ext_eeprom1(long int address, byte data)
{
i2c_start();
i2c_write(((0xa0)|(hi(address)>>5))&0xfe);
i2c_write(hi(address)&0x3f);
i2c_write(address);
i2c_write(data);
i2c_stop();
delay_ms(10);
}

byte read_ext_eeprom1(long int address) {
byte data;

i2c_start();
i2c_write(((0xa0)|(hi(address)>>5))&0xfe);
i2c_write(hi(address)&0x3f);
i2c_write(address);
i2c_start();
i2c_write((0xa1)|(hi(address)>>5));
data=i2c_read(0);
i2c_stop();
return(data);
}


Thanks for any responses

Mark
___________________________
This message was ported from CCS's old forum
Original Post ID: 7840
johnpcunningham
Guest







Re: Using built-in I2C functions with 1 clock and multiple d
PostPosted: Tue Oct 15, 2002 8:58 am     Reply with quote

<font face="Courier New" size=-1>I don't think that is what you want to do. The easiest and best way would be to make the Address bits on the EEPROMS unique by setting them to Vcc or Gnd. You have A0, A1, A2 and this will give you 000-111 (total of 8) choices to choose from.

I2C is a bus so all of the clock lines and data lines (SCL and SDA) should be tied together and should have about a 1K pull-up resistor on the the SDA and ACL lines.

When you want to address a specific EEPROM, you send out the device address (known as the contol byte) that corresponds to that EEPROM:

Device addressing writes(last bit is a 0)
0xA0 EEPROM0
0xA2 EEPROM1
0xA4 EEPROM2
0xA6 EEPROM3
0xA8 EEPROM4
0xAA EEPROM5
0xAC EEPROM6
0xAE EEPROM7

Device addressing reads (last bit is a 1)
0xA1 EEPROM0
0xA3 EEPROM1
0xA5 EEPROM2
0xA7 EEPROM3
0xA9 EEPROM4
0xAB EEPROM5
0xAD EEPROM6
0xAF EEPROM7

Internally, the EEPROM compares the received device address with the one that is set on its addrress pins. If it matches, then it waits for the next address/data information. IF no match, then it simply ignores the address and data info.

According to the spec on the 24LC128, the data flow should be something like this for a write:
1)Send out physical Device address (control byte)
2)Send out that EEPROMs internal memory address (upper)
3)Send out that EEPROMs internal memory address (lower)
4)Send out the data

You could use #define to define the control bytes so that your code is easier to read. The example in the PICC folder assumes only one external EEPROM. I believe adding in the seperat control byte make the code flow easier. Here is an idea:

#define EE0_R 0xA0
#define EE0_W 0xA1
#define EE1_R 0xA2
#define EE1_W 0xA3
//...and so on

#define EEPROM_SDA PIN_C4
#define EEPROM_SCL PIN_C3
#define hi(x) (*(&x+1))

// config for 16F877
#use i2c(master,sda=EEPROM_SDA, scl=EEPROM_SCL)

void write_ext_eeprom(byte control_byte, long int address, byte data)
{
i2c_start();
i2c_write(control_byte);
i2c_write(hi(address)&0x3f);
i2c_write(address);
i2c_write(data);
i2c_stop();
delay_ms(10);
}

////////////////////////////////
void main(){
write_ext_eeprom(EE0_W, 0x0000, 0xAA);
while(1){};
}
///////////////////////////////



Hope this helps,

JC</font>
___________________________
This message was ported from CCS's old forum
Original Post ID: 7842
Mark DSylva
Guest







Re: Using built-in I2C functions with 1 clock and multiple d
PostPosted: Tue Oct 15, 2002 10:00 am     Reply with quote

:=<font face="Courier New" size=-1>I don't think that is what you want to do. The easiest and best way would be to make the Address bits on the EEPROMS unique by setting them to Vcc or Gnd. You have A0, A1, A2 and this will give you 000-111 (total of 8) choices to choose from.

( a large portion of the response removed)

:=JC</font>

Hi John,
thanks for for taking the time to write such a detailed response.

In actual fact, I am not using the 24C128, but 8 24c1024's.
(I just used code for the 24c128 in my example as I had that handy)

The 24c128 only has 2 device address bits (A0 and A1) and the 24c1024 which I am using only has one (A1) and that is why the hardware designer developed the circuit as it is.
(Each data line is connected to 2 24c1024's, one with A1 pulled high and the other with it tied low)

After posting my question, I tried out the method I asked about and it does indeed appear to work. Here is the code I used for my testing, it calls the functions as shown in my previous post.



main()

{

byte cmd,page;
EEPROM_ADDRESS address0;
EEPROM_ADDRESS address1;


setup_adc_ports(RA0_RA1_ANALOG_RA3_RA2_REF); //

set_tris_a(0x30); // xx00 1111 d7:d0 pins

set_tris_b(0x30); // 0011 0000 d7:d0 pins

output_c(0xff);
set_tris_c(0x00); // 0000 0000 d7:d0 pins are OUTPUTS

init_ext_eeprom0(); // init EEPROM 0
init_ext_eeprom1(); // init EEPROM 1

address0 = 0x0200;
address1 = 0x0200;

page = 0; // this is the P0 bit
value0 = 0x55; // init data to write to EEPROM0
value1 = 0x65; // init data to write to EEPROM1


while(1)
{

DATA_PUP = 1; // activate data line pull-ups
delay_us(20);

WRITE_EXT_EEPROM0( page, address0, value0 );

WRITE_EXT_EEPROM1( page, address1, value1 );

readVal0 = READ_EXT_EEPROM0( page, address0 );

readVal1 = READ_EXT_EEPROM1( page, address1 );

delay_ms(3); // use this spot to set a breakpoint

value0++;
address0++;
value1++;
address1++;

}

}


ReadVal0 and ReadVal1 are properly displaying the same values as Value0 and Value1, so I am quite sure I can access the EEPROM correctly using the CCS functions.

Mark
___________________________
This message was ported from CCS's old forum
Original Post ID: 7847
johnpcunningham
Guest







Re: Using built-in I2C functions with 1 clock and multiple d
PostPosted: Tue Oct 15, 2002 12:54 pm     Reply with quote

Good to hear its working!

Yea, I went up on the Atmel site and checked out the "A0" configuration you spoke about. You are sort of stuck using "software routines" for I2C though; but if it works for you then super.

Another idea would be to use a 3to8 mux to control the A0 pins on the 8 devices. You could use 3 pins on the PIC (connected to the MUX which connects to the 8 A0 pins) to control which EEPROM one you write and could leave the I2C code running out of the PICs internal I2C hardware. I guess it is a tradeoff between code size, speed, and extra components.

Anyway, just some ideas to pass to you if you need them,

Best of luck,

JC
___________________________
This message was ported from CCS's old forum
Original Post ID: 7859
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

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

Re: Using built-in I2C functions with 1 clock and multiple d
PostPosted: Tue Oct 15, 2002 3:59 pm     Reply with quote

Check out Phillips. They invented I2C. They have I2C switches and Muxs. The PCA9548 is an 8-Channel switch perfect for this application.

Regards,
Mark

:=Good to hear its working!
:=
:=Yea, I went up on the Atmel site and checked out the "A0" configuration you spoke about. You are sort of stuck using "software routines" for I2C though; but if it works for you then super.
:=
:=Another idea would be to use a 3to8 mux to control the A0 pins on the 8 devices. You could use 3 pins on the PIC (connected to the MUX which connects to the 8 A0 pins) to control which EEPROM one you write and could leave the I2C code running out of the PICs internal I2C hardware. I guess it is a tradeoff between code size, speed, and extra components.
:=
:=Anyway, just some ideas to pass to you if you need them,
:=
:=Best of luck,
:=
:=JC
___________________________
This message was ported from CCS's old forum
Original Post ID: 7864
Mark DSylva
Guest







Re: Using built-in I2C functions with 1 clock and multiple d
PostPosted: Wed Oct 16, 2002 5:46 am     Reply with quote

As the circuit is already designed I have to use it without modification. as far as the tradeoff between code size, speed and parts:

- this device has to work for a long time on battery power. It is a data logger which wakes up every 0.5 1, 2, or 4 seconds, reads a strain gauge, stores the data in EEPROM and goes back to sleep till the next portB interrupt wakes it up. It has some other functions also, but code size is not expected to be an issue.

- Since the above function is all it does, a software I2C should be fine

- The price has to be as low as possible so we want to minimize the component count.

Thanks for the suggestions.

Mark



:=Good to hear its working!
:=
:=Yea, I went up on the Atmel site and checked out the "A0" configuration you spoke about. You are sort of stuck using "software routines" for I2C though; but if it works for you then super.
:=
:=Another idea would be to use a 3to8 mux to control the A0 pins on the 8 devices. You could use 3 pins on the PIC (connected to the MUX which connects to the 8 A0 pins) to control which EEPROM one you write and could leave the I2C code running out of the PICs internal I2C hardware. I guess it is a tradeoff between code size, speed, and extra components.
:=
:=Anyway, just some ideas to pass to you if you need them,
:=
:=Best of luck,
:=
:=JC
___________________________
This message was ported from CCS's old forum
Original Post ID: 7876
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