ds1302

来源:互联网 发布:重装系统数据恢复 编辑:程序博客网 时间:2024/05/18 21:07
原文地址:ds1302作者:面包会有的

DS1302是 DALLAS 公司推出的涓流充电时钟芯片,内含一个实时时钟/日历和31字节静态RAM,可以通过串行接口与单片机进行通信,仅需三根I/O线:复位(RST)、I/O数据线、串行时钟(SCLK),(补充一点小知识:一般来讲,无论是哪种同步通讯类型的串行接口,都是对时钟信号敏感的,而且一般数据写入有效是在上升沿,读出有效是在下降沿)。要想与ds1302通讯,就必须先了解它的控制字,[转载]ds1302如图所示,控制字的最高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入到DS1302中;位6:如果为0,则表示存取日历时钟数据,为1表示存取 RAM数据;位5至位1(A4~A0):指示操作单元的地址;位0(最低有效位):如为0,表示要进行写操作,为1表示进行读操作。控制字总是从最低位开始输出。在控制字指令输入后的下一个SCLK时钟的上升沿时,数据被写入 DS1302,数据输入从最低位(0位)开始。同样,在紧跟8位的控制字指令后的下一个 SCLK脉冲的下降沿,读出 DS1302的数据,读出的数据也是从最低位到最高位。

程序还有些地方看不懂,就是关于写操作时CLK应该是上升沿,但此程序是下降沿,而且运行良好,改成上升沿反而不对了,很不理解,etc.

现在介绍下主要的几块程序:

void v_RTInputByte(ucharucDa)       //输入-写操作
{
  uchar i;
  ACC=ucDa;//待写数据送给ACC
  for(i=8;i>0;i--)
 {
  if((ACC&0x01)==1) //ACC最后1位为1
   T_IO=1;
   elseT_IO=0;//if((ACC&0x01)==0)
   T_CLK=1;
   T_CLK=0;//不是上升沿写吗?
   ACC=ACC>>1;
 }
}

ucharuc_RTOutputByte(void)         //输出-读操作
{
  uchar i,ACC;
  ACC=0;//ACC清0
  for(i=0;i<8;i++)
 {
  ACC=ACC>>1;  

   if(T_IO==1)
   ACC=ACC|0x80;//ACC第1位置1
   T_CLK=1;
   T_CLK=0; //下降沿
 }
 return(ACC);//返回ACC
}

 

void v_W1302(uchar ucAddr,ucharucDa)    //指定地址写数据
{
 T_RST=0;
 T_CLK=0;
 T_RST=1;
 v_RTInputByte(ucAddr); //写地址

 v_RTInputByte(ucDa);   //写数据
 T_CLK=1;
 T_RST=0;
}

 

uchar uc_R1302(ucharucAddr)    //指定地址读数据
{
 unsigned char ucDa,k; //BCD转换成16进制
 k=0x00;
 T_RST=0;
 T_CLK=0;
 T_RST=1;
 v_RTInputByte(ucAddr); 
 ucDa=uc_RTOutputByte();
 T_CLK=1;
 T_RST=0;

 k=ucDa/16;
 ucDa=ucDa;
 ucDa=ucDa+k*10;//16进制转化为10进制

 return(ucDa);
}

以上就是对ds1302的给定地址读写操作了,下面是显示初始值的设定和记录时间子程序

void v_Set1302()//uchar*pSecDa)   设置初始时间值
{
  uchar i,j;
  ucharucAddr=0x80;    // 秒写地址
  v_W1302(0x8e,0x00);   // 控制命令,WP=0,写操作
  for(i=0;i<7;i++)      // 连续写入7个时间
 {
  j=ucCurtime[i];   // 代入初始时间
   v_W1302(ucAddr,j); // 秒 分时  
   ucAddr+=2;       // 地址+2,因为都是两位数
 }
 v_W1302(0x8e,0x80);   // 控制命令,WP=1,写保护
}

 

voidv_Get1302()          // 记录时间
{
  uchar i;
  ucharucAddr=0x81;    // 秒读地址
  for(i=0;i<7;i++)     // 连续读数据
 {
   ucCurtime[i]=uc_R1302(ucAddr);//格式为:秒 分 时 

   ucAddr+=2;
 }
}

然后是数码管显示内容和显示设置

void t2_10()        //数码管段数字显示内容
{
 unint k;
 a[5]=temp1/10;
 a[4]=temp1;
 a[3]=temp/1000;
 k=temp00;
 a[2]=k/100;
 k=k0;
 a[1]=k/10;
 a[0]=k;
}

voiddisplay2()        //显示设置
{
 t2_10();

 wei_1(0x7f);   //秒(两位)
 duan_1(a[0]);
 wei_1(0xbf);
 duan_1(a[1]);

 

 wei_1(0xdf);   
 duan_1(10);

 

 wei_1(0xef);  
 duan_1(a[2]);
 wei_1(0xf7);
 duan_1(a[3]);

 

 wei_1(0xfb);   
 duan_1(10);

 

 wei_1(0xfd);  
 duan_1(a[4]);
 wei_1(0xfe);
 duan_1(a[5]);

 

 wei_1(0xff);  
}

然后是主程序

void main()
{
 unint i,k;
 for(i=0;i<7;i++)      //将10进制转换成16进制
 {
  k=ucCurtime[i]/10;
  ucCurtime[i]=ucCurtime[i];
  ucCurtime[i]=ucCurtime[i]+16*k;
 }
 v_Set1302();          //时间初值
 while(1)

 {

  v_Get1302();                             //记录时间
  temp1=ucCurtime[2];                      //时
  temp=ucCurtime[1]*100+ucCurtime[0];      //分+秒
  display2();                              //显示

 }
}

这个程序是比较综合的除了中断没用到,其他的基本都用到了,其实若加进去整点报时或闹铃设置就更全面了,想着以后用1602做个时钟加进去这两个功能,试试吧。

原创粉丝点击