目录
一、电路图
二、底层驱动
三、实际应用
四、时序
一、电路图
上图是寄存器地址定义,时分秒,年月日等等
DS1302有自己的时钟线SCLK,不会跟单总线一样因为没有自己的时钟线而导致温度读不出来
CH:时钟静止,置1时钟就停止运行了
且上图的秒和分钟都分为了十位和个位,也就对应了BCD码用2个4位二进制数来表示十进制了,所以以BCD码的形式来看,
十位就是高四位,个位就是低四位,高四位/16+10,,然低四位直接%16后在相加即可得到十进制下的时间,具体做法看后面的实际应用
二、底层驱动
#ifndef __DS1302_H
#define __DS1302_H#include <STC15F2K60S2.H>
#include <intrins.h>sbit SCK = P1^7;
sbit SDA = P2^3;
sbit RST = P1^3; void Write_Ds1302(unsigned char temp);
void Write_Ds1302_Byte( unsigned char address,unsigned char dat );
unsigned char Read_Ds1302_Byte( unsigned char address );#endif
#include "ds1302.h" //写字节
void Write_Ds1302(unsigned char temp)
{unsigned char i;for (i=0;i<8;i++) { SCK = 0;SDA = temp&0x01;temp>>=1; SCK=1;}
} //向DS1302寄存器写入数据
void Write_Ds1302_Byte( unsigned char address,unsigned char dat )
{RST=0; _nop_();SCK=0; _nop_();RST=1; _nop_(); Write_Ds1302(address); Write_Ds1302(dat); RST=0;
}//从DS1302寄存器读出数据
unsigned char Read_Ds1302_Byte ( unsigned char address )
{unsigned char i,temp=0x00;RST=0; _nop_();SCK=0; _nop_();RST=1; _nop_();Write_Ds1302(address);for (i=0;i<8;i++) { SCK=0;temp>>=1; if(SDA)temp|=0x80; SCK=1;} RST=0; _nop_();SCK=0; _nop_();SCK=1; _nop_();SDA=0; _nop_();SDA=1; _nop_();return (temp);
}
三、实际应用
读写寄存器:
1.在哪 写入 什么
2.在哪 读出 什么
然后再main.c里面先写入,再读出,用数码管显示出来即可!
由地址命令字来实现
我们还要知道BCD码
我们定义的时间是以十进制展现的,而DS1302的寄存器中需要以BCD码的形式来存储数据,所以我们写入的时候要先转换成BCD码,然后读出数据的时候还要记得转换为十进制
若直接写入BCD码如写入秒寄存器0x50,就表示写入50秒,然后读出的时候转换成十进制就行了,如下列代码
void main() {LCD_Init();DS1302_Init();LCD_ShowString(1,1,"RTC");DS1302_WriteByte(0x8E,0x00);//解除写保护//DS1302_WriteByte(0x84,0x00);//hour//DS1302_WriteByte(0x82,0x00);//minDS1302_WriteByte(0x80,0x50);//secawhile(1){sec=DS1302_ReadByte(0x81);min=DS1302_ReadByte(0x83);hour=DS1302_ReadByte(0x85);LCD_ShowChar(2,6,':');LCD_ShowChar(2,3,':');LCD_ShowNum(2,7,sec/16*10+sec%16,2);LCD_ShowNum(2,4,min/16*10+min%16,2);LCD_ShowNum(2,1,hour/16*10+hour%16,2);} }
#define SEC 0x80
#define MIN 0x82
#define HOUR 0x84
#define DATA 0x86
#define MON 0x88
#define DAY 0x8a
#define YEAR 0x8c
#define WP 0x8eu8 time_buf[3] = {50,59,16};void SET_TIME()
{u8 i = 0;Write_Ds1302_Byte(WP,0x00);//关闭写保护for(i=0;i<3;i++){Write_Ds1302_Byte(SEC+i*2,time_buf[i]/10*16+time_buf[i]%10);//我们实现时分秒显示, //就分别对时分秒寄存器进行写入}Write_Ds1302_Byte(WP,0x80);//开启写保护
}void READ_TIME()
{u8 i = 0;u8 temp;for(i=0;i<3;i++){temp = Read_Ds1302_Byte(0x81+i*2);从时分秒寄存器读出数据给temptime_buf[i] = temp/16*10+temp%16;//将转化后的数据赋给time_buf的元素}
}
void main()
{ALL_INIT();Timer0Init();SET_TIME();while(1){READ_TIME(); seg_set(time_buf[2]/10,time_buf[2]%10,17,time_buf[1]/10,time_buf[1]%10,17,time_buf[0]/10,time_buf[0]%10); }
}void TIME_ISR() interrupt 1
{cnt++;seg_loop();cnt %= 1000;
}
关于数码管的使用若是不会可以看我前面的文章
四、时序
若是对时序感兴趣可以先自行看看研究
CE:操作使能,整个操作环节中,要给高电平
SCLK:时钟信号,在时钟上升沿向时钟芯片写入数据,在时钟下降沿读出时钟芯片的数据
只有读出的D0到D7由DS1320操控,其他全由单片机掌控