// ds1302 connecti on #defi ne ds1302_PORT PORTA #defi ne rst 5 #defi ne cl k 6 #defi ne i o 7
#defi ne rst_1() ds1302_PORT |= (1<<rst); #defi ne rst_0() ds1302_PORT &= ~ (1<<rst); #defi ne cl k_1() ds1302_PORT |= (1<<cl k); #defi ne cl k_0() ds1302_PORT &= ~ (1<<cl k); #defi ne i o_1() ds1302_PORT |= (1<<i o); #defi ne i o_0() ds1302_PORT &= ~ (1<<i o);
#defi ne mon 1 #defi ne tue 2 #defi ne wed 3 #defi ne thu 4 #defi ne fri 5 #defi ne sat 6 #defi ne sun 7
#defi ne sec_w 0x80 #defi ne sec_r 0x81 #defi ne mi n_w 0x82 #defi ne mi n_r 0x83 #defi ne hour_w 0x84 #defi ne date_r 0x87 #defi ne month_r 0x89 #defi ne day_r 0x8b #defi ne year_r 0x8d #defi ne date_w 0x86 #defi ne month_w 0x88 #defi ne day_w 0x8a #defi ne year_w 0x8c
#defi ne w_protect 0x8e
// Baud rate setti ng #defi ne BAUD 9600
voi d ds1302_reset(voi d); //ds1302_reset voi d ds1302_i ni t (voi d); //ds1302 i ni t voi d wri te(unsi gned char); unsi gned char read(voi d); voi d ds1302_wri te_byte(unsi gned char,unsi gned char); unsi gned char ds1302_read_byte(unsi gned char);
unsi gned char ds1302_read_byte(unsi gned char w_byte) //read the byte wi th regi ster w_byte { unsi gned char temp; ds1302_reset(); wri te(w_byte); temp = read(); rst_0(); // fi ni sh transmi tti on cl k_0(); return temp; }
voi d ds1302_i ni t(voi d) // sets al l pi ns as output and l ow { DDRA |= (1<<rst) | (1<<cl k) | (1<<i o); cl k_0(); // scl k -> 0 rst_0(); // rst -> 0 i o_0(); // i o -> 0 }
voi d ds1302_reset(voi d) //sets the pi ns to begi n the ds1302 communi cati on { cl k_0(); // scl k -> 0 rst_0(); // rst -> 0 rst_1(); // rst -> 1 }
voi d ds1302_wri te_byte(unsi gned char w_byte, unsi gned char w_2_byte) //wri te the byte wi th regi ster w_byte { ds1302_reset(); wri te(w_byte); wri te(w_2_byte); rst_0(); // fi ni sh transmi tti on cl k_0(); }
voi d wri te(unsi gned char W_Byte) //wri tes the W_Byte to the DS1302 { unsi gned char i ;
DDRA |= (1<<i o); // i o as output -> 1
for(i = 0; i < 8; ++i ) { i o_0();
i f(W_Byte & 0x01) { i o_1(); } cl k_0(); del ay_us(2); cl k_1(); del ay_us(2); W_Byte >>=1; } }
unsi gned char read(voi d) //reads the ds1302 repl y { unsi gned char i , R_Byte, TmpByte;
voi d rtc_i ni t(voi d); voi d rtc_comms(unsi gned char * data, char address, char rw); voi d rtc_get_ti me(struct rtc_ti me *); voi d rtc_set_ti me(struct rtc_ti me *); #endi f
and the code
Code: //////////////////////////////////////////////////////////////////////////////////////////// // // Real ti me cl ock i nterface // // CE -> PA7 // IO -> PA6 // SCLK -> PA5 // // The DS1302 uses three control si gnal s. Al l data transfers occur on the // edge of the scl k l i ne; ei ther data i s read from or wri tten to the i o l i ne. // Data transfers onl y occur when the ce l i ne i s hi gh. // // The procedure i s: // rai se the ce l i ne // send ei ght bi ts whi ch defi ne the address and r ead/wri te pl us enabl e: // // [rw][a0][a1][a2][a3][a4][rc][ 1] // // then ei ther send or recei ve the data i tsel f // // [d0][d1][d2][d3][d4][d5][d6][d7] // // when r/w = 1, the devi ce sends data to the control l er whi ch shoul d be // sampl ed on the *fal l i ng* edge of scl k // // when r/w = 0, the devi ce reads data from the control l er whi ch i s sampl ed // on the *ri si ng* edge of scl k // // after the address and data byte have been sent/recei ved, ce i s dropped agai n. // // burst mode i s avai l abl e but i s not used i n thi s project. // ////////////////////////////////////////////////////////////////////////////////////////////
#i fndef _RTC_ #defi ne _RTC_
#i ncl ude "rtc.h"
#defi ne CE PA7 #defi ne IO PA6 #defi ne SCLK PA5
voi d rtc_i ni t(voi d) { // i ni ti al i se the rtc i nterface // set CE and SCLK as output and set them l ow // set IO i nput hi gh i mpedance no pul l up
DDRA |= _BV(CE); DDRA |= _BV(SCLK); // make CE and SCLK as outputs DDRA &= ~(_BV(IO)); // and IO as i nput
PORTA &= ~(_BV(CE)); PORTA &= ~(_BV(SCLK)); // make CE and SCLK l ow to start
}
voi d rtc_comms(unsi gned char * data, char address, char rw) { // read or wri te a si ngl e byte at address // i f rw = 0, wri te the contents of data // i f rw = 1, read the contents of address to data // the ram/~ck control bi t i s passed as the hi gh bi t of the address
unsi gned char control ; i nt q;
// set up the control byte control = (address<<1) + 0x80 + rw;
// set CE hi gh to mark start of control PORTA |= _BV(CE);
// now spi t out the control byte // ce and scl k are l ow when we get here // but we need to set the di recti on for i o to output DDRA |= _BV(IO);
for (q=0; q<8; q++) { // set the data bi t i f (control & 1) { PORTA |= _BV(IO); } el se { PORTA &= ~(_BV(IO)); }
// dri ve the cl ock hi gh to l atch the bi t PORTA |= _BV(SCLK);
// shi ft the data so the next hi gher bi t i s sent next ti me control >>= 1;
// hopeful l y C codes thi s sl owl y enough to meet the mi ni mum cl ock peri od // of a mi crosecond, even though we' re worki ng at 8MHz // and havi ng l atched, send i t l ow agai n PORTA &= ~(_BV(SCLK)); }
// now we are di fferent for reads and wri tes i f (rw == READ) { // read a byte
// set the data di recti on to i nput DDRA &= ~(_BV(IO));
// cl ear the recei vi ng byte control = 0;
for (q=0; q<8; q++) { // as we fi ni sh the control byte cycl e, the cl ock i s l ow // whi ch means that the data i s avai l abl e to be read // we get data avai l abl e on the fal l i ng edge of the cl ock
// shi ft the data to make space control >>= 1;
i f (PINA & _BV(IO)) { control |= 0x80; } el se { control &= 0x7f; }
// dri ve the cl ock hi gh PORTA |= _BV(SCLK);
// and send i t l ow agai n PORTA &= ~(_BV(SCLK)); }
// and now we have the data, put i t where we need i t *data = control ;
} el se { // wri te a byte
// we conti nue to wri te on the ri si ng edge control = *data; for (q=0; q<8; q++) { // set the data bi t i f (control & 1) { PORTA |= _BV(IO); } el se { PORTA &= ~(_BV(IO)); }
// dri ve the cl ock hi gh to l atch the bi t PORTA |= _BV(SCLK);
// shi ft the data so the next hi gher bi t i s sent next ti me control >>= 1;
// hopeful l y C codes thi s sl owl y enough to meet the mi ni mum cl ock peri od // of a mi crosecond, even though we're worki ng at 8MHz // and havi ng l atched, send i t l ow agai n PORTA &= ~(_BV(SCLK)); } }
// and one l ast thi ng... bri ng CE l ow agai n to mark compl eti on // and make the i o l i ne hi gh i mpedance i nput PORTA &= ~(_BV(CE)); DDRA &= ~(_BV(IO)); PORTA &= ~(_BV(IO));
}
voi d rtc_get_ti me(struct rtc_ti me * ti me) { // get the ti me unsi gned char data;
rtc_comms(&data, 0x00, READ); ti me->second = (data&0x0f) + ((data&0x70)>>4)*10;
rtc_comms(&data, 0x01, READ); ti me->mi nute = (data&0x0f) + ((data&0x70)>>4)*10;
rtc_comms(&data, 0x02, READ); ti me->hour = (data&0x0f) + ((data&0x30)>>4)*10;
rtc_comms(&data, 0x03, READ); ti me->day = (data&0x0f) + ((data&0x30)>>4)*10;
rtc_comms(&data, 0x04, READ); ti me->month = (data&0x0f) + ((data&0x10)>>4)*10;
rtc_comms(&data, 0x05, READ); ti me->year = (data&0x0f) + ((data&0xf0)>>4)*10; } #endi f
//-------------------------------------------------------------------- ---------- // By Mark Koh // date : 20-MAR-2008, 02:26AM // // Objective : To demostrate DS1302 burst Read and burst write // // Code not tested, use at your own risk!! God bless......... //-------------------------------------------------------------------- ----------
#define DS1302_RST_TRIS TRISB.F0 // Modify these code to fix your IO lines #define DS1302_IO_TRIS TRISB.F1 #define DS1302_SCLK_TRIS TRISB.F2
#define DS1302_RST_DATA PORTB.F0 // Modify these code to fix your IO lines #define DS1302_IO_DATA PORTB.F1 #define DS1302_SCLK_DATA PORTB.F2
void main(){ // Place all other init code here DS1302_INIT(); DS1302_CLOCK_READ(); // Process your clock data here, ensure CH flag is LOW, or else DS1302 Clock will halt // Note, I believe at this point, you should able to decode the clock data yourself // So, I will not bore you with unnecessarily data conversion code.. //.. //.. //.. //.. //.. DS1302_CLOCK_WRITE(); // Write data back into DS1302 chip. //.. //.. //.. //.. //.. DS1302_RAM_READ(); // This will read all RAM data from DS1302, you may delete this routine if you are not using it. //.. //.. //.. //.. //.. DS1302_RAM_WRITE(); // This will write back all RAM data from DS1302, you may delete this routine if you are not using it. //.. //.. //.. //.. //..
}
void DS1302_INIT(){ DS1302_RST_TRIS = 0; // Define this pin as output DS1302_IO_TRIS = 1; // Define this pin as input for the start, need to change when Write DS1302_SCLK_TRIS = 0; // Define this pin as output
DS1302_RST_DATA = 0; // Hold DS1302 @ reset mode, int clock still running DS1302_SCLK_DATA = 0; // Sclk always begins at low DS1302_IO_DATA = 0; // Hold IO data line low } //-------------------------------------------------------------------- ---------- // Read all clock data sec, min, hour.......etc into array //-------------------------------------------------------------------- ---------- void DS1302_CLOCK_READ(){ unsigned char cc1,cc2,dat; // cc1 and cc2 are used for counter
DS1302_IO_TRIS = 0; // Change IO line to output DS1302_RST_DATA = 1; // Release reset line and prepare for transfer
dat = 0b10111111; // CLOCK READ BURST COMMAND, <1><R/#C><1><1><1><1><1><R/#W> for(cc1=0;cc1<8;cc1++){ if(dat.F0) DS1302_IO_DATA = 1; else DS1302_IO_DATA = 0; // Output data dat = dat >> 1; // Shift bit one step to the right.
DS1302_SCLK_DATA = 0; // Create a clock pulse, about 2us (freq 500Khz) delay_us(1); DS1302_SCLK_DATA = 1; delay_us(1); DS1302_SCLK_DATA = 0; } //--------------------------------------------------------------- ---------- // After sending command, next is to read all 8 bytes of data //--------------------------------------------------------------- ---------- DS1302_IO_TRIS = 1; // Change IO line to Input, to receive data
for(cc2=0;cc2<8;cc2++){ for(cc1=0;cc1<8;cc1++){ DS1302_SCLK_DATA = 0; // Create a clock pulse, about 2us (freq 500Khz) delay_us(1); DS1302_SCLK_DATA = 1; delay_us(1); //----------------------------------- // Read bit when sclk is high //----------------------------------- if(DS1302_IO_DATA) dat.F0 = 1; else dat.F0 = 0; // input data dat = dat << 1; // shift bit one step to left } DS1302_CLOCK_DATA[cc2] = dat; // store result int array } //--------------------------------------------------------------- ---------- // Whole operation completed, set IO line back to default //--------------------------------------------------------------- ---------- DS1302_SCLK_DATA = 0; DS1302_IO_TRIS = 1; // Change IO line to input DS1302_IO_DATA = 0; // Change IO line to input DS1302_RST_DATA = 0; // Hold reset line, internal clock still running } //-------------------------------------------------------------------- ---------- //-------------------------------------------------------------------- ---------- void DS1302_CLOCK_WRITE(){ unsigned char cc1,cc2,dat; // cc1 and cc2 are used for counter
DS1302_IO_TRIS = 0; // Change IO line to output DS1302_RST_DATA = 1; // Release reset line and prepare for transfer
dat = 0b10111110; // CLOCK WRITE BURST COMMAND, <1><R/#C><1><1><1><1><1><R/#W> for(cc1=0;cc1<8;cc1++){ if(dat.F0) DS1302_IO_DATA = 1; else DS1302_IO_DATA = 0; // Output data dat = dat >> 1; // Shift bit one step to the right.
DS1302_SCLK_DATA = 0; // Create a clock pulse, about 2us (freq 500Khz) delay_us(1); DS1302_SCLK_DATA = 1; delay_us(1); DS1302_SCLK_DATA = 0; } //--------------------------------------------------------------- ---------- // After sending command, next is to write all 8 bytes of data //--------------------------------------------------------------- ---------- for(cc2=0;cc2<8;cc2++){ dat = DS1302_CLOCK_DATA[cc2]; for(cc1=0;cc1<8;cc1++){ if(dat.F0) DS1302_IO_DATA = 1; else DS1302_IO_DATA = 0; // Output data dat = dat >> 1; // Shift bit one step to the right.
DS1302_SCLK_DATA = 0; // Create a clock pulse, about 2us (freq 500Khz) delay_us(1); DS1302_SCLK_DATA = 1; delay_us(1); DS1302_SCLK_DATA = 0; } } //--------------------------------------------------------------- ---------- // Whole operation completed, set IO line back to default //--------------------------------------------------------------- ---------- DS1302_SCLK_DATA = 0; DS1302_IO_TRIS = 1; // Change IO line to input DS1302_IO_DATA = 0; // Change IO line to input DS1302_RST_DATA = 0; // Hold reset line, internal clock still running } //-------------------------------------------------------------------- ---------- //-------------------------------------------------------------------- ----------
void DS1302_RAM_READ(){ unsigned char cc1,cc2,dat; // cc1 and cc2 are used for counter
DS1302_IO_TRIS = 0; // Change IO line to output DS1302_RST_DATA = 1; // Release reset line and prepare for transfer
dat = 0b11111111; // CLOCK READ BURST COMMAND, <1><R/#C><1><1><1><1><1><R/#W> for(cc1=0;cc1<8;cc1++){ if(dat.F0) DS1302_IO_DATA = 1; else DS1302_IO_DATA = 0; // Output data dat = dat >> 1; // Shift bit one step to the right.
DS1302_SCLK_DATA = 0; // Create a clock pulse, about 2us (freq 500Khz) delay_us(1); DS1302_SCLK_DATA = 1; delay_us(1); DS1302_SCLK_DATA = 0; } //--------------------------------------------------------------- ---------- // After sending command, next is to read all 31 bytes of data //--------------------------------------------------------------- ---------- DS1302_IO_TRIS = 1; // Change IO line to Input, to receive data
for(cc2=0;cc2<31;cc2++){ for(cc1=0;cc1<8;cc1++){ DS1302_SCLK_DATA = 0; // Create a clock pulse, about 2us (freq 500Khz) delay_us(1); DS1302_SCLK_DATA = 1; delay_us(1); //----------------------------------- // Read bit when sclk is high //----------------------------------- if(DS1302_IO_DATA) dat.F0 = 1; else dat.F0 = 0; // input data dat = dat << 1; // shift bit one step to left } DS1302_RAM_DATA[cc2] = dat; // store result int array } //--------------------------------------------------------------- ---------- // Whole operation completed, set IO line back to default //--------------------------------------------------------------- ---------- DS1302_SCLK_DATA = 0; DS1302_IO_TRIS = 1; // Change IO line to input DS1302_IO_DATA = 0; // Change IO line to input DS1302_RST_DATA = 0; // Hold reset line, internal clock still running }
void DS1302_RAM_WRITE(){ unsigned char cc1,cc2,dat; // cc1 and cc2 are used for counter
DS1302_IO_TRIS = 0; // Change IO line to output DS1302_RST_DATA = 1; // Release reset line and prepare for transfer
dat = 0b11111110; // CLOCK WRITE BURST COMMAND, <1><R/#C><1><1><1><1><1><R/#W> for(cc1=0;cc1<8;cc1++){ if(dat.F0) DS1302_IO_DATA = 1; else DS1302_IO_DATA = 0; // Output data dat = dat >> 1; // Shift bit one step to the right.
DS1302_SCLK_DATA = 0; // Create a clock pulse, about 2us (freq 500Khz) delay_us(1); DS1302_SCLK_DATA = 1; delay_us(1); DS1302_SCLK_DATA = 0; } //--------------------------------------------------------------- ---------- // After sending command, next is to write all 31 bytes of data //--------------------------------------------------------------- ---------- for(cc2=0;cc2<31;cc2++){ dat = DS1302_RAM_DATA[cc2]; for(cc1=0;cc1<8;cc1++){ if(dat.F0) DS1302_IO_DATA = 1; else DS1302_IO_DATA = 0; // Output data dat = dat >> 1; // Shift bit one step to the right.
DS1302_SCLK_DATA = 0; // Create a clock pulse, about 2us (freq 500Khz) delay_us(1); DS1302_SCLK_DATA = 1; delay_us(1); DS1302_SCLK_DATA = 0; } } //--------------------------------------------------------------- ---------- // Whole operation completed, set IO line back to default //--------------------------------------------------------------- ---------- DS1302_SCLK_DATA = 0; DS1302_IO_TRIS = 1; // Change IO line to input DS1302_IO_DATA = 0; // Change IO line to input DS1302_RST_DATA = 0; // Hold reset line, internal clock still running } //-------------------------------------------------------------------- ---------- //-------------------------------------------------------------------- ----------
Top
markkoh Post subject: Posted: 19 Mar 2008 20:21
Joined: 13 Jan 2006 18:06 Posts: 14 Location: Singapore Need some correction to my code..
For routine DS1302_CLOCK_READ and DS1302_RAM_READ, pls change
Line---> if(DS1302_IO_DATA) dat.F0 = 1; else dat.F0 = 0; // input data dat = dat << 1; // shift bit one step to left
To ---> if(DS1302_IO_DATA) dat.F7 = 1; else dat.F7 = 0; // input data dat = dat >> 1; // shift bit one step to left
Sorry for the error, data are shifted in LSB first.