DS1302 具有能计算2100年以前的秒分时……的能力,还有闰年调整功能
主要性能指标:
1、工作电压范围:2.0~5.5V
2、工作电流范围:2.0V时,电流小于200nA,功耗极低
3、TTL兼容
4、采用主电源和备份电源双电源供应
5、两种数据传送方式:单字节传送和多字节传送
6、采用串行数据传送方式
x1,x2:晶振接入引脚
I/O:input/output具有三态功能
VCC1:工作电源
vcc2:备用电源引脚,接入电池或者大电容
sclk: 串行时钟输入
DS1302.h
#ifndef DS1302_H
#define DS1302_H
#include "reg52.h"
#include "intrins.h"
#ifndef uchar //同理于c文件中的typedef unsigned char uchar;
#define uchar unsigned char
#endif
#ifndef uint
#define uint unsigned int
#endif
sbit DSIO = P3^4;
sbit RST = P3^5;
sbit SCLK = P3^6;
void Ds1302Write(uchar addr,uchar dat);
uchar Ds1302Read(uchar addr);
void Ds1302Init();
void Ds1302readTime();
extern uchar TIME[7];
#endif
SPI:串行外围接口
SPI接口主要以主从方式工作的,这种模式通常有一个主器件或多个从器件,其接口包括以下四种信号:
sclk: 时钟器件由主器件产生
MOSI:主器件数据output,从器件input
MISO:主器件数据input,从器件output
~SS:从器件使能信号,由主器件控制
缺点:没有指定的流控制,没有应答机制,确认是否接受到数据
Ds1302.c
#include "Ds1302.h"
/*
DS1302写入和读取时分秒的地址命令
秒分时日月周年 最低位读写位;
*/
uchar code READ_RTC_ADDR[7]=
{0x81,0x83,0x85,0x87,0x89,0x8B,0x8D};
uchar code WEITE_RTC_ADDR[7]=
{0x80,0x82,0x84,0x86,0x88,0x8A,0x8C};
/*
DS1302时钟初始化2018年5月13日星期六23点00分00秒。
存储顺序是秒分时日月周年,存储格式是用BCD码
*/
uchar TIME[7]={0,0,0x23,0x013,0x05,0x06,0x18};
/*
DS1302是通过SPI串行总线跟单片机通信的,当进行一次读写操作时最少得读写两个字节,第一个字节是控制字节,就是一个命令,告诉DS1302是读还是写操作,是对RAM还是对CLOK寄存器操作。第二个字节就是要读或写的数据了。
单字节读写:
只有在SCLK为低电平时,才能将CE置为高电平。
所以在进行操作之前先将SCLK置低电平,然后将CE置为高电平,接着开始在IO上面放入要传送的电平信号,然后跳变SCLK。
数据在SCLK上升沿时,DS1302读写数据,在SCLK下降沿时,DS1302放置数据到IO上
*/
void Ds1302Write(uchar addr,uchar dat)//向DS1302命令(地址+数据)
{
uchar n;
RST=0;_nop_();
SCLK=0;_nop_();
RST=1;_nop_();
for(n=0;n<8;n++){//地址传送
DSIO=addr&0x01;
addr>>=1;
SCLK=1;_nop_();
SCLK=0;_nop_();
}
for(n=0;n<8;n++){//读数据
DSIO=dat&0x01;
dat>>=1;
SCLK=1;_nop_();//数据在SCLK上升沿时,DS1302读写数据,
//在SCLK下降沿时,DS1302放置数据到IO上
SCLK=0;_nop_();
}
RST=0;_nop_();
}
uchar Ds1302Read(uchar addr)
{
uchar r,dat1,dat;
RST=0;_nop_();
SCLK=0;_nop_();
RST=1;_nop_();
for(r=0;r<8;r++){
DSIO=addr&0x01;
addr>>=1;
SCLK=1;_nop_();
SCLK=0;_nop_();
}
_nop_();
for(r=0;r<8;r++){
dat1=DSIO;
dat=(dat>>1)|(dat1<<7);
SCLK=1;_nop_();//数据在SCLK上升沿时,DS1302读写数据,
//在SCLK下降沿时,DS1302放置数据到IO上
SCLK=0;_nop_();
}
RST=0;_nop_();
SCLK=1;_nop_();
DSIO=0;_nop_();
DSIO=1;_nop_();
return dat;
}
/*
控制寄存器用于存放DS1302的控制命令字,
DS1302的RST引脚回到高电平后写入的第一个字就为控制命令。
它用于对DS1302读写过程进行控制,它的格式如下:
D7:固定为1
D6:RAM/CK位,=1片内RAM,=0日历、时钟寄存器选择位。
D5~D1:地址位,用于选择进行读写的日历、时钟寄存器或片内RAM。对日历、时钟寄存器或片内RAM的选择见表。
D0: 读写选择,=0写,=1读
*/
void Ds1302Init()
{
uchar n;
Ds1302Write(0x8e,0x00);//禁止写保护
for(n=0;n<8;n++){
Ds1302Write(WRITE_RTC_ADDR[n],TIME[N]);
}
Ds1302Write(0x8e,0x80);//打开写保护
}
void Ds1302readTime()//读取时钟信息
{
uchar n;
for(n=0;n<8;n++){
TIME[n]=Ds1302Read(READ_RTC_ADDR[n]);
}
}
main.c
#include "reg52.h"
#include "Ds1302.h"
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
typedef unsigned int u16;
typedef unsigned char u8;
char num=0;
u8 DisplayData[8];
u8 code smgduan[10]=
{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
void delay(u16 i){//最简单的延时程序
while(i--);
}
void dispros()
{
Da1302readtime();
DisplayData[0] = smgduan[TIME[2]/16]; //时
DisplayData[1] = smgduan[TIME[2]&0x0f];
DisplayData[2] = 0x40;
DisplayData[3] = smgduan[TIME[1]/16]; //分
DisplayData[4] = smgduan[TIME[1]&0x0f];
DisplayData[5] = 0x40;
DisplayData[6] = smgduan[TIME[0]/16]; //秒
DisplayData[7] = smgduan[TIME[0]&0x0f];
}
void display()
{
u8 i;
for(i=0;i<8;i++)
{
switch(i) //位选,选择点亮的数码管,
{
case(0):
LSA=0;LSB=0;LSC=0; break;//显示第0位
case(1):
LSA=1;LSB=0;LSC=0; break;//显示第1位
case(2):
LSA=0;LSB=1;LSC=0; break;//显示第2位
case(3):
LSA=1;LSB=1;LSC=0; break;//显示第3位
case(4):
LSA=0;LSB=0;LSC=1; break;//显示第4位
case(5):
LSA=1;LSB=0;LSC=1; break;//显示第5位
case(6):
LSA=0;LSB=1;LSC=1; break;//显示第6位
case(7):
LSA=1;LSB=1;LSC=1; break;//显示第7位
}
P0=DisplayData[i];//发送数据
delay(100); //间隔一段时间扫描
P0=0x00;//消隐
}
}
//最基本的简单实现函数
void main()
{
Ds1302Init();
while(1)
{
datapros(); //数据处理函数
DigDisplay();//数码管显示函数
}
}