📄 ds1302.c
字号:
/********************************************************************文件名:ds1302.c *功能:给cpu提供实时时钟*完成日期:2004.7.18*This file handles the Dallas DS1302 Real Time Clock.*On the SUMSUNG 4510B, the DS1302 requires three port*pins, designated as follows...*DATA GPIO P1口*CLOCK GPIO P2口 *RESET* GPIO P3口********************************************************************/#include "ds1302.h"#include <stdio.h>#define WORD unsigned int#define BYTE unsigned charint DS1302IN(int ds1302_bit){ int x; iopmod[0]=iopmod[0]&(~ds1302_bit); x=iopdata[0]&ds1302_bit; if(x==0) return 0; else return 1;}//local storageTIME_STRUCT ds_1302_time;/* 拷贝系统时间 *///writevoid DS1302(unsigned char ds1302_bit,unsigned int logical_value) { iopmod[0]=iopmod[0]|ds1302_bit; if (!logical_value) iopdata[0]=iopdata[0]&(~ds1302_bit); else iopdata[0]=iopdata[0]|ds1302_bit; }/********************************************************************Setup_1302_Port*Initialize Port Pins to access DS1302 Clock.*Note that all three pins are defined initialliy as outputs.*When you want to read a port pin, you have to turn it*around. S3C4510B P1 = DATA P2 = CLOCK P3 = RST*********************************************************************/void Setup_1302_Port(void) { iopmod[0]=0x000000ff; Idle_1302(); /* set the port pins idle */ return; } //end proc Setup_1302_Port()/********************************************************************Read_1302_Data*Reads all 8 bytes of data from the DS1302.*Inputs: TimeBuffer- Pointer to 8 byte unsigned char array where data* will be placed once read from the clock*Returns in TimeBuffer:*TimeBuffer[0] seconds: msb=1, clock hold, BCD seconds*TimeBuffer[1] minutes: 0,BCD minutes*TimeBuffer[2] hours: msb=1,12 hour/0,24 hour, BCD hour* msb=0, 0-23 BCD* msb=1, {10}{0=am/1=pm}01-12 BCD*TimeBuffer[3] day of month: BCD day 0-31*TimeBuffer[4] month: BCD 1-12*TimeBuffer[5] day of week: BCD 1-7 1=Sunday*TimeBuffer[6] year: BCD 00-99*TimeBuffer[7] write protect: msb=1, write protect* msb=0, write en*returns: 0 if all is well, non-zero if clock was stopped*NOTE: If clock was stopped, returns non-zero and time is* indicated as Jan 1, 1999, 12:00:00 Noon********************************************************************/unsigned int Read_1302_Data(unsigned char * TimeBuffer) { unsigned char Cmd_Byte; /*clock command*/ unsigned char databyte; /*temp data byte*/ unsigned char shifter; /* bit selector */ unsigned int i,j; unsigned char c; DS1302(CLK_1302,LOW); DS1302(DAT_1302,LOW); DS1302(RST_1302,HIGH); Cmd_Byte = READ_CMD; /* set command to the 1302 for burst read operation */ shifter = 0x01; for(i=0; i<8; i++) /* shift the read command */ { if (shifter & Cmd_Byte) DS1302(DAT_1302,HIGH); else DS1302(DAT_1302,LOW); /* set up the data line */ DS1302(CLK_1302,HIGH); shifter = shifter << 1; DS1302(CLK_1302,LOW); /* toggle the clock */ } //next i for(i=0; i<8; i++) /* read in the next 7 bytes returned */ { databyte = 0; /* start clean */ for(j=0; j<8; j++) /* read in a byte */ { //make room for the new bit databyte = databyte >> 1; /* shift the collected data right */ if (DS1302IN(DAT_1302)) databyte |= 0x80; else /* capture the state of the data line */ databyte &= 0x7f; DS1302(CLK_1302,HIGH); DS1302(CLK_1302,LOW); /* clock the chip */ } //next j TimeBuffer[i] = databyte; /* save it in the buffer */ } //next i Idle_1302(); /* set the port pins idle */ //clean-up of time if time is bad (like when clock is stopped...) if (TimeBuffer[0] > 0x59) { //The time is bogus, make an assumption TimeBuffer[5] = 4; //day of week: BCD 1-7 1=Sunday TimeBuffer[6] = 0x99; //year: BCD 00-99 TimeBuffer[4] = 0x1; //month: BCD 1-12 TimeBuffer[3] = 0x1; //day of month: BCD day 0-31 TimeBuffer[1] = 0x00; //minutes: 0,BCD minutes TimeBuffer[2] = 0x12; //hours: msb=1,12 hour/0,24 hour, BCD hour //msb=0, 0-23 BCD //msb=1, {10}{0=am/1=pm}01-12 BCD TimeBuffer[0] = 0; //0 sec //seconds: msb=1, clock hold, BCD seconds return(1); //indicate that clock was stopped } //end if (TimeBuffer[0] > 59) return(0); //indicate that clock is running } /* end Read_1302_Data() *//*********************************************************************WRITE_1302_Data*This routine will write all 8 bytes to the 1302 clock chip.*Inputs: TimeBuffer- Pointer to 8 byte unsigned char array where data* will be placed once read from the clock*Obtains from TimeBuffer:*TimeBuffer[0] seconds: msb=1, clock hold, BCD seconds*TimeBuffer[1] minutes: 0,BCD minutes*TimeBuffer[2] hours: msb=1,12 hour/0,24 hour, BCD hour* msb=0, 0-23 BCD* msb=1, {10}{0=am/1=pm}01-12 BCD*TimeBuffer[3] day of month: BCD day 0-31*TimeBuffer[4] month: BCD 1-12*TimeBuffer[5] day of week: BCD 1-7 1=Sunday*TimeBuffer[6] year: BCD 00-99*TimeBuffer[7] write protect: msb=1, write protect* msb=0, write en* Returns: None*********************************************************************/void Write_1302_Data(unsigned char * TimeBuffer) { unsigned char Cmd_Byte; /*clock command*/ unsigned char databyte; /*temp data byte*/ unsigned char shifter; /* bit selector */ unsigned int i,j; DS1302(CLK_1302,LOW); DS1302(DAT_1302,LOW); DS1302(RST_1302,HIGH); Cmd_Byte = WRITE_CMD;/* set command to the 1302 for burst write operation */ shifter = 0x01; for(i=0; i<8; i++) /* shift out the command */ { if (shifter & Cmd_Byte) DS1302(DAT_1302,HIGH); else DS1302(DAT_1302,LOW); /* set up the data port pin */ DS1302(CLK_1302,HIGH); shifter = shifter << 1; DS1302(CLK_1302,LOW); /* clock the chip */ } //next i for(i=0; i<8; i++) /* output all 8 bytes to DS1302 */ { shifter = 0x01; databyte = TimeBuffer[i]; /* get byte from buffer */ for(j=0; j<8; j++) /* shift out data */ { if (shifter & databyte) DS1302(DAT_1302,HIGH); else DS1302(DAT_1302,LOW);/* set up the data port pin */ DS1302(CLK_1302,HIGH); shifter = shifter << 1; DS1302(CLK_1302,LOW); /* clock the chip */ } //next j } //next i Idle_1302(); /* set the port pins idle */ return; } /* end Write_1302_Data() *//********************************************************************Enable_1302*Write enables the Dallas Semi 1302 clock chip.********************************************************************/void Enable_1302(void) { unsigned char Cmd_Byte; /*clock command*/ unsigned char databyte; /*temp data byte*/ unsigned char shifter; /* bit selector */ unsigned int i,j; DS1302(CLK_1302,LOW); DS1302(DAT_1302,LOW); DS1302(RST_1302,HIGH); Cmd_Byte = 0x8e;/* set command to the 1302 for write to write prot register */ shifter = 0x01; for(i=0; i<8; i++) /* shift out the command */ { if (shifter & Cmd_Byte) DS1302(DAT_1302,HIGH); else DS1302(DAT_1302,LOW); DS1302(CLK_1302,HIGH); shifter = shifter << 1; DS1302(CLK_1302,LOW); } //next i shifter = 0x01; databyte =0; /* we want to write enable the DS1302 chip */ for(j=0; j<8; j++) /* shift out the data */ { if (shifter & databyte) DS1302(DAT_1302,HIGH); else DS1302(DAT_1302,LOW); DS1302(CLK_1302,HIGH); shifter = shifter << 1; DS1302(CLK_1302,LOW); /* clock the chip */ } //next j Idle_1302(); /* idle the port pins */ return; } /* end Enable_1302() *//********************************************************************Idle_1302*This routine will set the port pins that drive the clock to*their idle states.********************************************************************/void Idle_1302(void) { DS1302(RST_1302,LOW); DS1302(DAT_1302,HIGH); DS1302(CLK_1302,HIGH); return; } /* end Idle_1302() *//********************************************************************Lock_1302*This routine will LOCK the clock and stop its oscillator to*preserve Battery Life.*Uses TimeBuffer[] as temporary storage.********************************************************************/void Lock_1302 (void) { unsigned char TimeBuffer[8]; //temp storage Read_1302_Data(&TimeBuffer[0]); //get the time TimeBuffer[0] = TimeBuffer[0]|0x80; //halt the clock Enable_1302(); //write enable the clock Write_1302_Data(&TimeBuffer[0]); //write back the halted time return; } /* end proc Lock_1203() *//********************************************************************Set_Time*This routine SETs the clock and start its oscillator, write-*protecting the clock registers.*Obtains time from TimeBuffer[].********************************************************************/void Set_Time(unsigned char * TimeBuffer) { TimeBuffer[7] = '\x80'; //write protect the chip after write Enable_1302(); //write enable the clock Write_1302_Data(TimeBuffer); //write the clock and start it up } /* end proc Set_Time() *//********************************************************************Get_Time*This routine GETs the time from the Dallas 1302 clock.*The time is returned in TimeBuffer.*This function returns 0 when the clock is operating properly.*If the clock was locked (stopped) the default time is returned*as 1/1/99, 12:00Noon and the function returns non-zero.********************************************************************/unsigned int Get_Time(unsigned char * TimeBuffer) { unsigned int clock_locked; clock_locked = Read_1302_Data(TimeBuffer); //store the time in system variable time.... //Note that since the values in the RTC and TimeBuffer are in //BCD, we need to convert back to normal numbers! ds_1302_time.year = (((TimeBuffer[6] & 0xf0)>>4)*10)+(TimeBuffer[6] & 0xf); ds_1302_time.month = (((TimeBuffer[4] & 0xf0)>>4)*10)+(TimeBuffer[4] & 0xf); ds_1302_time.date = (((TimeBuffer[3] & 0xf0)>>4)*10)+(TimeBuffer[3] & 0xf); ds_1302_time.hour = (((TimeBuffer[2] & 0x30)>>4)*10)+(TimeBuffer[2] & 0xf); ds_1302_time.min = (((TimeBuffer[1] & 0xf0)>>4)*10)+(TimeBuffer[1] & 0xf); ds_1302_time.sec = (((TimeBuffer[0] & 0xf0)>>4)*10)+(TimeBuffer[0] & 0xf); ds_1302_time.dayOfWeek = TimeBuffer[5]; return(clock_locked); } /* end proc Get_Time() */BYTE bcd2bin ( BYTE x ){ return ( ( x >> 4 ) * 10 + ( x & 0x0F ));}BYTE bin2bcd ( BYTE x ) //x : [0..99]{ return ((( x / 10 ) << 4 ) + ( x % 10 ));}/********************************************************************date_encoder*功能:此函数将6个字节的日期转换为传输协议要求的4字节日期********************************************************************/WORD date_encoder (BYTE * TimeBuffer){ BYTE x; WORD y; WORD clock_locked; clock_locked = Read_1302_Data(TimeBuffer); x = TimeBuffer[6]; //year x = bcd2bin ( x ); //BCD -> BIN y = ( x + 20 ) * 512; //from 1980 x = TimeBuffer[4]; //month x = bcd2bin ( x ); //BCD -> BIN y |= x * 32; x = TimeBuffer[3]; //date x = bcd2bin ( x ); //BCD -> BIN y |= x; return ( y );} /********************************************************************time_encoder*功能:此函数将6个字节的时间转换为传输协议要求的4字节时间********************************************************************/WORD time_encoder ( BYTE * TimeBuffer ){ BYTE x; WORD y; WORD clock_locked; clock_locked = Read_1302_Data(TimeBuffer); x = TimeBuffer[2] & 0x3F; //hour x = bcd2bin ( x ); //BCD -> BIN y = x * 2048; x = TimeBuffer[1]; //minute x = bcd2bin ( x ); //BCD -> BIN y |= x * 32; x = TimeBuffer[0] & 0x7F; //second x = bcd2bin ( x ); //BCD -> BIN y |= x / 2; return ( y );}/********************************************************************coder_endate*功能:此函数将传输协议要求的4字节日期还原为6个字节的日期********************************************************************/void coder_endate (WORD z){ BYTE y,x; x = (BYTE)(z&0x001F); //day x = bin2bcd ( x ); //BCD -> BIN y = x ; printf("0=%x\n",y); ds_1302_time.date = (((y & 0xf0)>>4)*10)+(y & 0xf); x = (BYTE)((z>>5)&0x000f); //minute x = bcd2bin ( x ); //BCD -> BIN y = x; printf("1=%x\n",y); ds_1302_time.month = (((y & 0xf0)>>4)*10)+(y & 0xf); x = (BYTE)(((z>>9)-20)&0x007f); //day x = bin2bcd ( x ); //BCD -> BIN y = x ; printf("3=%x\n",y); ds_1302_time.year = (((y & 0xf0)>>4)*10)+(y & 0xf);}/********************************************************************coder_entime*功能:此函数将传输协议要求的4字节时间还原为6个字节的时间********************************************************************/void coder_entime (WORD z){ BYTE y,x; x = (BYTE)(z&0x001F); //sec x = bin2bcd ( 2*x ); //BCD -> BIN y = x ; printf("0=%x\n",y); ds_1302_time.sec = (((y & 0xf0)>>4)*10)+(y & 0xf); x = (BYTE)((z&0x07e0)>>5); //minute x = bcd2bin ( x ); //BCD -> BIN y = x; printf("1=%x\n",y); ds_1302_time.min = (((y & 0xf0)>>4)*10)+(y & 0xf); x = (BYTE)((z>>11)&0x001f); //hour x = bin2bcd ( x ); //BCD -> BIN y = x ; printf("3=%x\n",y); ds_1302_time.hour = (((y & 0x30)>>4)*10)+(y & 0xf); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -