16-DS1302的基本应用
DS1302的基本使用
一、描述
DS1302时钟芯片是由美国DALLAS公司推出的具有涓细电流充电能力的低功耗实时时钟芯片。它可以对年、月、日、周、时、分、秒进行计时,且具有闰年补偿等多种功能。DS1302芯片包含一个用于存储实时时钟/日历的 31 字节的静态 RAM,可通过简单的串行接口与微处理器通讯,将当前的是时钟存于RAM。DS1302芯片对于少于 31 天的月份月末会自动调整,并会自动对闰年进行校正。由于有一个 AM/PM 指示器,时钟可以工作在 12 小时制或者 24小时制。
芯片参数
1.芯片特点
- 实时时钟计算年、月、日、时、分、秒、星期、直到2100年,并有闰年调节功能
- 32×8位通用暂存ROM
- 串行输入输出使管脚数最少
- 2.0V至5.5V宽电压范围操作
- 在2.0V时工作电流小于300nA
- 读写时钟或 RAM 数据时有单字节或多字节(脉冲串模式)数据传送方式
- 8 管脚 DIP 封装或可选的 8 管脚表面安装 SO 封装
- 简单的 3 线接口
- 与 TTL 兼容 (VCC = 5V)
- 可选的工业温度范围:-40°C to +85°C
2.引脚说明
DS1302采用的是三线接口的双向数据通信接口,RST是片引脚,低电平有效;SCLK是时钟芯片,为通信提供时钟源;I/O为数据输入输出引脚,用于传输及接收数据;
DS1302还采用了双电源供电模式,VCC1 连接到备用电源,在VCC2主电源失效时保持时间和日期数据.
参考电路
DS1302芯片基本电路如上图,其中Y2为32.768k外部晶振,为芯片提供时钟源;VCC1为备用电池,以保证在主电源掉电后,芯片仍可继续运行,
DS1302相关寄存器
1.秒寄存器(80H和81H)的位7(CH)为时钟暂停标志
CH为0时,时钟震荡停止
CH为1时,时钟开始运行
2.控制寄存器(8EH和8FH)的位7(WP)为写保护位
WP为0时,可对任何的时钟或RAM寄存器进行写操作
WP为1时,禁止对任一寄存器进行写操作
DS1302内部含有8位控制寄存器用于存放DS1302控制命令字,例:如果为0x81就是读秒寄存器,如果为0x80就是对秒寄存写入数据,初始化时需要令WP为0,才可以写入初始时间。也就是需要写入将WP置0,关闭写保护,才能写入数据,写完数据后再开启写保护即将WP置一
DS1302控制字的格式
BIT7: 必须为1,若为0,则不能把数据写入DS1302中
BIT6: 0表示存取日历时钟数据,1表示存取RAM数据
BIT5~BIT1: 表示操作单元的地址
BIT0: 0表示写操作,1表示读操作
读时序说明
时序图:读取数据传输
单字节读
1.DS1302是通过串行总线跟单片机通信的,当进行一次读写操作是最少得读写两个字节,第一个字节就是控制字节,就是一个命令,告诉DS1302是读还是写操作,是对RAM还对CLOK寄存器操作。第二个字节就是要读写的数据了。
2.单字节读写:只有在SCLK为低电平时才能将RST(即CE)置为高电平。所以在进行操作之前先将SCLK置低电平,然后将RST(即CE)置为高电平,接着开始在IO上面放入要传输的电平信号,然后跳变SCLK。数据在SCLK上升沿时,DS1302读写数据,在SCLK下降沿时,DS1302放在数据到IO上
代码如下:
unsigned char DS1302_ReadByte(unsigned char addr)
{
unsigned char n;
unsigned dat = 0x00;
RST = 0;
SCLK = 0;
RST = 1;
for(n=0; n<8; n++)
{
DSIO = addr & 0x01;
addr >>= 1;
SCLK = 1;
SCLK = 0;
}
for(n=0; n<8; n++)
{
//tmp = DSIO;
//dat = (dat>>1) | (tmp<<7);
if(DSIO) { // IO == 1
dat = dat | (0x01 << n);
}
SCLK = 1;
SCLK = 0;
}
RST = 0;
SCLK = 1;
DSIO = 0;
return dat;
}
写时序说明
时序图:写数据传输
单字节写
由上可知,写字节比读字节稍做简单,只需依旧保持上升沿即可
代码如下
void DS1302_WriteByte(unsigned char addr, unsigned char dat)
{
unsigned char n;
RST = 0;
SCLK = 0;
RST = 1;
for (n=0; n<8; n++)
{
DSIO = addr & 0x01;
addr >>= 1;
SCLK = 1;
SCLK = 0;
}
for (n=0; n<8; n++)
{
DSIO = dat & 0x01;
dat >>= 1;
SCLK = 1;
SCLK = 0;
}
RST = 0;
}
时钟代码如下:
#include "reg52.h"
sbit SCLK = P1^7;
sbit RST = P1^3;
sbit DSIO = P2^3;
unsigned char code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};
unsigned char code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};
unsigned char TIME[7] = {0x30, 0x50, 0x23, 0x17, 0x02, 0x06, 0x18};
unsigned char code SMG_NoDot[18] =
{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,
0xbf,0x7f};
void DelaySMG(unsigned int time)
{
while(time--);
}
void Init74HC138(unsigned char n)
{
switch(n) {
case 4: P2 = (P2 & 0x1f) | 0x80;
break;
case 5: P2 = (P2 & 0x1f) | 0xa0;
break;
case 6: P2 = (P2 & 0x1f) | 0xc0;
break;
case 7: P2 = (P2 & 0x1f) | 0xe0;
break;
}
}
void DispaySMG_Bit(unsigned char value, unsigned char pos)
{
Init74HC138(6);
P0 = (0x01 << pos);
Init74HC138(7);
P0 = value;
}
void DS1302_WriteByte(unsigned char addr, unsigned char dat)
{
unsigned char n;
RST = 0;
SCLK = 0;
RST = 1;
for (n=0; n<8; n++)
{
DSIO = addr & 0x01;
addr >>= 1;
SCLK = 1;
SCLK = 0;
}
for (n=0; n<8; n++)
{
DSIO = dat & 0x01;
dat >>= 1;
SCLK = 1;
SCLK = 0;
}
RST = 0;
}
unsigned char DS1302_ReadByte(unsigned char addr)
{
unsigned char n;
unsigned dat = 0x00;
RST = 0;
SCLK = 0;
RST = 1;
for(n=0; n<8; n++)
{
DSIO = addr & 0x01;
addr >>= 1;
SCLK = 1;
SCLK = 0;
}
for(n=0; n<8; n++)
{
//tmp = DSIO;
//dat = (dat>>1) | (tmp<<7);
if(DSIO) { // IO == 1
dat = dat | (0x01 << n);
}
SCLK = 1;
SCLK = 0;
}
RST = 0;
SCLK = 1;
DSIO = 0;
return dat;
}
void DS1302_Config()
{
unsigned char n;
DS1302_WriteByte(0x8E,0x00);
for (n=0; n<7; n++)
{
DS1302_WriteByte(WRITE_RTC_ADDR[n],TIME[n]);
}
DS1302_WriteByte(0x8E,0x80);
}
void DS1302_ReadTime()
{
unsigned char n;
for (n=0; n<7; n++) {
TIME[n] = DS1302_ReadByte(READ_RTC_ADDR[n]);
}
}
void XMF_ShowRealTime()
{
DispaySMG_Bit(SMG_NoDot[TIME[2]/16],0);
DelaySMG(500);
DispaySMG_Bit(0xff,0);
DispaySMG_Bit(SMG_NoDot[TIME[2]&0x0f],1);
DelaySMG(500);
DispaySMG_Bit(0xff,1);
DispaySMG_Bit(SMG_NoDot[16],2);
DelaySMG(500);
DispaySMG_Bit(0xff,2);
DispaySMG_Bit(SMG_NoDot[TIME[1]/16],3);
DelaySMG(500);
DispaySMG_Bit(0xff,3);
DispaySMG_Bit(SMG_NoDot[TIME[1]&0x0f],4);
DelaySMG(500);
DispaySMG_Bit(0xff,4);
DispaySMG_Bit(SMG_NoDot[16],5);
DelaySMG(500);
DispaySMG_Bit(0xff,5);
DispaySMG_Bit(SMG_NoDot[TIME[0]/16],6);
DelaySMG(500);
DispaySMG_Bit(0xff,6);
DispaySMG_Bit(SMG_NoDot[TIME[0]&0x0f],7);
DelaySMG(500);
DispaySMG_Bit(0xff,7);
}
void main(){
DS1302_Config();
while(1){
DS1302_ReadTime();
XMF_ShowRealTime();
}
}