|
|
View previous topic :: View next topic |
Author |
Message |
pdswar
Joined: 18 Jul 2006 Posts: 33 Location: Maryland, USA
|
need help with 24FC256 I2C EEPROM |
Posted: Mon Oct 02, 2006 8:33 am |
|
|
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
|
|
Posted: Mon Oct 02, 2006 9:35 am |
|
|
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
|
|
Posted: Mon Oct 02, 2006 9:41 am |
|
|
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
|
|
Posted: Mon Oct 02, 2006 10:03 am |
|
|
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
|
still not working |
Posted: Mon Oct 02, 2006 12:04 pm |
|
|
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
|
|
Posted: Mon Oct 02, 2006 2:51 pm |
|
|
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
|
|
Posted: Mon Oct 02, 2006 4:25 pm |
|
|
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
|
|
Posted: Tue Oct 03, 2006 2:26 am |
|
|
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...).
Best Wishes |
|
|
pdswar
Joined: 18 Jul 2006 Posts: 33 Location: Maryland, USA
|
|
Posted: Fri Oct 06, 2006 8:34 am |
|
|
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. |
|
|
|
|
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
|