sayonee
Newbie level 6
Hello there I have almost completed coding interfacing with EEPROM - AT24C04 using I2C protocol,But using this I am able to perform a "READ" operation but not a WRITE.
I am using a similar kind of program( found on this forum ) for interfacing the EEPROM using I2C and this program works.
This program that I found can do both READ/WRITE....But when I burn my program on the MC ..it cannot write but it can read the values stored at addresses 0x000,0x001,0x002 using the program found on this forum.
Attached to this post is my source code ..can someone let me know as to what mistake I am doing ...thanks
I am using a similar kind of program( found on this forum ) for interfacing the EEPROM using I2C and this program works.
This program that I found can do both READ/WRITE....But when I burn my program on the MC ..it cannot write but it can read the values stored at addresses 0x000,0x001,0x002 using the program found on this forum.
Attached to this post is my source code ..can someone let me know as to what mistake I am doing ...thanks
Code:
/*
AT24C04 EERPOM HEADER FILE
*/
#include <reg51.h>
#include <intrins.h>
#include <stdlib.h>
#include <string.h>
#include "AT24C04-EEPROM.h"
#include "AT24C04-LCD.h"
#include "AT24C04-I2C.h"
void main()
{
unsigned char value2,i;
char *str1 = "SUCCESS";
char *str2 = "FAIL";
unsigned char *p;
lcdinitialize();
EEPROMwrite( 0x000,'Z' );
lcddata('M');
value2 = EEPROMread( 0x000 );
Delay(150);
lcddata(value2);
}
Code:
/*
AT24C04 I2C BUS HEADER FILE - ROUTINE/FUNCTION DECLARATIONS
*/
#ifndef __I2C_H
#define __I2C_H
void I2C_delay(void); //Delay needed while doing I2C related coding
void I2C_clock(void);
void I2C_start(void);
void I2C_stop(void);
void I2C_write( unsigned char );
unsigned char I2C_read( void );
void I2C_ackpolling(void);
void I2C_check_NACK(void);
void I2C_ack(void); //master sending the acknowlege to slave
void I2C_nack(void);
#endif
Code:
#include <reg51.h>
#include <intrins.h>
#include "AT24C04-LCD.h"
#include "AT24C04-I2C.h"
sbit SDA = P3^6; //refer circuit board schematics for the assignment of SDA & SCL
sbit SCL = P3^7;
bit NACK; //bit FLAG to set status of NACK
void I2C_delay(void) //Delay needed while doing I2C related coding
{
_nop_();
}
void I2C_clock(void)
{
//I2C_delay();
SCL = 1;
I2C_delay();
SCL = 0;
}
void I2C_start(void)
{
SDA = 1;
I2C_delay();
SCL = 1;
I2C_delay();
SDA = 0;
I2C_delay();
SCL = 0;
I2C_delay();
}
void I2C_stop(void)
{
SCL = 1;
I2C_delay();
SDA = 0;
I2C_delay();
SDA = 1;
I2C_delay();
SCL = 0;
}
/*void I2C_ackpolling(void)
{
SDA = 1; //release SDA high
I2C_delay();
SCL = 1; //release SCL high for acknowledge,start clock
I2C_delay();
while( SDA ); //wait,loop while SDA = 1( HIGH ),if HIGH this means EEPROM is busy,will wait till it pulls SDA low
SCL = 0;
} */
void I2C_check_NACK()
{
SDA = 1; //release SDA high
I2C_delay();
SCL = 1; //release SCL high for acknowledge,start clock
I2C_delay();
if( !SDA ) //Check for acknowledge status from slave if SDA == 0,then ACK is 0 & OK from slave
{
SCL = 0; // pull down SCL,end the clock for acknowledge
I2C_delay();
NACK = 0;
//lcddata('R');
}
else // SDA status is still HIGH so NACK ,i.e NACK is 1
{
SCL = 0;
NACK = 1; //ACK -acknowledge bit not received from EEPROM(receiver),EEPROM has pulled SDA high
lcddata('W'); //to indicate on LCD of a possible ACK failure
}
}
void I2C_write( unsigned char userdata )
{
bit databit; //bit variable for determining whether bit is 1 or 0
unsigned char i; //loop counter variable for a byte received
unsigned char temp;
//lcddata( userdata );
SCL = 0;
for( i = 0; i<8 ;i++)
{
databit = SDA = userdata & 0x80; //store MSB in databit
temp = (unsigned char )databit + 0x30; //assign it to the SDA
lcddata(temp);
I2C_delay(); //clock out the bit,do this for a byte
I2C_clock();
userdata = userdata << 1; // left shift to determine next MSB
}
}
unsigned char I2C_read( void )
{
bit read_bit;
unsigned char received_data = 0x00,i;
SDA = 1;
SCL = 0;
for( i = 0; i< 8 ;i++)
{
SCL = 1; //set SCL high,start of Clock,SCL = high here since before making it low the ACK is read in
I2C_delay();
received_data = received_data << 1; //left shit,MSB goes in first
received_data = received_data | (unsigned char )SDA;
SCL = 0; //set SCL low,end the clock
//received_data = received_data | read_bit;
}
SDA = 0;
// received_data = received_data | read_bit;
lcddata( received_data );
//lcddata( received_data );
return received_data;
}
void I2C_ack(void) //master sending the acknowlege to slave
{
SDA = 0; //clear SDA
I2C_delay();
//clock out
I2C_clock();
SDA = 1;
}
void I2C_nack(void) //master sending NACK to slave
{
SDA = 1; //set SDA high
I2C_delay();
I2C_clock();
SDA = 0; //set SCL to default high
}
Code:
/*
AT24C04 EEPROM HEADER FILE - ROUTINE/FUNCTION DECLARATIONS
*/
#ifndef __EEPROM_H
#define __EERPOM_H
#define EEPROM_ID 0xA0 //in binary this would be 10100000 for read,and 0xA1 = 10100001 for write
extern bit NACK;
extern SCL;
extern SDA;
unsigned char EEPROMread( unsigned char );
void EEPROMwrite( unsigned char ,unsigned char );
#endif
Code:
/*
AT24C04 EERPOM C FILE
*/
#include <reg51.h>
#include <intrins.h>
#include "AT24C04-I2C.h" //HEADER FILE FOR I2C RELATED OPERATIONS
#include "AT24C04-EEPROM.h"
#include "AT24C04-LCD.h"
/*PLEASE REFER AT24C04 datasheet's PAGE 12 - FIGURE 11 FOR THIS RANDOM READ IMPLEMENTATION */
unsigned char EEPROMread( unsigned char eeprom_word_address )
{
unsigned char received_data;
NACK = 1;
while(NACK)
{
I2C_start();
I2C_write( EEPROM_ID ); //to identify the particular EEPROM device on I2C bus
I2C_check_NACK(); //call function to check for ACK/NACK and set the flag NACK
if( NACK )
continue;
lcddata('4');
I2C_write( eeprom_word_address ); //write to the word address in that particular EEPROM device
I2C_check_NACK(); //call function to check for ACK/NACK and set the flag NACK
if( NACK )
continue;
lcddata('5');
I2C_start(); //REPEATED START
I2C_write( EEPROM_ID + 1 ); // EEPROM_ID+1, R/W bit is now 1 for READ,passed to indicate reading from EEPROM device
I2C_check_NACK(); //call function to check for ACK/NACK and set the flag NACK
if( NACK )
continue;
lcddata('6');
received_data = I2C_read(); //read data from that particular word address
I2C_ack(); //SEND THE ACKNOWLEDGE TO TRANSMITTER - HERE TRANSMITTER IS EEPROM
lcddata('7');
//lcddata( received_data );
I2C_nack(); //MCU sending NOACK because no further reading is to be done,NACK necessary for STOPing condition
I2C_stop(); // Stop I2C bus operations
}
return received_data;
}
void EEPROMwrite( unsigned char eeprom_word_address,unsigned char store_data )
{
NACK = 1; //NACK intially set to 1 to make sure the while() loops execute,inside while loop it
// may be set to 0 if ACK from transmitter is 0 ..
while( NACK ) //NACK global bit variable is set if no ACK in I2C routine..
{
I2C_start(); //start I2C bus operation
//lcddata( EEPROM_ID );
I2C_write( EEPROM_ID ); //get to interact the particular EEPROM device using its unique address
I2C_check_NACK(); //call function to check for ACK/NACK and set the flag NACK
if( NACK )
continue;
//lcddata('1'); //PRINT SUCH VALUES TO LCD TO KNOW THE SEQUENCE OF STEPS HAPPENING
I2C_write( eeprom_word_address ); //send particular word address,where data from RAM is to be written in that EEPROM device
I2C_check_NACK(); //call function to check for ACK/NACK and set the flag NACK
if( NACK )
continue;
//lcddata('2');
I2C_write( store_data );
I2C_check_NACK(); //call function to check for ACK/NACK and set the flag NACK
if( NACK )
continue;
//lcddata('3');
I2C_stop(); //stop I2C bus operations
}
}