目录
一、电路图
上图是寄存器地址定义,时分秒,年月日等等
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);//min DS1302_WriteByte(0x80,0x50);//seca while(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 0x8e
u8 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);从时分秒寄存器读出数据给temp
time_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操控,其他全由单片机掌控