Figure 3. Program Listing /*********************************************************************/ /* Ds1318AN.c program, use on the DS1318 app note board */ /*********************************************************************/ #include /* Prototypes for I/O functions */ #include /* Register declarations for DS5000 */ #include /* needed to define xdata addresses */ /***************************** Defines *******************************/ #define SSEC1 XBYTE[0x0000] #define SSEC2 XBYTE[0x0001] #define SEC0 XBYTE[0x0002] #define SEC1 XBYTE[0x0003] #define SEC2 XBYTE[0x0004] #define SEC3 XBYTE[0x0005] #define AL0 XBYTE[0x0006] #define AL1 XBYTE[0x0007] #define AL2 XBYTE[0x0008] #define AL3 XBYTE[0x0009] #define CTLA XBYTE[0x000A] #define CTLB XBYTE[0x000B] #define STAT XBYTE[0x000C] /************************* bit definitions ***************************/ /************************* Global Variables **************************/ uchar int_flg = 0; /*********************** Function Prototypes *************************/ void init_rtc(); void writebyte(); void readregs(); void disp_clk_regs(); void disp_clk_regs_int(); void bin2date(); unsigned long date2bin(uint, uint, uint, uint, uint, uint); void external0_int(void); void init_rtc() /* ------------ set the time and date ----------------- */ /* Note: NO error checking is done on the user entries! */ { uint yrs, mon, dt, hrs, min, sec; unsigned long y; printf("\nEnter the year (1970-2099): "); scanf("%d", &yrs); printf("Enter the month (1-12): "); scanf("%d", &mon); printf("Enter the date (1-31): "); scanf("%d", &dt); printf("Enter the hour (0-23): "); scanf("%d", &hrs); printf("Enter the minute (0-59): "); scanf("%d", &min); printf("Enter the second (0-59): "); scanf("%d", &sec); CTLA = 0x46; /* disable update transfers */ y = date2bin(yrs, mon, dt, hrs, min, sec); SEC0 = (y & 0xff); SEC1 = ((y >> 8) & 0xff); SEC2 = ((y >> 16) & 0xff); SEC3 = ((y >> 24) & 0xff); CTLA = 0xC6; } void writebyte() /* -------- enter data for one byte --------- */ { int add; uchar dat; printf("\nEnter address (hex): "); scanf("%x", &add); printf("Enter data (hex): "); scanf("%bx", &dat); XBYTE[add] = dat; } void readregs() /* --------- list all of the registers -------- */ { uchar inc; CTLA = 0x46; /* disable update transfers */ printf("\n"); for(inc = 0; inc < 0xd; inc++) { printf("%02bx ", XBYTE[inc]); } CTLA = 0xC6; /* enable transfers, osc, sqw */ } void disp_clk_regs() /* -------------- read time & date using TE as intended ----------------- */ { uchar prv_sec = 99; while(!RI) /* Read & Display Clock Registers */ { if(prv_sec != SEC0) /* display once per second */ { bin2date(); prv_sec = SEC0; } } RI = 0; /* Swallow keypress to exit loop */ } void disp_clk_regs_int() /* ----- display time using irq output ----- */ { CTLA = 0xC6; /* enable update transfers, oscillator, squarewave and PIE */ CTLB = 0xA0; /* PF = 1Hz, SQW = 32kHz */ EX0 = 1; /* enable interrupt 0 */ IT0 = 1; /* edge activated */ PX0 = 0; /* low priority */ EX1 = 0; /* disable interrupt 1 */ EA = 1; /* enable all interrupts */ while(!RI) /* Read & Display Clock Registers */ { while(!int_flg); /* wait for interrupt */ if(int_flg & 0x02) /* only display if the periodic flag caused the interrupt */ { EX0 = EX1 = 0; /* disable interrupts while updating the display */ bin2date(); /* calculate and display time and date */ int_flg = 0; /* for this example, we'll just clear all interrupt sources */ EX0 = EX1 = 1; /* re-enable interrupts */ } } EX0 = 0; /* disable interrupt */ RI = 0; /* Swallow keypress to exit loop */ } /* Note: The following routine could be replaced with the ANSI C ctime function */ void bin2date() /* ------ convert binary time to date format ------ */ { int yrs, mon, day, date, dow, tmp, jday, hrs, min, sec; uchar ssec; unsigned long x, j, n; CTLA = 0x46; /* disable update transfers */ x = SEC3; x <<= 8; x |= SEC2; x <<= 8; x |= SEC1; x <<= 8; x |= SEC0; ssec = SSEC2; CTLA = 0xC6; /* enable transfers, osc, sqw */ j = x / 60; /* whole minutes since 1/1/70 */ sec = x - (60 * j); /* leftover seconds */ n = j / 60; min = j - (60 * n); j = n / 24; hrs = n - (24 * j); j = j + (365 + 366); /* whole days since 1/1/68 */ day = j / ((4 * 365) + 1); tmp = j % ((4 * 365) + 1); if(tmp >= (31 + 29)) /* if past 2/29 */ day++; /* add a leap day */ yrs = (j - day) / 365; /* whole years since 1968 */ jday = j - (yrs * 365) - day; /* days since 1/1 of current year */ if(tmp <= 365 && tmp >= 60) /* if past 2/29 and a leap year then */ jday++; /* add a leap day */ yrs += 1968; /* calculate year */ for(mon = 12; mon > 0; mon--) { switch(mon) { case 1: tmp = 0; break; case 2: tmp = 31; break; case 3: tmp = 59; break; case 4: tmp = 90; break; case 5: tmp = 120; break; case 6: tmp = 151; break; case 7: tmp = 181; break; case 8: tmp = 212; break; case 9: tmp = 243; break; case 10: tmp = 273; break; case 11: tmp = 304; break; case 12: tmp = 334; break; } if((mon > 2) && !(yrs % 4)) /* adjust for leap year */ tmp++; if(jday >= tmp) break; } day = jday - tmp + 1; /* calculate day in month */ dow = (j + 1) % 7 + 1; /* 1 = Sun, 2 = Mon, and so on */ printf("\n%04d/%02d/%02d %d %02d:%02d:", yrs ,mon, day, dow, hrs, min); printf("%02d.%02bu", sec, ssec); } /* ---- convert date to elapsed days in binary ---- */ unsigned long date2bin(uint yrs, uint mon, uint day, uint hrs, uint min, uint sec) { unsigned long x; /* the following is broken down for clarity */ x = 365 * (yrs - 1970); /* calculate number of days for previous years */ x += (yrs - 1969) >> 2; /* add a day for each leap year */ if((mon > 2) && (yrs % 4 == 0)) /* add a day if current year is leap and past Feb 29th */ x++; switch(mon) { case 1: x += 0; break; case 2: x += 31; break; case 3: x += 59; break; case 4: x += 90; break; case 5: x += 120; break; case 6: x += 151; break; case 7: x += 181; break; case 8: x += 212; break; case 9: x += 243; break; case 10: x += 273; break; case 11: x += 304; break; case 12: x += 334; break; } x += day - 1; /* finally, add the days into the current month */ x = x * 86400; /* and calculate the number of seconds in all those days */ x += ((long) hrs * 3600); /* add the number of seconds in the hours */ x += (min * 60); /* ditto the minutes */ x += sec; /* finally, the seconds */ return(x); } void external0_int(void) interrupt 0 /* --- display time/date on interrupt from RTC --- */ { EX0 = EX1 = 0; /* disable interrupt */ int_flg = STAT; /* clear the interrupt source, save the info */ STAT = 0; /* clear PF (and all other bits) */ EX0 = EX1 = 1; /* re-enable interrupt */ } main (void) /* ----------------------------------------------------- */ { uchar i, M, M1; while (1) { printf("\nDS1318 build %s\n", __DATE__); printf("CI Clock Init CN Clk iNt rd\n"); printf("CR Read Time W Write byte\n"); printf("R Read regs\n"); printf("Enter Menu Selection:"); M = _getkey(); switch(M) { case 'C': case 'c': printf("\rEnter Clock Routine to run: C"); M1 = _getkey(); switch(M1) { case 'I': case 'i': init_rtc(); break; case 'N': case 'n': disp_clk_regs_int(); break; case 'R': case 'r': disp_clk_regs(); break; } break; case 'R': case 'r': readregs(); break; case 'W': case 'w': writebyte(); break; } } }