51单片机DS1302实时时钟驱动程序

DS1302是低功耗实时时钟芯片,它可以对年、月、日、周、时、分、秒进行计时,且具有闰年补偿等多种功能。主要特点是采用串行数据传输,可为掉电保护电源提供可编程的充电功能,并且可以关闭充电功能。

一.基本原理

1.引脚分析

51单片机DS1302实时时钟驱动程序_第1张图片

2.时序分析
(1)写字节

51单片机DS1302实时时钟驱动程序_第2张图片

第一个字节是地址字节,第二个字节是数据字节。RST信号必须拉高,否则数据的输入是无效的。换一句话说,RST信号控制数据|时间信号输入的开始和结束。地址字节和数据字节的读取时上升沿有效,而且是由LSB开始读入。

(2)读字节

51单片机DS1302实时时钟驱动程序_第3张图片

读一个字节和写一个字节有明显的不一样,先是写地址字节,然后再读数据字节,写地址字节时上升沿有效,而读数据字节时下降沿有效,当然前提是RST信号必须拉高。写地址字节和读数据字节同是从最低位(即第0位)开始。

二.驱动程序

#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int

sbit IO=P3^4;  //数据输入输出线
sbit RST=P3^5;  //复位信号线
sbit SCLK=P3^6;   //时钟信号线

uchar code write_addr[]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};   //写的地址
uchar code read_addr[]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};   //读的地址

//---存储顺序是秒分时日月周年,存储格式是用BCD码---//
uchar time[7]={0,0,0x12,0x12,0x12,0x20,0x15};  //初始化的时间为2015年12月12日12:00

1.初始化

void ds1302_init()
{
   uchar k;
   write(0x8e,0x00);  //禁止写保护,即允许数据写入
   for(k=0;k<7;k++)   //写入7个字节的时钟信号:分秒时日月周年
   {
     write(write_addr[k],time[k]);
   }
   write(0x8e,0x80);  //打开写保护
}

2.写字节

void write(uchar addr,uchar dat)
{
   uchar i,j;
   SCLK=0;       
   _nop_();
   RST=0;        
   _nop_();
   RST=1;             //拉高,准备写地址写数据
   _nop_();
   _nop_(); 
   for(i=0;i<8;i++)   //传送8位地址,往哪里写
   {
      SCLK=0;        //再置为低,以便实现上升沿 
      _nop_();
      IO=addr&0x01;   //先传送最低位
      addr>>=1;       //向右移位,把8位数据依次写入
      SCLK=1;         //数据在上升沿时,写入数据
      _nop_();    
   }
   for(j=0;j<8;j++)  //写入8位数据
   {
      SCLK=0;        //置为低,以便实现上升沿
      _nop_(); 
      IO=dat&0x01;   //先传送最低位
      dat>>=1;       //向右移位,把8位数据依次写入
      SCLK=1;        //数据在上升沿时,写入数据
      _nop_();
   }
    RST=0;          //释放
   _nop_();
}

3.读字节

uchar read(uchar addr)
{
    uchar i,dat=0;
   SCLK=0;
   _nop_();
   RST=0;
   _nop_();
   RST=1;               //拉高,准备写地址读数据
   _nop_();
   _nop_();
   for(i=0;i<8;i++)     //传送8位地址,从哪里读
   {
      SCLK=0;           //置为低,以便实现上升沿
      _nop_();
      IO=addr&0x01;     //先传送最低位
      addr>>=1;         //向右移位,把8位数据依次写入
      SCLK=1;           //数据在上升沿时,写入数据
      _nop_();
   }
   _nop_();
   for(i=0;i<8;i++)     //读出8位数据
   {  
      SCLK=1;           //置为低,以便实现下降沿
      _nop_();
      dat>>=1;          //向右移位,把8位数据依次读出
      if(IO==1)
        dat=dat|0x80;         
      SCLK=0;          //读数据时,下降沿有效
      _nop_();     
   }
   RST=0;              //复位
   _nop_();
   SCLK = 1;
   _nop_();
   IO = 0;
   _nop_();
   IO = 1;
   _nop_();
   return dat;         //返回读到的数据
}

4.读时间

void read_time()
{
   uchar n;
   for(n=0;n<7;n++)
    time[n]=read(read_addr[n]);   //读取分秒时日月周年
}

注:在主函数里调用ds1302_init()函数进行初始化,然后一直调用read_time()即可获取实时的时间,并显示出来。

你可能感兴趣的:(单片机,ds1302,实时时钟)