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.

Problem regarding DS1307 RTC using with I2C in 89c51 for generating clock (SCL)

Status
Not open for further replies.

jay_3189

Banned
Joined
Sep 19, 2013
Messages
104
Helped
0
Reputation
0
Reaction score
0
Trophy points
16
Location
Ahmedabad
Activity points
0
I am using DS1307 and 89C51 controller. here I am trying to display time in hyper terminal.
I have read datasheet of DS1307 and there I found that 100kHz is standard clock rate for using I2c and DS1307. so, its mean I have to give only specific clock with delay or I can give any delay.
please check my below I2C code. is that work better or not.

Code:
/*-------------------------------------------------------------
					I2C
--------------------------------------------------------------*/
/*This function is used to generate a clock pulse on SCL line.*/
void I2C_Clock(void)
{
	delay_us(5); 
	SCL = 1;	// Wait for Some time and Pull the SCL line High
	delay_us(5);	// Wait for Some time
	SCL = 0;	// Pull back the SCL line low to Generate a clock pulse
}

/*This function is used to generate I2C Start Condition. 
Start Condition: SDA goes low when SCL is High.*/  
void I2C_Start()
{
	SCL = 0;	// Pull SCL low
	SDA = 1;	// Pull SDA High
	delay_us(1);
	SCL = 1;	//Pull SCL high
	delay_us(1);
	SDA = 0;	//Now Pull SDA LOW, to generate the Start Condition
	delay_us(1);
	SCL = 0;	//Finally Clear the SCL to complete the cycle
}

/*Stop Condition: SDA goes High when SCL is High.
SCL  __-----------
SDA  ______------*/
void I2C_Stop(void)
{
	SCL = 0;	// Pull SCL low	
	delay_us(1);		
	SDA = 0;	// Pull SDA  low	
	delay_us(1);		
	SCL = 1;	// Pull SCL High	
	delay_us(1);		
	SDA = 1;	// Now Pull SDA High, to generate the Stop Condition
}		

/*This function is used to send a byte on SDA line using I2C protocol 
8bit data is sent bit-by-bit on each clock cycle. MSB(bit) is sent first and LSB(bit) is sent at last.
Data is sent when SCL is low.*/		
void I2C_Write(unsigned char dat)
{
	unsigned char i;
	for(i=0;i<8;i++)	// loop 8 times to send 1-byte of data
	{
	 	SDA = dat & 0x80;	// Send Bit by Bit on SDA line
		I2C_Clock();	// Generate Clock at SCL
		dat = dat<<1;
	}
	SDA = 1;	// Set SDA at last
}


/*This fun is used to receive a byte on SDA line using I2C protocol.
8bit data is received bit-by-bit each clock and finally packed into Byte.
MSB(bit) is received first and LSB(bit) is received at last.*/

unsigned char I2C_Read(void)
{
	unsigned char i, dat=0x00;
	SDA=1;	//Make SDA as I/P
	for(i=0;i<8;i++)		// loop 8times to read 1-byte of data
	{
		delay_us(1);
		SCL = 1;			// Pull SCL High
		delay_us(1);
		dat = dat<<1;		//dat is Shifted each time and
		dat = dat | SDA;	//ORed with the received bit to pack into byte
		SCL = 0;			// Clear SCL to complete the Clock
	}
	return dat;		// Finally return the received Byte*
}

/*This function is used to generate a the Positive ACK 
pulse on SDA after receiving a byte.*/
void I2C_Ack()
{
	SDA = 0; 		//Pull SDA low to indicate Positive ACK 
	I2C_Clock(); 	//Generate the Clock
	SDA = 1;		// Pull SDA back to High(IDLE state)
}

/*This function is used to generate a the Negative/NO ACK 
pulse on SDA after receiving all bytes.*/
void I2C_NoAck()
{
	SDA = 1;		//Pull SDA high to indicate Negative/NO ACK
	I2C_Clock();	// Generate the Clock
	SCL = 1;		// Set SCL 
}

At this time I am not getting tome accurate.
 

Hello,
The above code looks fine. Where is the main file? How are you sending commands to the device? There is no issue with the clock rate. Even you can read the device at 10Kb/s rate.

Enjoy!!!
 

you have to give acurate duration of high pulse and low pulses of clock and also for data.if u are using keil u can use _nop_(); for 1us delay.
 

Hello,
The above code looks fine. Where is the main file? How are you sending commands to the device? There is no issue with the clock rate. Even you can read the device at 10Kb/s rate.

Enjoy!!!

Code:
#include <stdio.h> 
#include<reg51.h> 
void DS1307_Init();
void DS1307_SetTime(unsigned char hh, unsigned char mm, unsigned char ss);
void DS1307_SetDate(unsigned char DD, unsigned char MM, unsigned char YY);
void DS1307_GetTime(unsigned char *h_ptr,unsigned char *m_ptr,unsigned char *s_ptr);
void DS1307_GetDate(unsigned char *D_ptr,unsigned char *M_ptr,unsigned char *Y_ptr);
void DS1307_Write(unsigned char dat);
unsigned char DS1307_Read();

void I2C_Clock(void);
void I2C_Start();
void I2C_Stop(void);
void I2C_Write(unsigned char dat);
unsigned char I2C_Read(void);
void I2C_Ack();
void I2C_NoAck();
void delay_us(unsigned int us_count);
//void delay_ms(unsigned int ms_count);
//void delay_sec(unsigned char sec_count);

void serial_init(void);

int dec_to_bcd(int dec);
int bcd_to_dec(int bcd);

sbit SCL=P2^4; //SCL Connected to P2.4 
sbit SDA=P2^5; //SDA Connected to P2.5

#define DS1307_ID 0xD0		// DS1307 ID
#define SEC_ADDRESS	0x00	// Address to access Ds1307 SEC register
#define DATE_ADDRESS 0x04	// Address to access Ds1307 DATE register
#define CONTROL 0x07		// Address to access Ds1307 CONTROL register

void main(void)
{
	
		DS1307_Init();
	  	 DS1307_SetTime(10, 55, 15);
		DS1307_SetDate(12, 11, 13);
		serial_init();
		while(1)
	   	{
				DS1307_GetTime(0x02, 0x01, 0x00);//Address to access Hour,Min,Sec 
			  	DS1307_GetDate(0x04, 0x05, 0x06);//Address to access Date,Month,Year  
				delay_us(5000);
	   	}
}

/*-------------------------------------------------------------
					DS1307 RTC
--------------------------------------------------------------*/
/*This function is used to initialize the Ds1307 RTC.
Ds1307 ic is enabled by sending the DS1307 id on the I2C bus. 
After selecting DS1307, write 0x00 into Control register of Ds1307*/
void DS1307_Init()
{
	I2C_Start();	// Start I2C communication
	DS1307_Write(DS1307_ID); // Connect to DS1307 by sending its ID on I2c Bus 
	DS1307_Write(CONTROL); // Select the Ds1307 ControlRegister to configure Ds1307
	DS1307_Write(0x00);	// Write 0x00 to Control register to disable SQW-Out
	I2C_Stop();	// Stop I2C communication after initilizing DS1307
}

/*This function is used to set Time(hh,mm,ss) into the Ds1307 RTC.
Ds1307 ic is enabled by sending the DS1307 id on the I2C bus.	  
After selecting DS1307, select the RAM address 0x00 to point to sec Initilze Sec, MIN, Hour one after the other.
Stop the I2c communication.*/
void DS1307_SetTime(unsigned char hh, unsigned char mm, unsigned char ss)
{
	I2C_Start();	// Start I2C communication
	DS1307_Write(DS1307_ID); // connect to DS1307 by sending its ID on I2c Bus 
	DS1307_Write(SEC_ADDRESS); // Select the SEC RAM address

	ss = dec_to_bcd(ss);
	mm = dec_to_bcd(mm);
	hh = dec_to_bcd(hh);
	
   	DS1307_Write(ss);	// Write sec on RAM address	00H
	DS1307_Write(mm);	// Write min on RAM address	01H
	DS1307_Write(hh);	// Write hour on RAM address 02H
	I2C_Stop();	// Stop I2C communication after Setting the Time
}

/*This function is used to set Date(dd,mm,yy) into the Ds1307 RTC.
Ds1307 ic is enabled by sending the DS1307 id on the I2C bus. 
After selecting DS1307, select the RAM address 0x04 to point to day Initilze Day,Month and Year one after the other.
Stop the I2c communication.*/ 
void DS1307_SetDate(unsigned char DD, unsigned char MM, unsigned char YY)
{
	I2C_Start();	// Start I2C communication
	DS1307_Write(DS1307_ID); // connect to DS1307 by sending its ID on I2c Bus 
	DS1307_Write(DATE_ADDRESS); // Request DAY RAM address at 04H

	DD = dec_to_bcd(DD);
	MM = dec_to_bcd(MM);
	YY = dec_to_bcd(YY);
	

	DS1307_Write(DD);	// Write date on RAM address	04H
	DS1307_Write(MM);	// Write month on RAM address 05H
	DS1307_Write(YY);	// Write year on RAM address	06h
	I2C_Stop();	// Stop I2C communication after Setting the Date
}

/*This function is used to get the Time(hh,mm,ss) from Ds1307 RTC. 
Ds1307 ic is enabled by sending the DS1307 id on the I2C bus. 
After selecting DS1307, select the RAM address 0x00 to point to sec Get Sec, MIN, Hour one after the other.
Stop the I2c communication.*/
void DS1307_GetTime(unsigned char *h_ptr,unsigned char *m_ptr,unsigned char *s_ptr)
{
	I2C_Start();	// Start I2C communication			
	DS1307_Write(DS1307_ID);	// connect to DS1307 by sending its ID on I2c Bus
	DS1307_Write(SEC_ADDRESS);	// Request Sec RAM address at 00H	
	I2C_Stop();	// Stop I2C communication after selecting Sec Register

	I2C_Start();	// Start I2C communication
	DS1307_Write(0xD1);	// connect to DS1307( under Read mode) by sending its ID on I2c Bus	 
	  
*s_ptr = DS1307_Read();  I2C_Ack();	// read second and return Positive ACK 
*m_ptr = DS1307_Read();  I2C_Ack();	// read minute and return Positive ACK
*h_ptr = DS1307_Read();  I2C_NoAck();   // read hour and return Negative/No ACK

*s_ptr = bcd_to_dec(*s_ptr);
*m_ptr = bcd_to_dec(*m_ptr);
*h_ptr = bcd_to_dec(*h_ptr);
 
printf("Time is in ss:mm:hh =  %p:%p:%p\n", *s_ptr, *m_ptr, *h_ptr);

I2C_Stop();	// Stop I2C communication after reading the Time   
}


/*This function is used to get the Date(y,m,d) from Ds1307 RTC.
Ds1307 ic is enabled by sending the DS1307 id on the I2C bus.
After selecting DS1307, select the RAM address 0x00 to point to DAY Get Day, Month, Year one after the other.
Stop the I2c communication*/
void DS1307_GetDate(unsigned char *D_ptr,unsigned char *M_ptr,unsigned char *Y_ptr)
{
	I2C_Start();	// Start I2C communication
	DS1307_Write(DS1307_ID); // connect to DS1307 by sending its ID on I2c Bus 
	DS1307_Write(DATE_ADDRESS); // Request DAY RAM address at 04H
	I2C_Stop();	// Stop I2C communication after selecting DAY Register

	I2C_Start();	// Start I2C communication
	DS1307_Write(0xD1);	// connect to DS1307( under Read mode) by sending its ID on I2c Bus

*D_ptr = DS1307_Read(); I2C_Ack();	// read Day and return Positive ACK
*M_ptr = DS1307_Read(); I2C_Ack();	// read Month and return Positive ACK
*Y_ptr = DS1307_Read(); I2C_NoAck();   // read Year and return Negative/No ACK

*D_ptr = bcd_to_dec(*D_ptr);
*M_ptr = bcd_to_dec(*M_ptr);
*Y_ptr = bcd_to_dec(*Y_ptr);

printf("Date is in dd/mm/yy =  %p/%p/%p\n", *D_ptr, *M_ptr, *Y_ptr);

I2C_Stop();	// Stop I2C communication after reading the Time  
}

/*This function is used to write a byte of data into Ds1307 RTC. 
This function calls I2C_write function to perform the same*/
void DS1307_Write(unsigned char dat)
{
	I2C_Write(dat); // Connect to DS1307 by sending its ID on I2c Bus 
	I2C_Clock();
}

/*This function is used to read a byte of data from Ds1307 RTC.
This function calls I2C_Read function to perform the same*/
unsigned char DS1307_Read()
{
	unsigned char dat;
	dat = I2C_Read(); // Connect to DS1307 by sending its ID on I2c Bus 
	return(dat);
}



/*-------------------------------------------------------------
					I2C
--------------------------------------------------------------*/
/*This function is used to generate a clock pulse on SCL line.*/
void I2C_Clock(void)
{
	delay_us(1); 
	SCL = 1;	// Wait for Some time and Pull the SCL line High
	delay_us(1);	// Wait for Some time
	SCL = 0;	// Pull back the SCL line low to Generate a clock pulse
}

/*This function is used to generate I2C Start Condition. 
Start Condition: SDA goes low when SCL is High.*/  
void I2C_Start()
{
	SCL = 0;	// Pull SCL low
	SDA = 1;	// Pull SDA High
	delay_us(1);
	SCL = 1;	//Pull SCL high
	delay_us(1);
	SDA = 0;	//Now Pull SDA LOW, to generate the Start Condition
	delay_us(1);
	SCL = 0;	//Finally Clear the SCL to complete the cycle
}

/*Stop Condition: SDA goes High when SCL is High.
SCL  __-----------
SDA  ______------*/
void I2C_Stop(void)
{
	SCL = 0;	// Pull SCL low	
	delay_us(1);		
	SDA = 0;	// Pull SDA  low	
	delay_us(1);		
	SCL = 1;	// Pull SCL High	
	delay_us(1);		
	SDA = 1;	// Now Pull SDA High, to generate the Stop Condition
}		

/*This function is used to send a byte on SDA line using I2C protocol 
8bit data is sent bit-by-bit on each clock cycle. MSB(bit) is sent first and LSB(bit) is sent at last.
Data is sent when SCL is low.*/		
void I2C_Write(unsigned char dat)
{
	unsigned char i;
	for(i=0;i<8;i++)	// loop 8 times to send 1-byte of data
	{
	 	SDA = dat & 0x80;	// Send Bit by Bit on SDA line
		I2C_Clock();	// Generate Clock at SCL
		dat = dat<<1;
	}
	SDA = 1;	// Set SDA at last
}


/*This fun is used to receive a byte on SDA line using I2C protocol.
8bit data is received bit-by-bit each clock and finally packed into Byte.
MSB(bit) is received first and LSB(bit) is received at last.*/

unsigned char I2C_Read(void)
{
	unsigned char i, dat=0x00;
	SDA=1;	//Make SDA as I/P
	for(i=0;i<8;i++)		// loop 8times to read 1-byte of data
	{
		delay_us(1);
		SCL = 1;			// Pull SCL High
		delay_us(1);
		dat = dat<<1;		//dat is Shifted each time and
		dat = dat | SDA;	//ORed with the received bit to pack into byte
		SCL = 0;			// Clear SCL to complete the Clock
	}
	return dat;		// Finally return the received Byte*
}

/*This function is used to generate a the Positive ACK 
pulse on SDA after receiving a byte.*/
void I2C_Ack()
{
	SDA = 0; 		//Pull SDA low to indicate Positive ACK 
	I2C_Clock(); 	//Generate the Clock
	SDA = 1;		// Pull SDA back to High(IDLE state)
}

/*This function is used to generate a the Negative/NO ACK 
pulse on SDA after receiving all bytes.*/
void I2C_NoAck()
{
	SDA = 1;		//Pull SDA high to indicate Negative/NO ACK
	I2C_Clock();	// Generate the Clock
	SCL = 1;		// Set SCL 
}


/*-------------------------------------------------------------
					Delay
--------------------------------------------------------------*/
/*It genarates a approximate delay of 10us for each count,
if 5000 is passed as the argument then it generates a delay of apprx 50ms.*/
void delay_us(unsigned int us_count)
{
	while(us_count!=0)
	{
		us_count--;
	}
}

/*It genarates a approximate delay of 1ms for each count, 
if 1000 is passed as the argument then it generates delay of apprx 1000ms(1sec)*/
/*void delay_ms(unsigned int ms_count)
{
	while(ms_count!=0)
	{
		delay_us(112);   //delay_us is called to generate 1ms delay
		ms_count--;
	}	
}
 */
/*It genarates a approximate delay of 1sec for each count,
if 10 is passed as the argument then it generates delay of apprx 10sec
note: A max of 255 sec delay can be generated using this function.*/
/*void delay_sec(unsigned char sec_count)
{
	while(sec_count!=0)
	{
		delay_ms(1000); //delay_ms is called to generate 1sec delay 
		sec_count--;
	}
}  */

//-------------------------------------------------
//Setup the serial port for 9600 baud at 11.0592MHz.
//-------------------------------------------------
void serial_init(void)
{
    SCON  = 0x50;               /* SCON: mode 1, 8-bit UART, enable rcvr         */
    TMOD |= 0x20;               /* TMOD: timer 1, mode 2, 8-bit reload           */
    TH1   = 0xFD;               /* TH1:  reload value for 9600 baud @ 11.0592MHz */
    TR1   = 1;                  /* TR1:  timer 1 run                             */
    TI    = 1;                  /* TI:   set TI to send first char of UART       */
}

 /*Decimal to BCD and Viceversa	*/
int dec_to_bcd(unsigned int dec)
	{
  		return ((dec/10)<<4) + (dec%10);
	}

int bcd_to_dec(unsigned int bcd)
	{
  		return ((bcd>>4)*10) + (bcd%16);
	}

- - - Updated - - -

you have to give acurate duration of high pulse and low pulses of clock and also for data.if u are using keil u can use _nop_(); for 1us delay.

is delay_us() default function of C like _nop_()?
 

which compiler u are using?
if u are using keil then there is no any delay function like delay_us(); and for use of _nop_(); u have to include #include <intrins.h> file.

- - - Updated - - -

_nop_(); this will take 1 microsecond to run.
 

which compiler u are using?
if u are using keil then there is no any delay function like delay_us(); and for use of _nop_(); u have to include #include <intrins.h> file.

- - - Updated - - -

_nop_(); this will take 1 microsecond to run.


ok
I am using keil microvision 4
and please will you tell me that how could I see all library function?
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top