/* Program DS1307_1.C (Flashlite V25) ** ** Illustrates an interface with the Dallas DS1307 Real Time Clock. ** ** Writes a time and date to the DS1307 and then continually reads and ** displays on the terminal. ** ** Note that the date and time data is stored in BCD format. ** ** FLASHLIGHT V25 DS1307 ** ** P2.1 ------------------------ SCL ----- To Other ** P2.0 ------------------------ SDA ----- I2C Devices ** ** ** copyright, Peter H. Anderson, Onya Barnes. Baltimore, MD, Oct, '00 */ #include<stdio.h> #include<dos.h> #define SEG 0xf000 #define P2_OFFSET 0xff10 #define PM2_OFFSET 0xff11 #define PMC2_OFFSET 0xff12 /* #define D */ typedef unsigned char byte; struct Time { byte hr; byte mi; byte se; }; struct Date { byte yr; byte mo; byte da; byte weekday; }; /*routines used for DS1307*/ void set_up_clock(byte control_reg); void write_clock(struct Time *p_t, struct Date *p_d); void read_clock(struct Time *p_t, struct Date *p_d); /*common I2C routines*/ byte i2c_in_byte(void); void i2c_out_byte(byte o_byte); void i2c_nack(void); void i2c_ack(void); void i2c_start(void); void i2c_stop(void); void i2c_high_sda(void); void i2c_low_sda(void); void i2c_high_scl(void); void i2c_low_scl(void); /* note global */ byte far *p2, far *pm2,far *pmc2; byte dirs2, outs2; void main(void) { struct Time t_base={0x23, 0x59, 0x00}, t; struct Date d_base={0x99, 0x02, 0x28, 0x07}, d; p2=MK_FP(SEG, P2_OFFSET); pm2=MK_FP(SEG, PM2_OFFSET); pmc2=MK_FP(SEG, PMC2_OFFSET); /*no special purpose*/ *pmc2=0x00; /* */ dirs2=0xff; *pm2=dirs2; set_up_clock(0x10); write_clock(&t_base, &d_base); while(1) { read_clock(&t, &d); printf("%0.2x/%0.2x/%0.2x, %0.2x:%0.2x:%0.2x\n", d.mo, d.da, d.yr, t.hr, t.mi, t.se); printf("%d\n", d.weekday); delay(1000); } } /*DS1307 Routines*/ void set_up_clock(byte control_reg) { i2c_start(); i2c_out_byte(0xd0); i2c_nack(); i2c_out_byte(0x07); i2c_nack(); i2c_out_byte(control_reg); i2c_nack(); i2c_stop(); } void write_clock(struct Time *p_t, struct Date *p_d) { i2c_start(); i2c_out_byte(0xd0); i2c_nack(); i2c_out_byte(0x00); /* address of first write*/ i2c_nack(); i2c_out_byte(p_t->se); i2c_nack(); i2c_out_byte(p_t->mi); i2c_nack(); i2c_out_byte(p_t->hr); /* 24 hour format - 0x80 for 12 hour time*/ i2c_nack(); i2c_out_byte(p_d->weekday); /* YY TT UUUU*/ i2c_nack(); i2c_out_byte(p_d->da); /* DDD T UUUU*/ i2c_nack(); i2c_out_byte(p_d->mo); /* YY TT UUUU*/ i2c_nack(); i2c_out_byte(p_d->yr); i2c_nack(); i2c_stop(); } void read_clock(struct Time *p_t, struct Date *p_d) { i2c_start(); i2c_out_byte(0xd0); i2c_nack(); i2c_out_byte(0x00); /* begin with seconds*/ i2c_nack(); i2c_stop(); i2c_start(); i2c_out_byte(0xd1); i2c_nack(); p_t->se = i2c_in_byte() & 0x7f; i2c_ack(); p_t->mi = i2c_in_byte(); i2c_ack(); p_t->hr = i2c_in_byte() & 0x3f; i2c_ack(); p_d->weekday = i2c_in_byte() & 0x07; i2c_ack(); p_d->da = i2c_in_byte() & 0x3f; i2c_ack(); p_d->mo = i2c_in_byte() & 0x3f; i2c_ack(); p_d->yr = i2c_in_byte(); i2c_nack(); i2c_stop(); } /* Common I2C Routines*/ byte i2c_in_byte(void) { byte i_byte=0, n; i2c_high_sda(); for (n=0; n<8; n++) { i2c_high_scl(); if (*(p2) & 0x01) { i_byte = (i_byte << 1) | 0x01; /* msbit first */ } else { i_byte = i_byte << 1; } i2c_low_scl(); } return(i_byte); } void i2c_out_byte(byte o_byte) { byte n; for(n=0; n<8; n++) { if(o_byte&0x80) { i2c_high_sda(); } else { i2c_low_sda(); } i2c_high_scl(); i2c_low_scl(); o_byte = o_byte << 1; } i2c_high_sda(); } void i2c_nack(void) { i2c_high_sda(); /*data at one*/ i2c_high_scl(); /*clock pulse*/ i2c_low_scl(); } void i2c_ack(void) { i2c_low_sda(); /*bring data low and clock*/ i2c_high_scl(); i2c_low_scl(); i2c_high_sda(); } void i2c_start(void) { i2c_low_scl(); i2c_high_sda(); i2c_high_scl(); /* bring SDA low while SCL is high*/ i2c_low_sda(); i2c_low_scl(); } void i2c_stop(void) { i2c_low_scl(); i2c_low_sda(); i2c_high_scl(); i2c_high_sda(); /*bring SDA high while SCL is high*/ /*idle is SDA high and SCL high*/ } void i2c_high_sda(void) { dirs2 = dirs2 | 0x01; *pm2 = dirs2; #ifdef D /* used for debugging */ printf("SDA_HIGH %x\n", dirs2); delay(500); #endif } void i2c_low_sda(void) { outs2 = outs2 & (~0x01); /* zero the output pin */ *p2 = outs2; dirs2 = dirs2 & (~0x01); /* and output */ *pm2 = dirs2; #ifdef D printf("SDA_LOW %x\n", dirs2); delay(500); #endif } void i2c_high_scl(void) { dirs2 = dirs2 | 0x02; /* bring SCL to high impedance */ *pm2 = dirs2; #ifdef D printf("SCL_HIGH %x\n", dirs2); delay(500); #endif } void i2c_low_scl(void) { outs2 = outs2 & (~0x02); *p2 = outs2; /* zero the output pin */ dirs2 = dirs2 & (~0x02); /* and output */ *pm2 = dirs2; #ifdef D printf("SCL_LOW %x\n", dirs2); delay(500); #endif }