51单片机—DS1302实时时钟

一、DS1302的介绍

S1302 是 DALLAS 公司推出的涓流充电时钟芯片,内含有一个实时时钟/日历和 31 字节静态 RAM,通过简单的串行接口与单片机进行通信。实时时钟/日历电路提供秒、分、时、日、周、月、年的信息,每月的天数和闰年的天数可自动调整。时钟操作可通过 AM/PM 指示决定采用 24 或 12 小时格式。DS1302 与单片机之间能简单地采用同步串行的方式进行通信,仅需用到三根通信线:

  • RES复位
  • I/O数据线
  • SCLK串行时钟
    S1302 由 DS1202 改进而来增加了以下的特性:双电源管脚用于主电源和备份电源供应,Vcc1 为可编程涓流充电电源,附加七个字节存储器。它广泛应用于电话、传真、便携式仪器以及电池供电的仪器仪表等产品领域下面。

1.1.主要性能指标

  • 实时时钟具有能计算 2100 年之前的秒、分、时、日、星期、月、年的能力,还有闰年调整的能力。
  • 31 个 8 位暂存数据存储 RAM。
  • 串行 I/O 口方式使得管脚数量最少。
  • 宽范围工作电压 2.0~5.5V。
  • 工作在 2.0V 时,电流小于 300nA。
  • 读/写时钟或 RAM 数据时有两种传送方式单字节传送和多字节传送字符组方式。
  • 8 脚 DIP 封装或可选的 8 脚 SOIC 封装根据表面装配。
  • 简单 3 线接口。
  • 与 TTL 兼容 Vcc=5V。
  • 可选工业级温度范围-40~+85。

1.2.DS1302芯片的管脚及功能

在这里插入图片描述

  • VCC2:主用电源引脚。
  • X1、X2:DS1302 外部晶振引脚,通常需外接 32.768K 晶振。
  • GND:电源地。
  • CE:使能引脚,也是复位引脚(新版本功能变)。
  • I/O:串行数据引脚,数据输出或者输入都从这个引脚。
  • SCLK:串行时钟引脚。
  • VCC1:备用电源。

1.3.DS1302的寄存器

1.3.1.控制寄存器

控制寄存器用于存放 DS1302 的控制命令字,DS1302 的 RST 引脚回到高电平后写入的第一个字节就为控制命令。它用于对 DS1302 读写过程进行控制,格式如下:
在这里插入图片描述
由上图可知:

  • 第 7 位永远都是 1。
  • 第 6 位,1 表示 RAM,寻址内部存储器地址;0 表示 CK,寻址内部寄存器。
  • 第 5 到第 1 位,为 RAM 或者寄存器的地址。
  • 最低位,高电平表示 RD,即下一步操作将要“读”;低电平表示 W,即下一步操作将要“写”。

1.4.DS1302 的读写时序

在控制指令字输入后的下一个 SCLK 时钟的上升沿时,数据被写入 DS1302,数据输入从低位(位 0)开始。同样,在紧跟 8 位的控制指令字后的下一个 SCLK脉冲的下降沿读出 DS1302 的数据,读出数据时从低位 0 位到高位 7。
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/967454e612574201bda492d4823e2771.png

1.5.硬件设计

在这里插入图片描述
从上图中可以看出,该电路是集成的,DS1302 芯片的控制管脚接至单片机P3_4~P3_6 上,在芯片的 X1、X2 管脚处外接了一个 32.768KHZ 晶振,为时钟运行提供一个稳定的时钟频率。

1.6.软件设计

以下是DS1302.c文件:

#include <REGX52.H>

sbit DS1302_CE=P3^5;
sbit DS1302_IO=P3^4;
sbit DS1302_SCLK=P3^6;

#define DS1302_SECOND  0x80
#define DS1302_MINUTE  0x82
#define DS1302_HOUR    0x84
#define DS1302_DATE    0x86
#define DS1302_MONTH   0x88
#define DS1302_DAY     0x8A
#define DS1302_YEAR    0x8C
#define DS1302_WP      0x8E

unsigned char DS1302_Time[]={25,4,9,17,19,30,3};

void DS1302_Init(void)
{
	DS1302_CE=0;
	DS1302_IO=0;
}

void DS1302_WriteByte(unsigned char Command,Data)
{
	unsigned char i;
	DS1302_CE=1;
	for(i=0;i<8;i++)
	{
		DS1302_IO=Command&(0x01<<i);
		DS1302_SCLK=1;
		DS1302_SCLK=0;
	}
	for(i=0;i<8;i++)
	{
		DS1302_IO=Data&(0x01<<i);
		DS1302_SCLK=1;
		DS1302_SCLK=0;
	}
	DS1302_CE=0;
}

unsigned char DS1302_ReadByte(unsigned char Command)
{
	unsigned char i,Data=0x00;
	DS1302_CE=1;
	Command|=0x01;
	for(i=0;i<8;i++)
	{
		DS1302_IO=Command&(0x01<<i);
		DS1302_SCLK=0;
		DS1302_SCLK=1;
	}
	for(i=0;i<8;i++)
	{
		DS1302_SCLK=1;
		DS1302_SCLK=0;
		if(DS1302_IO){Data|=(0x01<<i);}        //不是1就补上0,是1就置1,录进DS1302_IO
	}
	DS1302_CE=0;
	DS1302_IO=0;
	return Data;
}

void DS1302_SetTime(void)
{
	DS1302_WriteByte(DS1302_WP,0x00);
	DS1302_WriteByte(DS1302_YEAR,  DS1302_Time[0]/10*16+DS1302_Time[0]%10);
	DS1302_WriteByte(DS1302_MONTH, DS1302_Time[1]/10*16+DS1302_Time[1]%10);
	DS1302_WriteByte(DS1302_DATE,  DS1302_Time[2]/10*16+DS1302_Time[2]%10);
	DS1302_WriteByte(DS1302_HOUR,  DS1302_Time[3]/10*16+DS1302_Time[3]%10);
	DS1302_WriteByte(DS1302_MINUTE,DS1302_Time[4]/10*16+DS1302_Time[4]%10);
	DS1302_WriteByte(DS1302_SECOND,DS1302_Time[5]/10*16+DS1302_Time[5]%10);
	DS1302_WriteByte(DS1302_DAY,   DS1302_Time[6]/10*16+DS1302_Time[6]%10);
	DS1302_WriteByte(DS1302_WP,0x80);
}

void DS1302_ReadTime(void)
{
	unsigned char temp;
	temp=DS1302_ReadByte(DS1302_YEAR);
	DS1302_Time[0]=temp/16*10+temp%16;
	
	temp=DS1302_ReadByte(DS1302_MONTH);
	DS1302_Time[1]=temp/16*10+temp%16;
	
	temp=DS1302_ReadByte(DS1302_DATE);
	DS1302_Time[2]=temp/16*10+temp%16;
	
	temp=DS1302_ReadByte(DS1302_HOUR);
	DS1302_Time[3]=temp/16*10+temp%16;
	
	temp=DS1302_ReadByte(DS1302_MINUTE);
	DS1302_Time[4]=temp/16*10+temp%16;
	
	temp=DS1302_ReadByte(DS1302_SECOND);
	DS1302_Time[5]=temp/16*10+temp%16;
	
	temp=DS1302_ReadByte(DS1302_DAY);
	DS1302_Time[6]=temp/16*10+temp%16;
}

以下是DS1302.h头文件:

#ifndef __DS1302_H__
#define __DS1302_H__


unsigned char DS1302_Time[];


void DS1302_Init(void);
void DS1302_WriteByte(unsigned char Command,Data);
unsigned char DS1302_ReadByte(unsigned char Command);
void DS1302_SetTime(void);
void DS1302_ReadTime(void);

#endif

在主函数main里包含它的头文件:

#include <REGX52.H>
#include "LCD1602.h"
#include "DS1302.h"


void main()
{
	LCD_Init();
	DS1302_Init();
	LCD_ShowString(1,1,"  -  -  ");
	LCD_ShowString(2,1,"  :  :  ");
	DS1302_SetTime();
	
	while(1)
	{
		DS1302_ReadTime();
		LCD_ShowNum(1,1,DS1302_Time[0],2);
		LCD_ShowNum(1,4,DS1302_Time[1],2);
		LCD_ShowNum(1,7,DS1302_Time[2],2);
		LCD_ShowNum(2,1,DS1302_Time[3],2);
		LCD_ShowNum(2,4,DS1302_Time[4],2);
		LCD_ShowNum(2,7,DS1302_Time[5],2);
		LCD_ShowNum(2,10,DS1302_Time[6],2);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值