Email: Password: Remember Me | Create Account (Free)

Back to Subject List

Old thread has been locked -- no new posts accepted in this thread
???
01/16/09 12:12
Read: times


 
#161555 - its working
Responding to: ???'s previous message
Dear all,

Firstly, sorry for the delayed reply. I was off on leave. Now that I am back things are going quiet smoothly.

I found the "bug" in my code. The problems were:
* read() was shifting the MSB out.
* Device READ ADDRESS was incorrect.


I am updating my code for a review.




/* A program demonstrating application of DS1307 as a Real Time Clock */

#include <error_funcs.c> /* this has some basic IO and delay functions */

#define SCL P1_6
#define SDA P1_7
#define DS1307_READ_ADDR  0XD1
#define DS1307_WRITE_ADDR 0XD0
#define HIGH  1
#define LOW   0
#define ACK   LOW
#define NACK  HIGH
#define ERROR LOW
#define SUCCESS HIGH

__sbit __at (0x96) P1_6 ;
__sbit __at (0x97) P1_7 ;


enum time {
	SECONDS, MINUTES, HOURS,
	DAY, DATE, MONTH, YEAR,
	CONTROL
	};
enum day {
	SUN, MON, TUE, WED,
	THU, FRI, SAT
	};
enum month {
	JAN, FEB, MAR, APR,
	MAY, JUN, JUL, AUG,
	SEP, OCT = 0x10,	/* BCD 10 = 0x10 */
	NOV, DEC
	};


typedef struct time_reg {
	unsigned char sec;
	unsigned char min;
	unsigned char hour;
	unsigned char day;
	unsigned char date;
	unsigned char mon;
	unsigned char year;
} time_t;



/* I2C functions */
void start()
{
	/* I2C START condition */
	SCL = SDA = HIGH;
	NOP;
	SDA = LOW;
	NOP;
	SCL = LOW;
}

void stop()
{
	/* I2C STOP condition */
	SDA = LOW;
	SCL = HIGH;
	NOP;
	SDA = HIGH;
	NOP;
	SCL = LOW;
}

unsigned char clock()
{
	/* A subroutine to generate a clock pulse and return the
	 * status of the data bus during the clock period */
	unsigned char status = 0;
	SCL = HIGH;
	NOP;
	while(!SCL);		/* eliminate ripples */
	status = SDA;
	SCL = LOW;
	return (status);
}

unsigned char write(unsigned char byte)
{
	/* I2C WRITE operation, Write a byte on SDA and return the
	 * acknowledgement */
	unsigned char mask = 0x80;
	unsigned char status= ACK;
	
	for ( ; mask > 0 ;  ) {
		SDA = (byte & mask) ? ( SET ):( CLEAR ) ;
		mask >>= 1;
		clock();
	}
	status = clock();
	return (status);	/* return the status of SDA line on
				 * the 9th pulse */
}

unsigned char read(unsigned char status)
{
	/* I2C READ operation, read one byte from the transmitter and
	 * give ack/nack to it */
	unsigned char byte = 0;
	unsigned char count;

	for ( count = 0; count < 8; count++ ) {
		byte <<= 1;	/* 1 */
		byte |= clock(); /* 2 */
/* My mistake was (1) followed (2) so MSB was pushed out during the last iteration and the read values were "NOT BCD but HEX" */
	}
	SDA = status;		/* status = 1 :- NACK
				 * status = 0 :- ACK */
	clock();
	return byte;
}



/* RTC functions */
unsigned char read_rtc(unsigned char addr)
{
	/* Read a byte from RTC */
	unsigned char byte = 0;
	
	start();

	if ( write(DS1307_WRITE_ADDR) == ACK ) {
		if ( write(addr) == ACK) {

			start();

			if ( write(DS1307_READ_ADDR) == ACK ) 
				byte = read(NACK);
			else
				print_on_lcd("write device read address failed!");
		}
		else
			print_on_lcd("Write addr to RTC failed");

	}
	else
		print_on_lcd("RTC is not selected in read()!!!!!");
	
	stop();
	return byte;
}


unsigned char  write_rtc(unsigned char addr, unsigned char byte)
{
	/* Write a byte to RTC */
	unsigned char status = ERROR;
	start();

	if ( write(DS1307_WRITE_ADDR) == ACK ) {
		if ( write( addr ) == ACK ) { 
			if ( write( byte ) == ACK ) 
				status = SUCCESS;			
			else
				print_on_lcd("write byte to RTC failed!!");
		}
		else
			print_on_lcd("write address failed!!");	
	}
	else
		print_on_lcd("device not selected!!");
	
	stop();

	delay_millisec(4);
	
	return status;
}

/* Enable the internal oscillator */
#define init_rtc() 	if ( write_rtc(CONTROL, 0x00) == ACK )	
				print_on_lcd("RTC initiated")


void time( time_t * new, time_t *old)
{
	/* A function to get time/set RTC time. Time is set to values
	 * refered by 'new'(if its not NULL) and the previous values
	 * are read to 'old'  */

	if ( old ) {
	/* read time registers to 'old'*/
		old->sec  = read_rtc(SECONDS);
		old->min  = read_rtc(MINUTES);
		old->hour = read_rtc(HOURS);
		old->day  = read_rtc(DAY);
		old->date = read_rtc(DATE);
		old->mon  = read_rtc(MONTH);
		old->year  = read_rtc(YEAR);
	}
	if ( new != NULL ) {
		/* set timer registers to new values */
		write_rtc(SECONDS, new->sec);
		write_rtc(MINUTES, new->min);
		write_rtc(HOURS,   new->hour);
		write_rtc(DAY,     new->day);
		write_rtc(DATE,    new->date);
		write_rtc(MONTH,   new->mon);
		write_rtc(YEAR,    new->year);
	}
	
}

void show_time()
{
	/* A function to display time on LCD */
	   
	unsigned char format[] = "time = HH:MM:SS dt- DT DA:MON:YE";
	time_t tm;

	time( NULL, &tm);		/* get time */
	/* convert BCD to ASCII */

	format[7]  = (tm.hour >> 4) + '0';
	format[8]  = (tm.hour & 0x0F) + '0';
	format[10] = (tm.min >> 4) + '0';
	format[11] = (tm.min & 0x0F) + '0';
	format[13] = (tm.sec >> 4) + '0';
	format[14] = (tm.sec & 0x0F) + '0';
	/* display AM or PM  */
 	format[15] = (tm.hour & 0x40) ? ( (tm.hour & 0x20)? 'a' :'p' ):(' ');

	
	format[20] = (tm.date >> 4) + '0';
	format[21] = (tm.date & 0x0F) + '0';
	/* get day of the week */
	switch (tm.day) {
	case SUN:
		format[23] = 'S';
		format[24] = 'U';
		break;
	case MON:
		format[23] = 'M';
		format[24] = 'O';
		break;
	case TUE:
		format[23] = 'T';
		format[24] = 'U';
		break;
	case WED:
		format[23] = 'W';
		format[24] = 'E';
		break;
	case THU:
		format[23] = 'T';
		format[24] = 'H';
		break;
	case FRI:
		format[23] = 'F';
		format[24] = 'R';
		break;
	case SAT:
		format[23] = 'S';
		format[24] = 'A';
	}
	/* get month */
	switch (tm.mon) {
	case JAN:
		format[26] = 'J';
		format[27] = 'A';
		format[28] = 'N';
		break;
		
 		
 	case FEB:
		format[26] = 'F';
		format[27] = 'E';
		format[28] = 'B';
		break;

		
 	case MAR:
		format[26] = 'M';
		format[27] = 'A';
		format[28] = 'R';
		break;

		
 	case APR:
		format[26] = 'A';
		format[27] = 'P';
		format[28] = 'R';
		break;

	case MAY:
		format[26] = 'M';
		format[27] = 'A';
		format[28] = 'Y';
		break;

	case JUN:
		format[26] = 'J';
		format[27] = 'U';
		format[28] = 'N';
		break;
		
 	case JUL:
		format[26] = 'J';
		format[27] = 'U';
		format[28] = 'L';
		break;

		
 	case AUG:
		format[26] = 'A';
		format[27] = 'U';
		format[28] = 'G';
		break;

		
 	case SEP:
		format[26] = 'S';
		format[27] = 'E';
		format[28] = 'P';
		break;

		
 	case OCT:
		format[26] = 'O';
		format[27] = 'C';
		format[28] = 'T';
		break;

		
 	case NOV:
		format[26] = 'N';
		format[27] = 'O';
		format[28] = 'V';
		break;

		
 	case DEC:
		format[26] = 'D';
		format[27] = 'E';
		format[28] = 'C';
	}

	format[30] = (tm.year >> 4) + '0';
	format[31] = (tm.year & 0x0F) + '0';

	print_on_lcd(format);
	delay_millisec(200);
}


main()
{
	time_t new =  { 0x17, 0x35, 0x13, THU, 0x15, JAN, 0x09};
	/* date is: "Thu Jan 15 13:35:17 2009" */

	init_lcd();
	init_rtc();

	time( &new, NULL);	/* set time */
	
	while (1) 
		show_time();	/* keep showing time */
}


 



your comments and reviews are welcome.
thank you for your suggestions, time and intrest.

Best regards,
Sarma


List of 18 messages in thread
TopicAuthorDate
DS1307 Memory Read and Write            01/01/70 00:00      
   Know your code?            01/01/70 00:00      
   Another thing to consider...            01/01/70 00:00      
   Pinnacle 52            01/01/70 00:00      
   The RAM is same as ordinary registers.            01/01/70 00:00      
   Debugging Strategy            01/01/70 00:00      
      Debugging Strategy for DS1307 memory Reading            01/01/70 00:00      
         next step            01/01/70 00:00      
         Be more specific.            01/01/70 00:00      
            a minor correction            01/01/70 00:00      
               Which i2c device?            01/01/70 00:00      
                  another small correction            01/01/70 00:00      
                     SMBus            01/01/70 00:00      
                     Which REAL i2c device            01/01/70 00:00      
                        apples and oranges            01/01/70 00:00      
                           Sorry Erik            01/01/70 00:00      
                              as I recall            01/01/70 00:00      
                                 its working            01/01/70 00:00      

Back to Subject List