16-DS1302的基本应用

发布时间 2023-10-20 23:56:07作者: 夏日清凉~

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.引脚说明

20191214231423367

DS1302采用的是三线接口的双向数据通信接口,RST是片引脚,低电平有效;SCLK是时钟芯片,为通信提供时钟源;I/O为数据输入输出引脚,用于传输及接收数据;
DS1302还采用了双电源供电模式,VCC1 连接到备用电源,在VCC2主电源失效时保持时间和日期数据.

参考电路

20231020185326

DS1302芯片基本电路如上图,其中Y2为32.768k外部晶振,为芯片提供时钟源;VCC1为备用电池,以保证在主电源掉电后,芯片仍可继续运行,

DS1302相关寄存器

20231020223830

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控制字的格式

20231020232838

BIT7: 必须为1,若为0,则不能把数据写入DS1302中

BIT6: 0表示存取日历时钟数据,1表示存取RAM数据

BIT5~BIT1: 表示操作单元的地址

BIT0: 0表示写操作,1表示读操作

读时序说明

时序图:读取数据传输

20231020225457

单字节读

20231020225410

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;        
}

写时序说明

时序图:写数据传输

20231020231927

单字节写

20231020231942

由上可知,写字节比读字节稍做简单,只需依旧保持上升沿即可

代码如下

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;
       
}

20231020233840

时钟代码如下:

#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();
        }
}