DS1302 时钟 51单片机实现时钟显示

2019-07-14 03:32发布

DS1302 具有能计算2100年以前的秒分时……的能力,还有闰年调整功能 主要性能指标: 1、工作电压范围:2.0~5.5V 2、工作电流范围:2.0V时,电流小于200nA,功耗极低 3、TTL兼容 4、采用主电源和备份电源双电源供应 5、两种数据传送方式:单字节传送和多字节传送 6、采用串行数据传送方式 ds1302时钟的链接图 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();//数码管显示函数 } }