| 
	
	|  |  |  
	
		| View previous topic :: View next topic |  
		| Author | Message |  
		| Mark DSylva Guest
 
 
 
 
 
 
 
			
			
			
			
			
			
			
			
			
 
 | 
			
				| Using built-in I2C functions with 1 clock and multiple data |  
				|  Posted: Tue Oct 15, 2002 7:46 am |   |  
				| 
 |  
				| 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 |  
				|  Posted: Tue Oct 15, 2002 8:58 am |   |  
				| 
 |  
				| <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 |  
				|  Posted: Tue Oct 15, 2002 10:00 am |   |  
				| 
 |  
				| :=<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 |  
				|  Posted: Tue Oct 15, 2002 12:54 pm |   |  
				| 
 |  
				| 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
 
 
			      
 
 | 
			
				| Re: Using built-in I2C functions with 1 clock and multiple d |  
				|  Posted: Tue Oct 15, 2002 3:59 pm |   |  
				| 
 |  
				| 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 |  
				|  Posted: Wed Oct 16, 2002 5:46 am |   |  
				| 
 |  
				| 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
 |  |  
		|  |  
		|  |  
  
	| 
 
 | 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
 
 |