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

need help with 24FC256 I2C EEPROM

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



Joined: 18 Jul 2006
Posts: 33
Location: Maryland, USA

View user's profile Send private message

need help with 24FC256 I2C EEPROM
PostPosted: Mon Oct 02, 2006 8:33 am     Reply with quote

I am using PIC 18F6722 and 24FC256 I2C EEPROM.

http://ww1.microchip.com/downloads/en/DeviceDoc/39646b.pdf
http://ww1.microchip.com/downloads/en/devicedoc/21203N.pdf#search=%2224FC256%22

*****Pin configurations PIC 18F6722******
BUZZER = PIN_C2
WP = PIN_A2
SDA = PIN_D5 10k resistor and +5V pull-up
SCL = PIN_D6 10k resistor and +5V pull-up
************************************


*****Pin configurations 24FC256*********
Not Connected = PIN_1 (A0)
Not Connected = PIN_2 (A1)
Pull-up = PIN_3 (A2) 10k resistor and +5V pull-up
GND = PIN_4
SDA = PIN_5
SCL = PIN_6
WP = PIN_7
VCC = PIN_8 (+5V)
************************************

Same I2C bus is shared by a I2C TC74 Temp. Sensor and it works fine.
I am trying to store a 8-bit integer into EEPROM and read it back. If the read data and the original data matches, the buzzer should beep.

Here is my code:

#include <18F6722.h>
#device adc=10

#fuses INTRC, NOWDT, NOPROTECT, PUT, BROWNOUT, NOLVP
#include <stdio.h>
#include <stdlib.h>
#include <pic_micro.h>


#use delay(clock=16000000)
#use I2C(master, sda=PIN_D5, scl=PIN_D6 )

//Pins already defined in "pic_micro.h"
//#define BUZZER PIN_C2
//#define FP_SCL PIN_D6
//#define FP_SDA PIN_D5

void buzzerbeep(void);
void i2c_eeprom_write(int8 addrh,int8 addrl,int8 data);
int8 i2c_eeprom_read(int8 addrh,int8 addrl);

void main()
{
int8 read_data,addrh,addrl;
int8 original[8]={0b10101010};//test data

i2c_eeprom_write(addrh,addrl,original); // Is it enough to write a 8-bit integer

while(1)
{
read_data=i2c_eeprom_read(addrh,addrl); /// Is it enough to read a 8-bit integer

if(read_data==original)
{
buzzerbeep();
buzzerbeep();
buzzerbeep();
buzzerbeep();
}
}
}

void buzzerbeep(void)
{
output_high(BUZZER);
delay_us(209);
output_low(BUZZER);
delay_us(209);
}


/************************** Eeprom Write **************************************/


void i2c_eeprom_write(int8 addrh,int8 addrl,int8 data)
{
i2c_start();
i2c_write(0xA2); // send chip addr and set data to write mode
i2c_write(addrh); // high addr bits
i2c_write(addrl); // low addr bits
i2c_write(data); // write data
i2c_stop();
delay_ms(5);
}

/************************** Eeprom Read **************************************/


int8 i2c_eeprom_read(int8 addrh,int8 addrl)
{
int8 temp;

i2c_start();

i2c_write(0xA2); // send address data in write mode
i2c_write(addrh); // high addr bits
i2c_write(addrl); // low addr bits

i2c_start();
i2c_write(0xA2); // change to read mode
temp = i2c_read(0); // reads are not acknowledged (0)

i2c_stop(); // if no stop() can get continuous read

return temp;
}


Any suggestions to fix this code will be appreciated.
Ttelmah
Guest







PostPosted: Mon Oct 02, 2006 9:35 am     Reply with quote

You are not changing the chip to read mode.
Address needs to be 0xA3 in the second part of the read program.
As a general comment, please use the 'code' buttons to post code. It makes it far easier to read.

Best Wishes
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Mon Oct 02, 2006 9:41 am     Reply with quote

As another comment, the PIC18F6722 using the INTRC clock option will run at a maximum of 4MHz, not your 16MHz. Fix this to get I2C running at your intended speed.
Ttelmah
Guest







PostPosted: Mon Oct 02, 2006 10:03 am     Reply with quote

Actually the internal oscillator can be used with the PLL, to give 16MHz.
This however needs to be setup in software (it is not a 'fuse' option), and whether the compiler is smart enough to automatically enable this, I don't know (this sort of thing has been 'variable' with the versions...). Adding 'setup_oscillator(OSC_16MHZ);', at the start of main, will automatically set the extra bit if it is not already being done. The internal oscillator with PLL, can give operation up to 32MHz on these chips.

Best Wishes
pdswar



Joined: 18 Jul 2006
Posts: 33
Location: Maryland, USA

View user's profile Send private message

still not working
PostPosted: Mon Oct 02, 2006 12:04 pm     Reply with quote

Thank you Ttelmah and ckielstra for replying.

I have changed address in read mode to 0xA3 and also the oscillator setting to 4MHz. (even though I2C Temp Sensor works fine at 16MHz)

Now, the data stored in read_data is 0b11111111
i.e buzzer beeps when

Code:
if(read_data==0b11111111) // buzzer beeps with this line
   {
   buzzerbeep();
   buzzerbeep();
   }


Here is my modified code:

Code:
#use delay(clock=4000000) //  Set clock to 4MHz
#use I2C(master, sda=PIN_D5, scl=PIN_D6 )

//Pins already defined in "pic_micro.h"
//#define BUZZER   PIN_C2
//#define FP_SCL   PIN_D6
//#define FP_SDA   PIN_D5

void buzzerbeep(void);
void i2c_eeprom_write(int8 addrh,int8 addrl,int8 data);
int8 i2c_eeprom_read(int8 addrh,int8 addrl);

void main()
{
int8 read_data,addrh,addrl;
int8 original[8]={0b10101010};//test data
//addrh=original[0];
//addrl=original[7];

i2c_eeprom_write(addrh,addrl,original);

while(1)
{
read_data=i2c_eeprom_read(addrh,addrl);

if(read_data==original)
//if(read_data==0b11111111) // buzzer beeps with this line
   {
   buzzerbeep();
   buzzerbeep();
   }
}
}

void buzzerbeep(void)
{
output_high(BUZZER);
delay_us(209);
output_low(BUZZER);
delay_us(209);
}


/************************** Eeprom Write **************************************/
/**** Writes a single byte to the eeprom supports 2^16 addresses ****/

void i2c_eeprom_write(int8 addrh,int8 addrl,int8 data)
{
        i2c_start();
        i2c_write(0xA2);                // send chip addr and set data to write mode
        i2c_write(addrh);               // high addr bits
        i2c_write(addrl);               // low addr bits
        i2c_write(data);                // write data
        i2c_stop();
        delay_ms(5);
}

/************************** Eeprom Read **************************************/
/**** Reads a single byte from the eeprom supports 2^16 addresses ****/

int8 i2c_eeprom_read(int8 addrh,int8 addrl)
{
        int8 temp;

        i2c_start();

        i2c_write(0xA2);                // send address data in write mode
        i2c_write(addrh);               // high addr bits
        i2c_write(addrl);               // low addr bits

        i2c_start();
        i2c_write(0xA3);                // change to read mode
        temp = i2c_read(0);             // reads are not acknowledged (0)

        i2c_stop();                     // if no stop() can get continuous read

return temp;
}


Please help me fix this code.
Ttelmah
Guest







PostPosted: Mon Oct 02, 2006 2:51 pm     Reply with quote

You are not putting any values into addrl/h. As such they may be anything.
Your definition of 'original', will only put a value into original[0].
You then hand the low 8 bits of the _address_ of 'original' to the write routine. This is what will be written, and will probably not match the full address (which is a 16bit value).
You also do not check if communication is actually working.
Your address is wrong for the wiring you describe. The address you have is:
0b1010100x
0xA8, not 0xA2.
Just changing the 'core' , to fix most of these. You will need to change the prototypes etc..

Code:

void main() {
  int8 read_data;
  //Set the address
  int16 address = 0;
  int8 original = 0b10101010;//test data

  if (i2c_eeprom_write(address,original)==FALSE) {
    //Put code here to say that the chip is not responding...
  }

  while(1) {
    read_data=i2c_eeprom_read(address);

    if(read_data==original) {
      buzzerbeep();
      buzzerbeep();
    }
  }
}

/* Union, to allow simple access to high/low bytes of the address */
union word_splitter {
   int16 address;
   int8 b[2];
}

/* Eeprom Write
  Writes a single byte to the eeprom supports 2^16 addresses */
int1 i2c_eeprom_write(union word_splitter val,int8 data)
{
        i2c_start();
        if (i2c_write(0xA8)==1) {
           return FALSE;        // send chip addr and set data to write mode
        }
        i2c_write(val.b[1]);   // high addr bits
        i2c_write(val.b[0]);   // low addr bits
        i2c_write(data);        // write data
        i2c_stop();
        delay_ms(5);
        return TRUE;
}

/* Eeprom Read
  Reads a single byte from the eeprom supports 2^16 addresses */
int8 i2c_eeprom_read(union word_splitter val) {
   int8 temp;

   i2c_start();

   i2c_write(0xA8);              // send address data in write mode
   i2c_write(val.b[1]);          // high addr bits
   i2c_write(val.b[0]);          // low addr bits

   i2c_start();
   i2c_write(0xA9);              // change to read mode
   temp = i2c_read(0);         // reads are not acknowledged (0)

   i2c_stop();                       // if no stop() can get continuous read

   return temp;
}


Best Wishes
rnielsen



Joined: 23 Sep 2003
Posts: 852
Location: Utah

View user's profile Send private message

PostPosted: Mon Oct 02, 2006 4:25 pm     Reply with quote

You have stated that you are not connecting A0 & A1 to anything (left floating). If you read the spec sheet for the eeprom, you will notice that it states that the address pins (A0-A2) need to be pulled high or pulled low. They cannot be left floating. You don't need a current limiting resistor tied to them either. Simply tie them to VCC or GND. This could cause erratic addressing for the eeprom.

Ronald
Ttelmah
Guest







PostPosted: Tue Oct 03, 2006 2:26 am     Reply with quote

Actually, I thought that too, but if you re-read the data sheet, it does allow the pins to be left floating (though I consider this 'bad practice', and 'to be avoided).
The section is a little 'unclear'. Section 2.1. Middle paragraph, says "if these pins are left unconnected, the pins will be pulled down internally to Vss". However latter is the section (where dealing with a unit which has the address set from a microprocessor), it says 'for applications in which these pins are controlled by a microprocessor, or other programmable device, the chip address pins must be driven to a logic '0' or a logic '1' before normal device operation can proceed".
It acually appears that the pins have a 'weak pull down' (similar to the pull up on the PIC portB pins), and that the second part is only saying that to select the address the logic level must be set to the required pattern before starting (makes sense...). Smile

Best Wishes
pdswar



Joined: 18 Jul 2006
Posts: 33
Location: Maryland, USA

View user's profile Send private message

PostPosted: Fri Oct 06, 2006 8:34 am     Reply with quote

Ttelmah and rnielsen,

Thank you very much.

I tied A0 and A1 pins to GND while A2 is pulled high.

It is working now.

Have a nice weekend.
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