对DS1302的操作最容易出错的就是它的读写时序,如附件中所示。
当对DS1302写数据时,前面的命令与后面紧跟的数据无差别,均是上升沿有效;
当读数据时,前面的命令是上升沿有效,紧跟的DS1302返回的数据是下降沿有效,并且是紧跟写数据的那个时序开始,这点要特别注意,下面是我写的DS1302的读取与设置,是我一直在用的,希望能帮到你。
#include <regx52.h>
#include <intrins.h>
#define DS1302_SCLK P3_4 //1302的SCLK端口
#define DS1302_IO P3_5 //1302的IO端口
#define DS1302_CE P3_6 //1302的CE端口
/*1302各寄存器写入与读取命令*********/
#define DS1302_WRITE_SEC 0x80
#define DS1302_READ_SEC 0x81
#define DS1302_WRITE_MIN 0x82
#define DS1302_READ_MIN 0x83
#define DS1302_WRITE_HOUR 0x84
#define DS1302_READ_HOUR 0x85
#define DS1302_WRITE_DAY 0x86
#define DS1302_READ_DAY 0x87
#define DS1302_WRITE_MONTH 0x88
#define DS1302_READ_MONTH 0x89
#define DS1302_WRITE_WEEK 0x8a
#define DS1302_READ_WEEK 0x8b
#define DS1302_WRITE_YEAR 0x8c
#define DS1302_READ_YEAR 0x8d
#define DS1302_WRITE_CONTROL 0x8e
#define DS1302_READ_CONTROL 0x8f
/*DS1302相关函数********************************/
void DS1302_Init();//DS1302初始化
void DS1302_TimeGet();//获取DS1302中的时间
void DS1302_TimeSet();//设置DS1302中的时间
void DS1302_Write(unsigned char dat);//项1302写数据
void DS1302_WriteDatToPos(unsigned char pos,unsigned char dat);//向地址pos写数据dat
unsigned char DS1302_Read();//读1302数据
unsigned char DS1302_ReadDatFromPos(unsigned char pos);//读取pos地址的数据
unsigned char YEAR,MONTH,DAY,HOUR,MIN,SEC,WEEK;//全部变量,用于存储时间信息
void main(){
DS1302_Init();
while(1){
DS1302_TimeGet();
}
}
void delay(unsigned int i){
for( ;i>0;i--);
}
void DS1302_Init(){
unsigned char secs,mins,hours,year,month,day,week;
/*获取当前DS1302中存储的时间及状态信息*********/
secs = DS1302_ReadDatFromPos(DS1302_READ_SEC);
mins = DS1302_ReadDatFromPos(DS1302_READ_MIN);
hours = DS1302_ReadDatFromPos(DS1302_READ_HOUR);
year = DS1302_ReadDatFromPos(DS1302_READ_YEAR);
month = DS1302_ReadDatFromPos(DS1302_READ_MONTH);
day = DS1302_ReadDatFromPos(DS1302_READ_DAY);
week = DS1302_ReadDatFromPos(DS1302_READ_WEEK);
mins = (mins>>4)*10 + (mins&0x0F);
hours = (hours>>4)*10 + (hours&0x0F);
year = (year>>4)*10 + (year&0x0F);
month = (month>>4)*10 + (month&0x0F);
day = (day>>4)*10 + (day&0x0F);
/*若判断DS1302处于未初始化状态或者时间信息存在问题,则初始化之*/
if((0x80&secs) || (mins>59) || (hours>23) || (year>99) ||\
(month>12) || (0==month) || (day>31) || (0==day) || (week>7) || (0==week)){
DS1302_WriteDatToPos(DS1302_WRITE_CONTROL,0x00);//关闭写保护
DS1302_WriteDatToPos(DS1302_WRITE_SEC,0x55);
DS1302_WriteDatToPos(DS1302_WRITE_MIN,0x55);
DS1302_WriteDatToPos(DS1302_WRITE_HOUR,0x00);
DS1302_WriteDatToPos(DS1302_WRITE_DAY,0x01);
DS1302_WriteDatToPos(DS1302_WRITE_MONTH,0x01);
DS1302_WriteDatToPos(DS1302_WRITE_WEEK,0x02);
DS1302_WriteDatToPos(DS1302_WRITE_YEAR,0x13);
DS1302_WriteDatToPos(DS1302_WRITE_CONTROL,0x80);//开启写保护
}
}
void DS1302_TimeGet(){//获取DS1302中的时间
unsigned char i,tmp;
code unsigned char readCmd[]={DS1302_READ_SEC,DS1302_READ_MIN,DS1302_READ_HOUR,\
DS1302_READ_DAY,DS1302_READ_MONTH,DS1302_READ_WEEK,DS1302_READ_YEAR};
code unsigned char *timePoint[]={&SEC,&MIN,&HOUR,&DAY,&MONTH,&WEEK,&YEAR};
for(i=0; i<7; i++){
tmp = DS1302_ReadDatFromPos(readCmd[i]);
tmp = (tmp>>4)*10 + (tmp&0x0F);
*timePoint[i]=tmp;
}
}
void DS1302_TimeSet(){//设置DS1302中的时间
unsigned char i,tmp;
code unsigned char writeCmd[]={DS1302_WRITE_SEC,DS1302_WRITE_MIN,DS1302_WRITE_HOUR,\
DS1302_WRITE_DAY,DS1302_WRITE_MONTH,DS1302_WRITE_WEEK,DS1302_WRITE_YEAR};
code unsigned char *timePoint[]={&SEC,&MIN,&HOUR,&DAY,&MONTH,&WEEK,&YEAR};
DS1302_WriteDatToPos(DS1302_WRITE_CONTROL,0x00);//关闭写保护
for(i=0; i<7; i++){
tmp = *timePoint[i];
tmp = ((tmp/10)<<4)|(tmp%10);
DS1302_WriteDatToPos(writeCmd[i],tmp);
}
DS1302_WriteDatToPos(DS1302_WRITE_CONTROL,0x80);//开启写保护
}
void DS1302_Write(unsigned char dat){//向1302写数据
unsigned char i;
DS1302_SCLK = 0;
delay(2);
for(i=0; i<8; i++){
DS1302_IO = dat&0x01;
delay(1);
DS1302_SCLK = 1;
delay(1);
DS1302_SCLK = 0;
dat >>= 1;
}
}
void DS1302_WriteDatToPos(unsigned char pos,unsigned char dat){//向地址pos写数据dat
DS1302_CE = 0;
DS1302_SCLK = 0;
DS1302_CE = 1;
delay(2);
DS1302_Write(pos);
DS1302_Write(dat);
DS1302_SCLK = 1;
DS1302_CE = 0;
delay(1);
DS1302_SCLK = 0;
DS1302_IO = 0;
}
unsigned char DS1302_Read(){//读1302数据
unsigned char i,dat;
delay(2);
for(i=0; i<8; i++){
dat >>= 1;
if(1 == DS1302_IO){
dat |= 0x80;
}
DS1302_SCLK = 1;
delay(1);
DS1302_SCLK = 0;
delay(1);
}
return dat;
}
unsigned char DS1302_ReadDatFromPos(unsigned char pos){//读取pos地址的数据
unsigned char dat;
DS1302_CE = 0;
DS1302_SCLK = 0;
DS1302_CE = 1;
DS1302_Write(pos);
dat = DS1302_Read();
DS1302_SCLK = 1;
DS1302_CE = 0;
delay(1);
DS1302_SCLK = 0;
DS1302_IO = 0;
return dat;
}
|