虽然程序大部分是一个网友的(我只改了3个函数),思路也是别人的。可是看在我搞了1天的份上面还是算原创吧,o(∩_∩)o...

注意那个IO口要和电源间接个电阻哦,还有我的外接电源用的手机电池,为这个去买充电电池不划算的

  1.    
  2. # include <AT89x52.h>  
  3. /***************************************** 
  4.          P0------DB0~DB7          
  5.    P1.0------RS 
  6.    P1.1------RW 
  7.    P1.2------E 
  8. *****************************************/  
  9. # define LCD_DB        P0  
  10.   sbit         LCD_RS=P1^0;  
  11.   sbit         LCD_RW=P1^1;  
  12.   sbit         LCD_E=P1^2;  
  13.   sbit         DS1302_SCLK = P3^4;  
  14.   sbit         DS1302_IO   = P3^3;  
  15.   sbit         DS1302_RST  = P3^5;  
  16.   //定义待设置的时间:秒、分、时、日、月、星期、年、控制字  
  17.   char table[]={0x00,0x58,0x12,0x8,0x3,0x06,0x06,0x00};  
  18.   char table1[]={0x11};  
  19.   char table2[]={0x22};  
  20.   unsigned char bdata time_rx ;  
  21.   sbit     time_rx7 = time_rx^7;  
  22. /******定义函数****************/  
  23. # define uchar unsigned char  
  24. # define uint unsigned int  
  25.   
  26. void LCD_init(void);//初始化函数  
  27. void LCD_write_command(uchar command);//写指令函数  
  28. void LCD_write_data(uchar dat);//写数据函数  
  29. void LCD_disp_char(uchar x,uchar y,uchar dat);//在某个屏幕位置上显示一个字符,X(0-16),y(1-2)  
  30. void delay_n40us(uint n);//延时函数  
  31.   //写一个字节数据函数  
  32. void time_write_1(unsigned char time_tx)  
  33. {  
  34.      int j;                             //设置循环变量  
  35.      for(j=0;j<8;j++)                   //连续写8bit  
  36.        {  
  37.          DS1302_IO    =  0;                         //先设置数据为0  
  38.          DS1302_SCLK  =  0;                        //时钟信号拉低  
  39.          if(time_tx&0x01)               //判断待发送的数据位是0或1  
  40.          {  
  41.              DS1302_IO = 1;                     //待发送数据位是1  
  42.          }  
  43.          time_tx=time_tx>>1;            //待发送的数据右移1位  
  44.          DS1302_SCLK = 1;                        //拉高时钟信号  
  45.         }  
  46.          DS1302_SCLK = 0;                          //写完一个字节,拉低时钟信号  
  47.    }  
  48. //---------------------------------------------  
  49. //读一个字节函数  
  50. unsigned char time_read_1()  
  51. {  
  52.     int j;                             //设置循环变量  
  53.     
  54.    
  55.  DS1302_IO = 1;        //设置为输入方式  
  56.     for(j=0;j<8;j++)                   //连续读取8bit  
  57.     {  
  58.          DS1302_SCLK  = 0;                       //拉低时钟信号  
  59.          time_rx=time_rx>>1;           //接收寄存器右移1位  
  60.          time_rx7=DS1302_IO;          //把接收到的数据放到接收寄存器的最高位  
  61.          DS1302_SCLK = 1;                        //拉高时钟信号  
  62.        }  
  63.        
  64.      DS1302_SCLK = 0;                           //拉低时钟信号  
  65.      return(time_rx);                  //返回读取到的数据  
  66.  }  
  67.    
  68. //DS1302初始化函数  
  69. void ds1302_init()  
  70. {  
  71.     DS1302_SCLK  =   0;                             //拉低时钟信号  
  72.     DS1302_RST   =   0;                             //复位DS1302  
  73.     DS1302_RST   =   1;                             //使能DS1302  
  74.     time_write_1(0x8e);                              //发控制命令  
  75.     time_write_1(0);                                  //允许写DS1302  
  76.    
  77.     DS1302_RST   =   0;                              //复位  
  78.  }  
  79. //---------------------------------------------  
  80.  //---------------------------------------------  
  81. //设置时间函数  
  82. void set_time()  
  83. {  
  84.     int i;                              //定义循环变量  
  85.     DS1302_RST = 1;                     //使能DS1302  
  86.     time_write_1(0xbe);                 //时钟多字节写命令  
  87.     for(i=0;i<8;i++)                    //连续写8个字节数据  
  88.     {  
  89.         time_write_1(table[i]);         //调用写一个字节函数  
  90.     }  
  91.     DS1302_RST = 0;                              //复位  
  92. }  
  93. //---------------------------------------------  
  94.    
  95.   
  96. //---------------------------------------------  
  97. //设置是否初始化标志  
  98. void set_ytime()  
  99. {  
  100.      
  101.     DS1302_RST = 1;                              //使能DS1302  
  102.     time_write_1(0xc0);                 //时钟多字节写命令  
  103.      
  104.     time_write_1(table1[0]);         //调用写一个字节函数  
  105.       
  106.     DS1302_RST = 0;                              //复位  
  107. }  
  108. //读取初始化标志函数  
  109. void get_ytime()  
  110. {  
  111.       
  112.     DS1302_RST = 1;                              //使能DS1302  
  113.     time_write_1(0xc1);                 //发送多字节读取命令  
  114.       
  115.     table2[0]=time_read_1();       //调用读取1个字节数据的函数  
  116.        
  117.     DS1302_RST = 0;                             //复位DS1302  
  118. }  
  119. //---------------------------------------------  
  120.    
  121.    
  122. //读取时间函数  
  123. void get_time()  
  124. {  
  125.     int i;                              //设置循环变量  
  126.     DS1302_RST = 1;                              //使能DS1302  
  127.     time_write_1(0xbf);                 //发送多字节读取命令  
  128.     for(i=0;i<7;i++)                    //连续读取7个字节数据  
  129.       {  
  130.          table[i]=time_read_1();       //调用读取1个字节数据的函数  
  131.       }  
  132.     DS1302_RST = 0;                             //复位DS1302  
  133. }  
  134.   
  135. //*******初始化函数***************  
  136. void LCD_init(void)  
  137. {  
  138.     delay_n40us(10000);  
  139.     LCD_write_command(0x38);//设置8位格式,2行,5x7  
  140.     LCD_write_command(0x38);//设置8位格式,2行,5x7  
  141.     LCD_write_command(0x38);//设置8位格式,2行,5x7  
  142.       
  143.  LCD_write_command(0x02);//整体显示,关光标,不闪烁  
  144.  LCD_write_command(0x0C);//清除屏幕显示  
  145.     LCD_write_command(0x06);//设定输入方式,增量不移位  
  146. }  
  147. //********************************  
  148. //********写指令函数************  
  149. void LCD_write_command(uchar dat)  
  150. {  
  151.       
  152.     LCD_E = 0;  
  153.    
  154.  LCD_RS=0;//指令  
  155.     LCD_RW=0;//写入  
  156.     LCD_DB=dat;  
  157.    
  158.  LCD_E=1;//允许  
  159.  delay_n40us(10);//实践证明,我的LCD1602上,用for循环1次就能完成普通写指令。  
  160.     LCD_E = 0;  
  161. }  
  162. //*******************************  
  163. //********写数据函数*************  
  164. void LCD_write_data(uchar dat)  
  165. {  
  166.      LCD_E = 0;      
  167.   LCD_RS=1;//数据  
  168.      LCD_RW=0;//写入  
  169.      LCD_DB=dat;  
  170.     
  171.   LCD_E=1;//允许  
  172.      delay_n40us(10);  
  173.        
  174.   LCD_E = 0;  
  175. }  
  176. //********************************  
  177. //*******显示一个字符函数*********  
  178. void LCD_disp_char(uchar x,uchar y,uchar dat)  
  179. {  
  180.   uchar address;  
  181.      if(y==1)  
  182.               address="0x80"+x;  
  183.      else  
  184.               address="0xc0"+x;  
  185.      LCD_write_command(address);  
  186.      LCD_write_data(dat);  
  187. }  
  188.    
  189. void delay_n40us(uint n)  
  190. {      
  191.        uint i;  
  192.       uchar j;             
  193.         for(i=n;i>0;i--)  
  194.            for(j=0;j<15;j++)  
  195.             ;          //  
  196. }                                         //  
  197. //*******************************  
  198. void disp_time()  
  199. {  
  200.     LCD_disp_char(3,1,((table[2]&0xf0)>>4)+0x30);   
  201.    
  202.  LCD_disp_char(4,1,(table[2]&0x0f)+0x30);  
  203.    
  204.  LCD_disp_char(5,1,':');  
  205.    
  206.  LCD_disp_char(6,1,((table[1]&0xf0)>>4)+0x30);   
  207.    
  208.  LCD_disp_char(7,1,(table[1]&0x0f)+0x30);  
  209.    
  210.    
  211.  LCD_disp_char(8,1,':');  
  212.  LCD_disp_char(9,1,((table[0]&0xf0)>>4)+0x30);   
  213.    
  214.  LCD_disp_char(10,1,(table[0]&0x0f)+0x30);  
  215.    
  216.   
  217. }  
  218. //*********主函数*****************  
  219. void main(void)  
  220. {         
  221.       
  222.   get_ytime();  
  223.          
  224.   if(table2[0]==0x11)  
  225.       {  
  226.     ;  
  227.       }  
  228.     else  
  229.    {  
  230.       ds1302_init();                    //调用DS1302初始化函数  
  231.           
  232.          set_time();                       //调用设置时间函数   
  233.       set_ytime();                       //调用设置标志函数  
  234.    }  
  235.      
  236.      
  237.          DS1302_RST   =   1;                             //使能DS1302  
  238.         time_write_1(0x90);                 //充电命令  
  239.      
  240.         time_write_1(0xa5);         //打开充电二级管  一个二级管串联一个2K电阻  
  241.      DS1302_RST   =   0;                             //复位DS1302   
  242.          
  243.    
  244.       
  245.   LCD_init();  
  246.         while(1)  
  247.   {  
  248.      get_time();                  //调用取时间函数  
  249.        
  250.      disp_time();  
  251.        
  252.    }  
  253.           
  254. }  


这是我接触到的第一个时钟芯片,编写这个时间模块程序,可是费了不少周折,这里will666博客里面有芯片资料http://blog.ednchina.com/will666/49952/message.aspx

 

使用的时候,S7偏上的两个脚要连起来,S8也是。这个不难,看wangjin博客上面有电路图,不过WILL66上面S7、S8那个接口图把ps2和时钟标反了。

如果你的还是不能正常显示,显示什么85呀,??呀,o(∩_∩)o...,那就在时钟芯片的IO脚与VCC之间接个上拉电阻吧。1K或者4.7K的都行(我自己是接的一个滑动变阻器)http://group.ednchina.com/329/3374.aspx

 

调试程序就不帖了,在小组里面找找哦。

还有那个备用电源VCC1可以不接,只是每次开机了上次的时间不会保持,如果要接的话,从资料上面看,要接那种可以充电的电池,因为资料上面说平时VCC2对VCC1充电,当VCC2电压比较低了就用VCC1的电源,就是类似于电脑主板上面的那个电池一样的。

下面是引用一个网友的资料,就是外接电源后,为什么时间还是没有保持的问题,o(∩_∩)o...,因为你每次开机都把时钟芯片初始化了呀。

关于DS1302的初始化也是有技巧的,这是一个可以带备用电池的芯片,放上电池,即使把电源关了,它的时间还是在走的,呵呵,和电脑一样呀!这样 的话,如果它的备用电池不断电,就不用再对它初始化啦,也就是说一辈子不断电,这一辈子它只要初始化一次就行了,但是单片机如果断电再通电,程序又会从头 开始执行,又会执行它的初始化程序,我开始以为只要不破坏它的时钟数据就行,单片机开机时先读一次时钟数据,然后把控制字叠加进去,再写回去就好了,可试 验了好几次都不行,每次都是小时的数据不对了。于是在DS1302暂存RAM中设立一个标志位,只要备用电池不断电,标志就不会消失,每次通电开机时,单 片机检测到这个标志就不再对其初始化,呵呵,一切正常。

posted on 2013-03-19 21:07  爱哎唉  阅读(121)  评论(0)    收藏  举报