Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- 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 have checked for the WP(write protect pin) and its alright - connected to ground.
- 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.
- <pre>
- /*
- 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"
- /*********************************************************************************
- AT24C04 - C FILE MAIN FUNCTION
- *********************************************************************************/
- void main()
- {
- unsigned char value2;
- lcdinitialize();
- EEPROMwrite( 0x000,'Z' );
- lcddata('M');
- value2 = EEPROMread( 0x000 );
- Delay(150);
- lcddata(value2);
- }
- </pre>
- <pre>
- /*********************************************************************************
- 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
- </pre>
- <pre>
- /*********************************************************************************
- AT24C04 - I2C C FILE - FUNCTIONS/ROUTINES
- *********************************************************************************/
- #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
- }
- </pre>
- <pre>
- /*********************************************************************************
- 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
- </pre>
- <pre>
- /*********************************************************************************
- AT24C04 EERPOM C FILE - ROUTINES/FUNCTIONS
- **********************************************************************************/
- #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
- }
- }
- </pre>
- <pre>
- /**********************************************************************************
- LCD ROUTINES/FUNCTIONS
- **********************************************************************************/
- #include "AT24C04-LCD.h"
- #include <intrins.h>
- void Delay( unsigned int itime)
- {
- int i,j;
- for( i = 0; i < itime ;i++)
- for( j = 0; j < 1275; j++);
- }
- void lcdcmd( unsigned char value )
- {
- lcd_port = value;
- RS = 0; //register select = 0 for command mode
- EN = 1; //latch enable = HIGH
- _nop_();
- EN = 0; //latch enable = LOW
- Delay(10);
- return;
- }
- void lcddata( unsigned char value )
- {
- lcd_port = value;
- RS = 1; //register select = 1 for data register
- EN = 1; //latch enable = HIGH
- _nop_();
- EN = 0; //latch enable = LOW
- Delay(30);
- return;
- }
- void lcdinitialize(void)
- {
- unsigned char l[10] = {0x38,0x0E,0x06,0x01,0x41};
- unsigned char i;
- for(i = 0 ;i <= 3 ; i++)
- lcdcmd(l[i]); //sending basic LCD commands to LCD
- }
- </pre>
- <pre>
- /**********************************************************************************
- AT24C04 LCD HEADER FILE - ROUTINE/FUNCTION DECLARATIONS
- **********************************************************************************/
- #include <reg51.h>
- #ifndef __LCD_H
- #define __LCD_H
- //SFR names declarations
- sfr lcd_port = 0x90; //address of PORT P1 ,used for data lines to LCD
- sbit EN = P3^4;
- sbit RS = P3^5;
- //sbit RW =
- //ANSI STYLE PROTOTYPE
- void lcddata( unsigned char value);
- void lcdcmd( unsigned char value);
- void Delay( unsigned int itime );
- void lcdinitialize(void);
- #endif
- </pre>
- /****************************************************************************/
- /****************************CODE FOUND ON THE FORUM*************************/
- #include "AT24C04-LCD.h"
- #include <reg51.h>
- #include <intrins.h>
- sbit sda = P3^6;
- sbit sclk = P3^7;
- /************************** prototypes begin*******************/
- void send_byte_s_eeprom(char );
- void send_to_mem(unsigned char , unsigned char );
- unsigned char get_byte_s_eeprom();
- void noacknowledge();
- void acknowledge();
- unsigned char get_from_mem(unsigned char );
- void wait();
- void start_s_eeprom();
- void stop_s_eeprom();
- /************************** prototypes end******************/
- void send_to_mem(unsigned char s_address, unsigned char s_data)
- {
- start_s_eeprom(); // sending start condition to eeprom
- send_byte_s_eeprom(0XA0); // A0 = 10100000 = sending device address word for write
- acknowledge();
- send_byte_s_eeprom(s_address); // sending data address
- acknowledge();
- send_byte_s_eeprom(s_data); // sending data
- acknowledge();
- stop_s_eeprom(); // sending stop condition to eeprom
- // acknowledge();
- }
- // fxn to get the data back frm the serial eeprom
- // just give the adress from where the data is to be retrieved
- unsigned char get_from_mem(unsigned char s_address)
- {
- unsigned char i;
- //-------dummy write seq----+ word address--------------------------------------
- start_s_eeprom(); // sending start condition to eeprom
- send_byte_s_eeprom(0XA0); // sending A0 = 10100000 = device address word for write
- acknowledge();
- send_byte_s_eeprom(s_address); // sending data address
- acknowledge();
- //----------------dummy over----------------------------------------------------
- start_s_eeprom();
- send_byte_s_eeprom(0XA1); // sending A1 =10100001 = device adress word for read
- acknowledge();
- i = get_byte_s_eeprom(); // sending data
- noacknowledge();
- stop_s_eeprom(); // sending stop condition to eeprom
- return(i);
- }
- /* fxn to transmit a byte to the eeprom
- this fxn just send the 8 bits serialy on the SDA line
- just pass the byte to be transmitted as parameter to this fxn */
- void send_byte_s_eeprom(char s_byte)
- {
- //unsigned char temp ;
- char i ;
- for(i = 7 ; i >= 0 ; i--) //scan data do be place in SDA
- {
- /* note SCL is low during transitions on SDA */
- if( ((s_byte >> i) & 0x01) == 0) //check individual bits
- sda = 0;
- else
- sda = 1;
- sclk = 1;
- wait();
- sclk = 0;
- }
- }
- // fxn to receive 8 bits serialy from sda line
- // this is not a fxn to read from eeprom
- // it just receives 8 bits serialy and retuns the byte received to the calling fxn
- unsigned char get_byte_s_eeprom()
- {
- char temp, temp_h, i;
- temp = 0;
- temp_h = 1;
- sda = 1; // making SDA as input pin for microcontroller
- sclk = 0;
- for(i = 7; i >=0 ; i--)
- {
- sclk = 1;
- if(sda == 1)
- {
- temp = temp | temp_h<<i ;
- }
- wait();
- sclk = 0;
- }
- sclk = 0;
- return(temp);
- }
- // fxn to send the start condition
- void start_s_eeprom()
- {
- sda = 1;
- sclk = 1;
- wait();
- sda = 0;
- sclk = 0;
- }
- // fxn to send stop condition
- void stop_s_eeprom()
- {
- sda = 0;
- sclk = 1;
- wait();
- sda = 1;
- sclk = 0;
- }
- // fxn for acknowledging the eeprom
- // this fxn actualy does not read the acknowledge signal
- // it just waits for sufficient time and assumes that the eeprom has given tha ack by the time the wait gets over
- void acknowledge()
- {
- sda = 0;
- sclk = 1;
- wait();
- sclk = 0;
- }
- // a small delay fxn to ensure the line settles down after transition
- void wait()
- {
- //char i;
- //for(i=0;i<=20;i++)
- //i++;
- }
- void noacknowledge()
- {
- sda = 1;
- sclk = 1;
- wait();
- sclk = 0;
- }
- void main()
- {
- unsigned char i,location = 0x000;
- unsigned char userdata[7] = {'P','Q','R','S','T','U','G'};
- lcdinitialize();
- send_to_mem(location,userdata[0]);
- for( i = 0; i < 7; i++)
- {
- send_to_mem(location+i,userdata[i]);
- Delay(50);
- }
- Delay(150);
- lcddata(get_from_mem(0x000));
- }
- //*********************************************************************
- #include "AT24C04-LCD.h"
- #include <intrins.h>
- void Delay( unsigned int itime)
- {
- int i,j;
- for( i = 0; i < itime ;i++)
- for( j = 0; j < 1275; j++);
- }
- void lcdcmd( unsigned char value )
- {
- lcd_port = value;
- RS = 0; //register select = 0 for command mode
- EN = 1; //latch enable = HIGH
- _nop_();
- EN = 0; //latch enable = LOW
- Delay(10);
- return;
- }
- void lcddata( unsigned char value )
- {
- lcd_port = value;
- RS = 1; //register select = 1 for data register
- EN = 1; //latch enable = HIGH
- _nop_();
- EN = 0; //latch enable = LOW
- Delay(30);
- return;
- }
- void lcdinitialize(void)
- {
- unsigned char l[10] = {0x38,0x0E,0x06,0x01,0x41};
- unsigned char i;
- for(i = 0 ;i <= 3 ; i++)
- lcdcmd(l[i]); //sending basic LCD commands to LCD
- }
- //********************************************************************************
- /*
- AT24C04 LCD HEADER FILE - ROUTINE/FUNCTION DECLARATIONS
- */
- #include <reg51.h>
- #ifndef __LCD_H
- #define __LCD_H
- //SFR names declarations
- sfr lcd_port = 0x90; //address of PORT P1 ,used for data lines to LCD
- sbit EN = P3^4;
- sbit RS = P3^5;
- //sbit RW =
- //ANSI STYLE PROTOTYPE
- void lcddata( unsigned char value);
- void lcdcmd( unsigned char value);
- void Delay( unsigned int itime );
- void lcdinitialize(void);
- #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement