| ??? 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 |
| Topic | Author | Date |
| 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 |



