1.分析原理图
由上图可以看到,芯片的时钟引脚SCK接到了P17,数据输出输入引脚IO接到P23,复位引脚RST接到P13。
2.查阅DS1302芯片手册
具体细节还需自行翻阅手册,我只截出重点部分
总结:数据在上升沿写出,下降沿读入,读时序命令字节结束的下降沿读出数据
3.代码封装库
请自行阅读芯片手册,理解记忆即可
#include "ds1302.h"
void DS1302_writebyte(u8 command,u8 byte)
{
u8 i;
RST=1;
for(i=0;i<8;i++)
{
IO=command &(0x01<<i); //低位在前
SCK=1; //提供上升沿,输出数据
SCK=0;
}
for(i=0;i<8;i++)
{
IO=byte &(0x01<<i); //低位在前
SCK=1; //提供上升沿,输出数据
SCK=0;
}
RST=0;
}
u8 DS1302_readbyte(u8 command)
{
u8 i,byte=0x00;
RST=1;
command++;
for(i=0;i<8;i++)
{
IO=command &(0x01<<i); //低位在前
SCK=0; //提供上升沿,输出数据
SCK=1;
}
for(i=0;i<8;i++)
{
SCK=1; //在下降沿读入数据
SCK=0;
if(IO) byte|=(0x01<<i); //低位在前
}
RST=0;IO=0; //复位
return byte;
}
//时间数组,分别为年、月、日、时、分、秒、星期
u8 DS1302_Time[]={24,1,28,00,00,30,7};
//写入初始时间
void Init_DS1302()
{
RST=0;SCK=0; //复位
DS1302_writebyte(0x8e,0x00);//写保护关
//十进制转BCD码后写入
DS1302_writebyte(0x8c,DS1302_Time[0]/10*16+DS1302_Time[0]%10); //年
DS1302_writebyte(0x88,DS1302_Time[1]/10*16+DS1302_Time[1]%10); //月
DS1302_writebyte(0x86,DS1302_Time[2]/10*16+DS1302_Time[2]%10); //日
DS1302_writebyte(0x84,DS1302_Time[3]/10*16+DS1302_Time[3]%10); //时
DS1302_writebyte(0x82,DS1302_Time[4]/10*16+DS1302_Time[4]%10); //分
DS1302_writebyte(0x80,DS1302_Time[5]/10*16+DS1302_Time[5]%10); //秒
DS1302_writebyte(0x8a,DS1302_Time[6]/10*16+DS1302_Time[6]%10); //星期
DS1302_writebyte(0x8e,0x80);
}
//读取后的时间存放于数组DS1302_Time[]
void DS1302_ReadTime()
{
//BCD码转十进制后读取
u8 Temp;
Temp=DS1302_readbyte(0x8c);
DS1302_Time[0]=(Temp>>4)*10+Temp%16;
Temp=DS1302_readbyte(0x88);
DS1302_Time[1]=(Temp>>4)*10+Temp%16;
Temp=DS1302_readbyte(0x86);
DS1302_Time[2]=(Temp>>4)*10+Temp%16;
Temp=DS1302_readbyte(0x84);
DS1302_Time[3]=(Temp>>4)*10+Temp%16;
Temp=DS1302_readbyte(0x82);
DS1302_Time[4]=(Temp>>4)*10+Temp%16;
Temp=DS1302_readbyte(0x80);
DS1302_Time[5]=(Temp>>4)*10+Temp%16;
Temp=DS1302_readbyte(0x8a);
DS1302_Time[6]=(Temp>>4)*10+Temp%16;
}
4.使用示例
我这里使用之前封装的数码管显示函数来显示时间:
#include "main.h"
extern u8 DS1302_Time[];//0~6:年月日时分秒星期
void System_Init(void);
void Timer0_Init(void);
void main()
{
System_Init();
Timer0_Init();
Init_DS1302();
while(1)
{
Nixie_Display(1,DS1302_Time[3]/10); //时
Nixie_Display(2,DS1302_Time[3]%10);
Nixie_Display(3,DS1302_Time[4]/10); //分
Nixie_Display(4,DS1302_Time[4]%10);
Nixie_Display(5,DS1302_Time[5]/10); //秒
Nixie_Display(6,DS1302_Time[5]%10);
Nixie_Display(7,16); //.
Nixie_Display(8,DS1302_Time[6]); //星期天
}
}
void Timer0_Isr() interrupt 1
{
static u16 count1=0;
if(++count1==1000){
P10=!P10;
Set_Leds(1,P10);
DS1302_ReadTime();
count1=0;
}
}
void Timer0_Init() //1毫秒@12.000MHz
{
AUXR &= 0x7F; //12T模式
TMOD &= 0xF0; //定时器0:16位自动重装载
TL0 = 0x18; //设置定时初始值
TH0 = 0xFC;
TF0 = 0; //清除TF0标志
ET0 = 1; //使能定时器0中断
EA = 1; //开总中断
TR0 = 1; //定时器0开始计时
}
void System_Init()//系统上电初始化
{
//先锁存蜂鸣器,继电器所在573输出低电平,防止上电乱叫
P25=1;P26=0;P27=1; //74HC138-->Y5=0,else=1-->Y5C=1,else=0
P04=0;P06=0; //ULN2003输入经过非门送入达林顿管,低电平有效
P25=0;P26=0;P27=0;//锁存数据
//关闭所有LED灯
P25=0;P26=0;P27=1; //74HC138-->Y4=0,else=1-->Y4C=1,else=0
P0=0XFF;
P25=0;P26=0;P27=0;//锁存数据
}