1.介绍
DS1302是一种串行接口的实时时钟,芯片内部具有可编程的日历时钟和31个字节的静态RAM。
2.内部结构
(1)SCLK:串行时钟输入端,控制数据输入与输出。
(2)I/O:双向输入线
(3)CE:使能端,CE为高时允许DS1302读写数据,CE端为低时DS1302数据不可读写
(4)X1与X2:外接32.768的圆形晶振,给时钟芯片提供晶振频率。
3.时钟日历控制寄存器
(1)秒寄存器(0X81,0X80): 当CH=1秒位停止关闭。
(2)小时寄存器(0x85,0x84):当BIT7为1时为12小时制,当BIT7为0时为24小时制。
(3)控制寄存器(0x8f,0x8e):当WP为1时,不能对Ds1302做任何操作。
4.DS130231字节的RAM寄存器
就是断电后仍然存在的数据区域
5.DS1302的工作模式寄存器
突发模式就是一次性转输多个字节的的数据到时钟或RAM
6.DS1320的通信时序
(1)从最低位开始
(2)读写数据:都是CE端由低到高,然后前8位,写命令字节,后8位,写数据字节。(上升沿时为写入,下降沿时为读出)
7.BCD码转换
(1)解释
因为我们时间是按一位一位来记录的,例如个位秒,十位秒,个位分…
所以我们用4位2进制就可以表示0-9的数字,(即8421任意选择加)
所以8421为 0000 0000,前四位表示10位,后四位表示个位
(2)BCD转8421码(BCD码)
例如45这个十进制数,先把十位与个位分开得到4与5,4是属于高四位的所以要再乘与16到高四位,所以45 = 416+5= 69 = 0100 0101
(3)8421转BCD码
如69这个8421码,先69/16得到高四位的值为4,再69%16得到低四位的值5,然后410+5=45,就是十进制数。
#include <reg52.h>
#include <intrins.h>
sbit LA=P2^2;
sbit LB=P2^3;
sbit LC=P2^4;
sbit TSCLK = P3^6; //时钟线
sbit TIO = P3^4; //数据线
sbit TRST = P3^5; //CE端,使能
//以下为显示函数
unsigned int miao;
unsigned char smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
void delay2(unsigned int z)
{
unsigned int x,y;
for(x=z;x>0;x--)
for(y=120;y>0;y--);
}
void timefrist()
{
EA = 1;
ET0 = 1;
TR0 = 1;
TMOD |= 0x01;
TH0 = 0xED;
TL0 = 0xFF;
}
void DigDisplay(unsigned int h)
{
unsigned int a = h % 60 % 10;
unsigned int b = h % 60 / 10;
unsigned int c = h / 60 % 10;
unsigned int d = h / 60 / 10;
static unsigned char wei=0;
switch(wei)
{
case 0: LA=1;LB=1;LC=1;P0 = smgduan[d];break;
case 1: LA=0;LB=1;LC=1;P0 = smgduan[c];break;
case 2: LA=1;LB=0;LC=1;P0 = smgduan[b];break;
case 3: LA=0;LB=0;LC=1;P0 = smgduan[a];break;
}
wei++;
if(wei==4)
{
wei = 0;
}
}
void timer0() interrupt 1
{
TH0 = 0xED;
TL0 = 0xFF;
DigDisplay(miao);
}
//以下为时钟函数
//写入数据
unsigned char Write_DS1302_DAT(unsigned char cmd,unsigned char dat)
{
unsigned char i;
TRST = 0;
TSCLK = 0;
TRST = 1; //CE端产生上升沿启动读写
for(i=0;i<8;i++)
{
TSCLK = 0;
TIO = cmd & 0x01; //由最低位开始
TSCLK = 1; //产生上升沿,直接写入数据
cmd >>= 1; //数据不断左移,把最低位提上
}
for(i=0;i<8;i++)
{
TSCLK = 0;
TIO = dat & 0x01;
TSCLK = 1;
dat >>= 1;
}
}
//读数据
char Read_DS1302_DAT(unsigned char cmd)
{
unsigned char i,dat;
TRST = 0;
TSCLK = 0;
TRST = 1; //CE端拉高,启动读或写
for(i=0;i<8;i++) //写入指命,找位置与功能
{
TSCLK = 0;
TIO = cmd & 0x01;
TSCLK = 1;
cmd >>= 1;
}
for(i=0;i<8;i++)
{
TSCLK = 0; //前面TSCLK已经被拉高了,现在拉低,数据读出
dat >>= 1; //数据右移动
if(TIO) dat |= 0x80; //转出数据为高电平,就最高位加一然后不断右移动到最低位
TSCLK = 1; //重新拉高回来
}
return dat; //返回数据
}
//10位变BCD
unsigned char Dat_Chg_BCD(unsigned char dat)
{
unsigned char dat1,dat2;
dat1 = dat /10;
dat2 = dat % 10;
dat2 = dat1*16 + dat2;
return dat2;
}
//BCD为10位
unsigned char BCD_Chg_Dat(unsigned char dat)
{
unsigned char dat1,dat2;
dat1 = dat / 16;
dat2 = dat2 %16;
dat2 = dat2 + dat1*10;
return dat2;
}
void main()
{
unsigned char a,b,c;
timefrist();
Write_DS1302_DAT(0x8e,0); //打开0x8e上WE置位为0
Write_DS1302_DAT(0x80,Dat_Chg_BCD(10)); //写秒0x80指命,后写入数据
Write_DS1302_DAT(0x82,Dat_Chg_BCD(50)); //写秒0x82指命,后写入数据
Write_DS1302_DAT(0x84,Dat_Chg_BCD(11)); //写秒0x84指命,后写入数据
Write_DS1302_DAT(0x8e,0x80); //打开0x8e上WE置位为1,不可读写
while(1)
{
Write_DS1302_DAT(0x8e,0); //打开0x8e上WE置位为0
a = BCD_Chg_Dat(Read_DS1302_DAT(0x81));//读取指命0x81,时间秒
b = BCD_Chg_Dat(Read_DS1302_DAT(0x83));//读取指命0x83,时间秒
c = BCD_Chg_Dat(Read_DS1302_DAT(0x85));//读取指命0x85,时间秒
Write_DS1302_DAT(0x8e,0x80); 打开0x8e上WE置位为1,不可读写
miao = a + b*60; //这里只用到了秒与分,全部化为秒后给全局变量
delay2(1000);
}
}