Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Micro Controller- about external memory interfacing

Status
Not open for further replies.

visva

Member level 3
Joined
Jul 26, 2012
Messages
55
Helped
2
Reputation
4
Reaction score
2
Trophy points
1,288
Activity points
1,633
how to interface the external memory with micro controller( 89c51 ) ? and how can we read and write the data on memory?
 

What kind of memory do you want and how much?

Be specific about your requirement
 

I supose you need serial EEPROM I2C, you can search existing EDABoard threads, there is many discussions about that.
 

thank u for ur replay. i want connect 64kbyte size memory.
 

k thank u i will try it and i have another doubt. how can i use real time(timing) in micro controller.(for example : if i want to write some data at 8 am in external memory. how will i do?)

MOD: USING SMS LANGUAGE / SHORT HAND TYPING IS NOT ALLOWED HERE

READ RULES BEFORE POSTING
 
Last edited by a moderator:

You can use counter or DS1307 realtime clock or any similar.

Of course there is new low cost RTC DS1308:
**broken link removed**




Examples:


Interfacing the DS1307 with an 8051-Compatible Microcontroller
**broken link removed**



Real Time Clock Interfacing (DS1307) with AT89C51
**broken link removed**

RTC.GIF


Code:
/********************************************************************/
/* DEMO1307.c                                                       */
/********************************************************************/
#include <at89x52.h>                /* Prototypes for I/O functions       */
#include <stdio.h>
/***************************** Defines *****************************/
#define        ACK        0
#define        NACK        1
#define        ADDRTC        0xd0        /* I2C slave address */
#define        DS1307        /* compile directive, modify as required */

/************************* bit definitions *************************/
sbit scl = P2^0;               /* I2C pin definitions */
sbit sda = P2^1;
sbit sqw = P3^2;                /* pin function depends upon device */

void        I2C_start();
void        I2C_stop();
void        I2C_write(unsigned char d);
uchar        I2C_read(uchar);
void        readbyte();
void        writebyte();
void        initialize();
void        disp_clk_regs(uchar);
void        burstramwrite(uchar);
void        burstramread();
void        alrm_int();
void        alrm_read();
void        tc_setup();

/* global variables */
uchar        sec, min, hr, dy, dt, mn, yr;
void I2C_start()        /* ----------------------------------------------- */
{
       sda = 1;  scl = 1;        /* Initiate start condition */
       sda = 0;
}
void I2C_stop()                /* ----------------------------------------------- */
{
       sda = 0; sda = 0; sda = 0; sda = 0;        /* Initiate stop condition */
       scl = 1; scl = 1; sda = 1;
}
void I2C_write(uchar d)                /* ----------------------------- */
{
uchar i;

       scl = 0;
       for (i = 1; i <= 8; i++)
       {
               sda = (d >> 7);
               scl = 1;
               d = d << 1;        /* increase scl high time */
               scl = 0;
       }
       sda = 1;        /* Release the sda line */
       scl = 0;
       scl = 1;
       if(sda) printf("Ack bit missing  %02X",(unsigned int)d);
       scl = 0;
}
uchar I2C_read(uchar b)        /* ----------------------------------- */
{
uchar d, i;

       sda = 1;             /* Let go of sda line */
       scl = 0;
       for (i = 1; i <= 8; i++)        /* read the msb first */
       {
               scl = 1;
               d = d << 1;
               d = d | (unsigned char)sda;
               scl = 0;
       }
       sda = b;          /* Hold sda low for acknowledge */

       scl = 0;
       scl = 1;
       if(b == NACK)        sda = 1;        /* sda = 1 if next cycle is reset */
       scl = 0;

       sda = 1;          /* Release the sda line */
       return d;
}
void readbyte()        /* -- read one byte of data from the specified address -- */
{
uchar Add;
       printf("ADDRESS: ");        /* Get Address */
       scanf("%bx", &Add);
       I2C_start();
       I2C_write(ADDRTC);
       I2C_write(Add);
       I2C_start();
       I2C_write(ADDRTC | 1);
       printf("%2bx", I2C_read(NACK) );
       I2C_stop();
}
void writebyte()        /* -- write one byte of data to the specified address -- */
{
uchar Add;
uchar Data;
       printf("Address: ");        /* Get Address */
       scanf("%bx", &Add);
       printf("DATA: ");
       scanf("%bx", &Data);        /* and data */
       I2C_start();
       I2C_write(ADDRTC);
       I2C_write(Add);
       I2C_write(Data);
       I2C_stop();
}
void initialize()        /* -- initialize the time and date using entries from stdin -- */
/* Note: NO error checking is done on the user entries! */
{
uchar        yr, mn, dt, dy, hr, min, sec, day;

       I2C_start();                /* The following Enables the Oscillator */
       I2C_write(ADDRTC);        /* address the part to write */
       I2C_write(0x00);        /* position the address pointer to 0 */
       I2C_write(0x00);        /* write 0 to the seconds register, clear the CH bit */
       I2C_stop();

       printf("Enter the year (0-99): ");
       scanf("%bx", &yr);
       printf("Enter the month (1-12): ");
       scanf("%bx", &mn);
       printf("Enter the date (1-31): ");
       scanf("%bx", &dt);
       printf("Enter the day (1-7): ");
       scanf("%bx", &dy);
       printf("Enter the hour (1-23): ");
       scanf("%bx", &hr);
       hr = hr & 0x3f;        /* force clock to 24 hour mode */
       printf("Enter the minute (0-59): ");
       scanf("%bx", &min);
       printf("Enter the second (0-59): ");
       scanf("%bx", &sec);

       I2C_start();
       I2C_write(ADDRTC);        /* write slave address + write */
       I2C_write(0x00);        /* write register address, 1st clock register */
       I2C_write(sec);
       I2C_write(min);
       I2C_write(hr);
       I2C_write(dy);
       I2C_write(dt);
       I2C_write(mn);
       I2C_write(yr);

#if defined DS1307 || defined DS1338
{
       I2C_write(0x10);        /* enable sqwe, 1Hz output */
}
#elif defined DS1337 || defined DS1339
{
       I2C_start();
       I2C_write(ADDRTC);        /* write slave address + write */
       I2C_write(0x0e);        /* write register address, control register */
       I2C_write(0x20);        /* enable osc, bbsqi */
       I2C_write(0);                /* clear OSF, alarm flags */
                               /* could enable trickle charger here */
}
#elif defined DS1340
{
       I2C_write(0x10);        /* enable sqwe, 1Hz output */
       I2C_start();                /* address pointer wraps at 7, so point to flag register */
       I2C_write(ADDRTC);        /* write slave address + write */
       I2C_write(0x09);        /* write register address, control register */
       I2C_write(0);                /* clear OSF */
}
#endif

       I2C_stop();

}
void        disp_clk_regs(uchar prv_sec)        /* ----------------------------------------- */
{
uchar Sec, Min, Hrs, Dte, Mon, Day, Yr, mil, pm;

       printf("Yr Mn Dt Dy Hr:Mn:Sc");

       while(!RI)        /* Read & Display Clock Registers */
       {
               I2C_start();
               I2C_write(ADDRTC);        /* write slave address + write */
               I2C_write(0x00);        /* write register address, 1st clock register */
               I2C_start();
               I2C_write(ADDRTC | 1);        /* write slave address + read */
               Sec = I2C_read(ACK);        /* starts w/last address stored in register pointer */
               Min = I2C_read(ACK);
               Hrs = I2C_read(ACK);
               Day = I2C_read(ACK);
               Dte = I2C_read(ACK);
               Mon = I2C_read(ACK);
               Yr  = I2C_read(NACK);
               I2C_stop();
               if(Hrs & 0x40)
                       mil = 0;
               else
                       mil = 1;

               if(Sec != prv_sec)        /* display every time seconds change */
               {
                       if(mil)
                       {
                               printf("%02bX/%02bX/%02bX %2bX", Yr, Mon, Dte, Day);
                               printf(" %02bX:%02bX:%02bX", Hrs, Min, Sec);
                       }
                       else
                       {
                               if(Hrs & 0x20)
                                       pm = 'A';
                               else
                                       pm = 'P';
                               Hrs &= 0x1f;        /* strip mode and am/pm bits */
                               printf("%02bx/%02bx/%02bx %02bx", Yr, (Mon & 0x1f), Dte, Day);
                               printf(" %02bx:%02bx:%02bx %cM", Hrs, Min, Sec, pm);
                       }
               }
               if(prv_sec == 0xfe)        return;
               prv_sec = Sec;
       }
       RI = 0;  /* Swallow keypress before exiting */
}
void burstramwrite(uchar Data)        /* -------- fill RAM with data -------- */
{
uchar j;

   I2C_start();
       I2C_write(ADDRTC);        /* write slave address + write */
       I2C_write(0x08);        /* write register address, 1st RAM location */
       for (j = 0; j < 56; j++)        /* write until the pointer wraps around */
       {
               I2C_write(Data);
       }
       I2C_stop();
}
void burstramread()                /* ----------------------------------------- */
{
uchar j;

       I2C_start();
       I2C_write(ADDRTC);        /* write slave address + write */
       I2C_write(8);        /* write register address, 1st RAM location -1*/
       I2C_start();
       I2C_write(ADDRTC | 1);        /* write slave address + read */

       for (j = 0; j < 56; j++)
       {
               if(!(j % 16)) printf("%02bX ", j);
               printf("%02bX ", I2C_read(ACK) );
       }
       I2C_read(NACK);
       I2C_stop();
}
void        alrm_int()        /* ----- initialize alarm registers ------ */
{
uchar        M, Sec, Min, Hr, DyDt;

       printf("1-Alarm each second        2-Alarm match=sec 3-Alarm match=sec+min");
       printf("4-Alarm match=sec+min+hr 5-Alarm match=sec+min+hr+date");
       printf("6-Alarm match=sec+min+hr+day        Enter selection: ");

       M = _getkey();        /* Note-No error checking is done on entries! */

       switch(M)
       {
               case '1':        M = 0xf;        break;
               case '2':        M = 0xe;        break;
               case '3':        M = 0xc;        break;
               case '4':        M = 8;                break;
               case '5':        M = 0;                break;
               case '6':        M = 0x40;        break;
       }
       if(M & 0x40)
       {
               printf("Enter the day (1-7): ");
               scanf("%bx", &DyDt);
       }
       else
       {
               printf("Enter the date (1-31): ");
               scanf("%bx", &DyDt);
       }
       printf("Enter the hour (1-23): ");
       scanf("%bx", &Hr);
       printf("Enter the minute (0-59): ");
       scanf("%bx", &Min);
       printf("Enter the second (0-59): ");
       scanf("%bx", &Sec);

       if( (M & 1) )        Sec |= 0x80;
       if( ((M >> 1) & 1) )        Min |= 0x80;
       if( ((M >> 2) & 1) )        Hr |= 0x80;
       if( ((M >> 3) & 1) )        DyDt |= 0x80;
       if(M & 0x40)        DyDt |= 0x40;

       I2C_start();
       I2C_write(ADDRTC);        /* write slave address + write */
       I2C_write(7);                /* write register address */
       I2C_write(Sec);
       I2C_write(Min);
       I2C_write(Hr);
       I2C_write(DyDt);
       I2C_start();
       I2C_write(ADDRTC);        /* write slave address + write */
       I2C_write(0x0e);        /* write register address */
       I2C_write(5);                /* enable interrupts, alarm 1 */
       I2C_stop();
}
void        alrm_read()        /* ----- read alarm registers ------ */
{
uchar        Sec, Min, Hr, DyDt;

       I2C_start();
       I2C_write(ADDRTC);        /* write slave address + write */
       I2C_write(7);                /* write register address */
       I2C_start();
       I2C_write(ADDRTC | 1);        /* write slave address + read */
       Sec = I2C_read(ACK);
       Min = I2C_read(ACK);
       Hr = I2C_read(ACK);
       DyDt = I2C_read(NACK);

       printf("Alarm 1: %02bx %02bx %02bx %02bx", Sec, Min, Hr, DyDt);
}
void        tc_setup()        /* ---- trickle charger set up routine ---- */
{
uchar        M, val;

#if defined DS1339
       #define        TC 0x10        /* address for DS1339 trickle charge register */
#else
       #define        TC 0x08        /* address for DS1340 trickle charge register */
#endif

       printf("Enable Trickle Charger (Y/N)? ");
       M = _getkey();

       if(M == 'Y' || M == 'y')
       {
               printf("1-250 ohm res2-2K res=sec3-4K res");

               M = _getkey();        /* Note-No error checking is done on entries! */

               switch(M)
               {
                       case '1':        val = 1;        break;
                       case '2':        val = 2;        break;
                       case '3':        val = 3;        break;
               }
               printf("1-no diode2-1 diode");

               M = _getkey();        /* Note-No error checking is done on entries! */

               switch(M)
               {
                       case '1':        val += 4;        break;
                       case '2':        val += 8;        break;
               }
               I2C_start();
               I2C_write(ADDRTC);                /* write slave address + write */
               I2C_write(TC);                /* write register address */
               I2C_write(val | 0xa0);        /* enable trickle charger per user input */
               I2C_stop();
       }
       else
       {
               I2C_start();
               I2C_write(ADDRTC);                /* write slave address + write */
               I2C_write(TC);                /* write register address */
               I2C_write(0);                        /* disable trickle charger */
               I2C_stop();
       }
       I2C_start();
       I2C_write(ADDRTC);                /* write slave address + write */
       I2C_write(TC);                /* write register address */
       I2C_start();
       I2C_write(ADDRTC | 1);        /* write slave address + read */
       printf("Trickle Charger: %02bx", I2C_read(NACK) );
}
main        (void)        /* ----------------------------------------------------- */
{
uchar        M, M1;

       sqw = 1;        /* set up for read, weak pull-up */

       while (1)
       {
#if defined DS1307
               printf("DEMO1307 build %s", __DATE__);
#elif defined DS1337
               printf("DEMO1337 build %s", __DATE__);
#elif defined DS1338
               printf("DEMO1338 build %s", __DATE__);
#elif defined DS1339
               printf("DEMO1339 build %s", __DATE__);
#elif defined DS1340
               printf("DEMO1340 build %s", __DATE__);
#endif

               printf("CI Init RTC    CR Read Clock");
               printf("BR Byte Read   BW Write Byte");

#if defined DS1337 || defined DS1339        /* only print if part has alarms */
               printf("AI Alarm 1 Int AR Alarm Read");
#endif
#if defined DS1340 || defined DS1339        /* parts that have trickle charger */
               printf("Tc Trickle charger");
#endif

#if defined DS1307 || defined DS1338        /* only print if part has RAM */
               printf("RR RAM Read    RW RAM Write");
#endif

               printf("Enter Menu Selection:");

               M = _getkey();

               switch(M)
               {
                       case 'A':
                       case 'a':
                       printf("Init or Read: ");
                       M1 = _getkey();

                       switch(M1)
                       {
                               case 'I':
                               case 'i':        alrm_int();        break;

                               case 'R':
                               case 'r':        alrm_read();        break;
                       }
                       break;

                       case 'B':
                       case 'b':
                       printf("Read or Write: ");
                       M1 = _getkey();

                       switch(M1)
                       {
                               case 'R':
                               case 'r':        readbyte();        break;

                               case 'W':
                               case 'w':        writebyte();        break;
                       }
                       break;

                       case 'C':
                       case 'c':
                       printf("\rEnter Clock Routine to run:C");
                       M1 = _getkey();

                       switch(M1)
                       {
                               case 'I':
                               case 'i':        initialize();        break;

                               case 'R':
                               case 'r':        disp_clk_regs(0x99);        break;
                       }
                       break;

                       case 'R':
                       case 'r':
                       printf("\rEnter Ram Routine to run:R");
                       M1 = _getkey();

                       switch(M1)
                       {
                               case 'R':
                               case 'r':        burstramread();        break;

                               case 'W':
                               case 'w':        printf("Enter the data to write: ");
                                               scanf("%bx", &M1);
                                               burstramwrite(M1);        break;
                       }
                       break;

                       case 'T':
                       case 't':        tc_setup();        break;
               }
       }
}



or

Interfacing 8051 With DS1307
https://www.8051projects.net/i2c-twi-tutorial/8051-DS1307-example.php

ds1307-8051-example.png
 
Last edited:

As per I know 89c51 don't have any internal I2C interface block so to start with one need to write Soft I2C code for communication with about device both real time clock and EPROM .....Also please do not forget the pull -up as I2C interface requires the PULL-UP resistors ....

Good Luck
 

that is correct.. you have to use soft I2C i.e. Bit Banging technique to run I2C protocol on your 89c51. Just search on net and you can have a sample code...
Also, like milind said.. don't forget pull-up resistors and that too depending upon strong pull up or weak pull up needed. Go thru data sheet of the Memory element and RTC you will have everything figured out.. :)
 

Thread: How to use I2C on AT89C51?
https://www.edaboard.com/threads/43804/

How to Interface Serial EEPROM 24C02 with 8051 microcontroller (AT89C51)


**broken link removed**

Code:
//Program to interface Serial EEPROM AT24C02 with 8051 microcontroller (AT89C51) 
#include<reg51.h>
#include<intrins.h>   //For using [_nop_()]
sbit sda=P1^0;
sbit scl=P1^1;
sbit led=P0^3;
bit ack;
sbit led1=P0^1;
sfr lcd_data_pin=0xA0;//p2 port
sfr output=0x80;//p0 port
sbit rs=P3^0;
sbit rw=P3^1;
sbit en=P3^6;
unsigned char reead,write,write2,i,j;
unsigned int temp;
void delay(unsigned int count)
{
	int i,j;
	for(i=0;i<count;i++)
		for(j=0;j<1275;j++);
}
void lcd_command(unsigned char comm)
{
	lcd_data_pin=comm;
	en=1;
	rs=0;
	rw=0;
	delay(1);
	en=0;
}
void lcd_data(unsigned char disp)
{
	lcd_data_pin=disp;
	en=1;
	rs=1;
	rw=0;
	delay(1);
	en=0;
}
lcd_dataa(unsigned char *disp)
{
	int x;
	for(x=0;disp[x]!=0;x++)
	{
		lcd_data(disp[x]);
	}
}
void lcd_ini()
{
	lcd_command(0x38);		  // for using 8-bit 2 row LCD 
	delay(5);
	lcd_command(0x0F);        // for display on, cursor blinking
	delay(5);
	lcd_command(0x80);
	delay(5);
}
void aknowledge()	  //acknowledge condition
{
	scl=1;
	_nop_();
	_nop_();
	scl=0;
} 
void start()		//start condition
{
	sda=1;
	scl=1;
	_nop_();         //No operation
	_nop_();
	sda=0;
	scl=0;
}
void stop()			//stop condition
{
	sda=0;
	scl=1;
	_nop_();
	_nop_(); 
	sda=1;
	scl=0;
}
void send_byte(unsigned char value)	//send byte serially
{ 
	unsigned int i;
	unsigned char send;
	send=value;
	for(i=0;i<8;i++)
	{
		sda=send/128;			//extracting MSB
		send=send<<1;			//shiftng left
		scl=1;
		_nop_();
		_nop_();
		scl=0;
	}
   ack=sda;					//reading acknowledge
   sda=0;
}
unsigned char read_byte()			//reading from EEPROM serially
{
	unsigned int i;
	sda=1;
	reead=0;
	for(i=0;i<8;i++)
	{
		reead=reead<<1;
		scl=1;
		_nop_();
		_nop_();
		if(sda==1)
			reead++;
		scl=0;
	}
	sda=0;
	return reead;				//Returns 8 bit data here
}		
void save()					//save in EEPROM
{
	start();
	send_byte(0xA0);						//device address
	aknowledge();
	send_byte(0x00);						//word address
	aknowledge();
	send_byte(5);							//send data
	aknowledge();
	send_byte(65);
	aknowledge();
	stop();							   
	if(ack==0)
	{
		led1=1;
		delay(100);
		led1=0;
		delay(100);
		lcd_command(0x86);
		lcd_data('5');
		lcd_command(0x87);
		lcd_data('A');
	}
	else
		led1=1;
	aknowledge();
}
void Read()
{
	start();
	send_byte(0xA0);
	aknowledge();
	send_byte(0x00);
	aknowledge();
	start();
	send_byte(0xA1);					 //device address
	aknowledge();
	i=read_byte();
	aknowledge();
	j=read_byte();
	aknowledge();
	stop();
	if(i==5)
	{
		led=0;
		delay(100);
		led=1;
		delay(100);
		write=i+48;
		lcd_command(0xC6);
		lcd_data(write);	
	}
	else
	 led=1;
	if(j==65)
	{
		lcd_command(0xC7);
		lcd_data(j);
	}
	aknowledge();
}

void main()
{
	lcd_ini();
	lcd_dataa("Sent :");
	lcd_command(0xC0);
	lcd_dataa("Read :");
	temp=0;
	while(1)
	{
		save();
		Read();
	}
}
 

RTCs tend to be very sensitive to quality of components, layout and temperature. Even being a few seconds per day out can build up to 30 or 40 minutes error over a year. In many cases this is not critical as operators can fix errors when maintaining equipment or the system can update time via internet if connected. If high accuracy is required over extended periods of time an alternative (at cost) is to use something like a DS3234
**broken link removed**
 

DS3234 - Price 10USD in 1-24 pieces range 1,9USD if more then 50,000 pieces. :-?
we only built 700 or 800 systems and used a low cost RTC. They were in stock for 3 months and on checking we found errors between 5 and 30 minutes. In the end we had to calibrate each one individually. It would have saved time and cost to use a DS3234.
 

which book is good for study embedded c ? (i need to study quick)

- - - Updated - - -

which book is good for study embedded c ? (i need to study quick)
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top