51单片机操作DS1302时钟芯片

DS1302通过3根线与MCU连接串行数据发送,接收时钟信号由MCU发送,可外接备用电池以便主电源断电后不丢失数据,并可编程对备用电源充电。

DS1302的结构如下



 外部结构


内部结构:



 
 对DS1302的操作一般只有两种:读数据和写数据

读数据即读出芯片RAM中的日期,时间等信息,写数据即修改这些信息。

数据的读写是以字节为单位操作的,

读操作函数要完成的功能便是传入一个一字节表示特定的地址,函数返回该地址RAM中一字节或多字节的数据。

写操作函数需要传入两个参数:地址和要写的数据;函数将要写的一字节数据写入给定的地址。

对于同一个内容,读和写通过地址中一个标志位来区分,因此表现出来就是读和写的地址不一样,这样芯片通过地址来区分你是要还是要写;例如读秒的地址是0x81,而写秒的地址是0x80;

因此我们首先就要写读数据和写数据的两个函数

首先要分析读操作的时序



 CE,SCLK,I/O是单片机与DS1302连接的三条线,要进行读操作,首先把CE和SCLK置0,准备读数据。

CE是使能信号,只有他为高才能进行操作。读数据操作实际上是先写后读的操 作,因为要先写入地址,然后读该地址的数据。图中带箭头的脉冲跳变表示起作用的脉冲跳变,因此读数据时上升沿有效,即SCLK从0变1的瞬间,I/O线上 的数据就会被写入DS1302。而读出是下降沿有效,即DS1302会在每个下降沿的时候修改数据线上的数据,因此,从此刻到下一个下降沿的这段时间 内,MCU读数据线上的数据都是正确的。

要注意MCU写完一个字节后第一个下降沿DS1302就开始送出数据了读写都是从低位到高位

所以就可以写程序了

C代码  收藏代码
  1. /********读DS1302,1字节**********/  
  2. uchar DS1302Read(uchar add)  
  3. {   uchar a, d=0;  
  4.     TCE = 0;  
  5.     TCLK = 0;  
  6.     TCE=1;  
  7.     for(a=0; a<8; a++)   //发送控制字节  
  8.     {  
  9.         TCLK=0;  
  10.         TIO= add & 0x01;  
  11.         TCLK=1;//制造上升沿  
  12.         add>>=1;  
  13.     }  
  14.     for(a=0; a<8; a++)   //读1字节数据  
  15.     {  
  16.         TCLK=1;  
  17.         d >>= 1;//右移1位  
  18.         TCLK=0;//制造下降沿  
  19.         if(TIO) {//如果读到1  
  20.             d |= 0x80;//把最高位置1  
  21.         }  
  22.     }  
  23.     TCE=0;              //拉低TCE  
  24.     //return dec(d);        //读取的数据转换成十进制  
  25.   return d;  
  26. }  

 

 

 

 写数据简单,一次性把两个字节全部写进去就行了



 写数据程序

C代码  收藏代码
  1. /*******向DS1302写入一字节数据*********/  
  2. void DS1302Write(uchar add,uchar d)  
  3. {  
  4.     uchar a;  
  5.     //d = hex(d);   //转换为BCD码  
  6.     TCE=0;      //拉低TCE引脚,终止数据传输  
  7.     TCLK=0;     //拉低TCLK引脚,清零时钟线  
  8.     TCE=1;      //拉高TCE引脚,所有数据传输都要拉高TCE脚,启动控制逻辑  
  9.     //先写入控制字节  
  10.     for(a=0; a<8; a++)  
  11.     {  
  12.         TIO= add & 0x01;    //TIO引脚准备好要写入的1位数据  
  13.         TCLK=1;             //TCLK上升沿,1位数据从TIO脚写入,低位先写入  
  14.         add>>=1;          //数据右移1位  
  15.         TCLK=0;             //拉低TCLK,为下次写入准备,循环8次写入1字节  
  16.     }  
  17.     //再写入数据字节  
  18.     for(a=0; a<8; a++)  
  19.     {  
  20.         TIO= d & 0x01;  
  21.         TCLK=1;  
  22.         d>>=1;  
  23.         TCLK=0;  
  24.     }  
  25.     TCE=0;      //数据传输完拉低TCE  
  26. }  

 

 有了读数据和写数据功能,就成功了一半了,接下来就是要搞懂每个地址所对应数据的结构和含义

首先是与时间有关的,一般也就操作这些寄存器就可以读写时间



 

 前两栏是地址,后面是各位所代表的含义:例如秒寄存器的最后一位bit7叫CH表示暂停时钟的,比如说用代码

C代码  收藏代码
  1. write1302(0x80,0x80) //写1000 0000  

 

这样就把地址为0x80寄存器的CH位置为1,其他位为0,这样的操作就使时钟暂停了,并且秒也置为0

但是单这样操作是不能修改数据的,DS1302只有地址为0x8e的WP即写保护开关可以随意修改,其他数据要在写保护开关关闭时才能写,如

C代码  收藏代码
  1. write1302(0x8e,0x00)//关闭写保护   
  2. write1302(0x80,0x01)//秒置为1  
  3.  write1302(0x8e,0x80)//打开写保护  

 

 另外使用寄存器0xbf/0xbe可以批量读写数据


如果备用电池是充电电池或者电容,可以通过寄存器90h设置涓流充电二极管(1~2个)和电阻(2k,4k,8k)可选,

要充电的话高四位必须是1010,低四位选择二极管和电阻



 控制方式



 只有这六种控制方式,只要不在这六中之内,则断电。

从表中可以看到,我们从寄存器取得的时分秒等信息不能直接使用,因为它的高四位一般代表一位代表10,而低四位代表1,也就是用BCD码表示的。如代表年的寄存器高四位以为就代表10年,而第四位只代表1年,所以在写入的时候和读取的时候还要做一些转换。

 

 

C代码  收藏代码
  1. #define hex(dat) (dat / 10 * 16 + (dat % 10)) //十进制转BCD码   
C代码  收藏代码
  1. #define dec(dat) ((dat >> 4)* 10 + (dat & 0x0f)) //BCD码转十进制   

 

 

所以,如果要在秒寄存器中写入23,可以直接写入0x23,

也可以使用上面写的预处理函数hex(23),效果一样(hex(23)的作用就是把23转换成0x23)。

 

 

 

 

 

posted @ 2013-03-18 20:10  天涯海角路  阅读(3319)  评论(0)    收藏  举报