找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1813|回复: 4
收起左侧

为什么这样单片机读出来的DS1302时间星期是0-7呀,这个怎么去调时间0,请大佬赐教

[复制链接]
ID:894870 发表于 2021-5-2 10:20 | 显示全部楼层 |阅读模式
  1. #include "intrins.h"
  2. #ifndef _DS1302_H_
  3. #define _DS1302_H_

  4. sbit clk = P2^2;          //ds1302时钟线定义
  5. sbit io =  P2^1;          //数据线
  6. sbit rst = P2^0;          //复位线
  7.                       //秒   分    时   日   月    年   星期         
  8. uchar code write_add[]={0x80,0x82,0x84,0x86,0x88,0x8c,0x8a};   //写地址
  9. uchar code read_add[] ={0x81,0x83,0x85,0x87,0x89,0x8d,0x8b};   //读地址
  10. uchar code init_ds[]  ={0x58,0x29,0x07,0x05,0x10,0x14,0x1};   
  11. extern uchar miao,fen,shi,ri,yue,week,nian;
  12. extern uchar i;

  13. void delaynus(unsigned char n)
  14. {
  15. unsigned char i;
  16. for(i=0;i<n;i++);     
  17. }

  18. //向1302写一个字节数据
  19. void Write1302(unsigned char dat)
  20. {
  21.   unsigned char i;
  22.   clk=0;            //拉低CLK,为脉冲上升沿写入数据做准备
  23.   delaynus(2);       //稍微等待,使硬件做好准备
  24.   for(i=0;i<8;i++)      //连续写8个二进制数据
  25.     {
  26.             io=dat&0x01;    //取出dat的第0位数据写入1302
  27.             delaynus(2);       //稍微等待,使硬件做好准备
  28.             clk=1;           //上升沿写入数据
  29.             delaynus(2);      //稍微等待,使硬件做好准备
  30.             clk=0;           //重新拉低SCLK,形成脉冲
  31.             dat>>=1;          //将dat的各数据位右移1位,准备下入下一位数据位
  32.           }

  33. }

  34. /*************根据命令,向1302写一个数据到对应的地址里***************/
  35. void write_ds1302(uchar add,uchar dat)
  36. {               
  37.         rst=0;           //禁止数据传递
  38.   clk=0;          //确保写数据前CLK被拉低
  39.   rst=1;           //启动数据传输
  40.   delaynus(2);     //稍微等待,为硬件做好准备
  41.   Write1302(add);  //写入命令字
  42.   Write1302(dat);  //写数据
  43.   clk=1;          //将始终电平置于已知状态
  44.   rst=0;           //禁止数据传递
  45. }

  46. /*****************************************************
  47. 从1302读一个字节数据
  48. ***************************************************/
  49. unsigned char Read1302(void)
  50. {
  51.    unsigned char i,dat;
  52.         delaynus(2);       //稍微等待,为硬件做好准备
  53.         for(i=0;i<8;i++)   //连续读8个二进制位数据
  54.          {
  55.            dat>>=1;       //将dat的各数据位右移1位,因为先读出来的是字节的最低位
  56.            if(io==1)    //如果读出来的是1
  57.            dat|=0x80;    //将1取出,写在dat的最高位
  58.            clk=1;       //将clk置于高电平,为下降沿读出
  59.            delaynus(2);  //稍微等待
  60.            clk=0;       //拉低clk,形成脉冲下降沿
  61.            delaynus(2);  //稍微等待
  62.           }         
  63.   return dat;        //将读出来的数据返回
  64. }  

  65. /*************根据命令,从1302对应的地址读一个数据出来***************/
  66. uchar read_ds1302(uchar add)
  67. {
  68.         unsigned char dat;
  69.   rst=0;                 //拉低RST
  70.   clk=0;                //确保写数据前CLK被拉低
  71.   rst=1;                 //启动数据传输
  72.   Write1302(add);       //写入命令字
  73.   dat=Read1302();       //读出数据
  74.   clk=1;              //将时钟电平置于已知状态
  75.   rst=0;               //禁止数据传递
  76.   return dat;          //将读出的数据返回
  77. }

  78. /*************把要的时间 年月日 都读出来***************/
  79. void read_time()
  80. {
  81.         miao = read_ds1302(read_add[0]);        //读秒
  82.         fen  = read_ds1302(read_add[1]);        //读分
  83.         shi  = read_ds1302(read_add[2]);        //读时
  84.         ri   = read_ds1302(read_add[3]);        //读日
  85.         yue  = read_ds1302(read_add[4]);        //读月
  86.         nian = read_ds1302(read_add[5]);        //读年
  87.         week = read_ds1302(read_add[6]);        //读星期
  88. }

  89. /*************把要写的时间 年月日 都写入ds1302里***************/
  90. void write_time()
  91. {
  92.         write_ds1302(0x8e,0x00);                        //关闭写保护
  93.         write_ds1302(write_add[0],miao);        //写秒
  94.         write_ds1302(write_add[1],fen);                //写分
  95.         write_ds1302(write_add[2],shi);                //写时
  96.         write_ds1302(write_add[3],ri);                //写日
  97.         write_ds1302(write_add[4],yue);                //写月
  98.         write_ds1302(write_add[5],nian);        //写年
  99.         write_ds1302(write_add[6],week);        //写星期
  100.         write_ds1302(0x8e,0x80);                        //打开写保护
  101. }

  102. /*************把数据保存到ds1302 RAM中**0-31*************/
  103. void write_ds1302ram(uchar add,uchar dat)
  104. {
  105.         add <<= 1;     //地址是从第二位开始的
  106.         add &= 0xfe;   //把最低位清零  是写的命令
  107.         add |= 0xc0;   //地址最高两位为 1  
  108.         write_ds1302(0x8e,0x00);
  109.         write_ds1302(add,dat);        
  110.         write_ds1302(0x8e,0x80);
  111. }

  112. /**********************设置ds1302时间函数**********************/
  113. void set_ds1302time(uchar num,uchar *shi,uchar dat)         //调时
  114. {
  115.           if(num == 1)
  116.     {
  117.             *shi+=0x01;
  118.                 if((*shi & 0x0f) >= 0x0a)
  119.                         *shi = (*shi & 0xf0) + 0x10;
  120.                 if(*shi >= dat)
  121.                         *shi = 0;
  122.     }
  123.     else
  124.     {
  125.                 if(*shi == 0x00)
  126.                         *shi = dat;
  127.                 if((*shi & 0x0f) == 0x00)
  128.                         *shi = (*shi | 0x0a) - 0x10;
  129.                 *shi -=0x01 ;
  130.     }  
  131. }

  132. /*************把数据从ds1302 RAM读出来**0-31*************/
  133. uchar read_ds1302ram(uchar add)
  134. {
  135.         add <<= 1;     //地址是从第二位开始的
  136.         add |= 0x01;   //把最高位置1  是读命令
  137.         add |= 0xc0;   //地址最高两位为 1  
  138.         return(read_ds1302(add));        
  139. }


  140. /*************初始化ds1302时间***************/
  141. void init_ds1302()
  142. {
  143.         uchar i;
  144.         rst = 0;        //第一次读写数据时要把I O口拉低
  145.         clk = 0;
  146.         io = 0;
  147.         i = read_ds1302ram(30);   
  148.         if(i != 3)
  149.         {        
  150.                 i = 3;
  151.                 write_ds1302ram(30,i);                         //4050   4100                 3080
  152.                 write_ds1302(0x8e,0x00);                    //关闭写保护
  153.                 for(i=0;i<7;i++)
  154.                 write_ds1302(write_add[i],init_ds[i]);        //把最高位值0 允许ds1302工作
  155.                 write_ds1302(0x8e,0x80);        //打开保护
  156.         }

  157.         read_time();                  //读时间
  158.         if(miao >= 0x60)
  159.         {
  160.                 write_ds1302(0x8e,0x00);                    //关闭写保护
  161.                 write_ds1302(write_add[0],0x01);        //把最高位值0 允许ds1302工作
  162.                 write_ds1302(0x8e,0x80);        //打开保护
  163.                
  164.         }

  165. }


  166. #endif
复制代码
回复

使用道具 举报

ID:889094 发表于 2021-5-2 23:37 | 显示全部楼层
你有什么问题,想问什么?
看了你的初始化数组init_ds[i],周你初始化个0x14进去,你让1302怎么想?
各种芯片都有例程,研究一下不难
回复

使用道具 举报

ID:889094 发表于 2021-5-2 23:48 | 显示全部楼层
144./*************把数据从ds1302 RAM读出来**0-31*************/

145.uchar read_ds1302ram(uchar add)

146.{

147.        add <<= 1;     //地址是从第二位开始的

148.        add |= 0x01;   //把最高位置1  是读命令

149.        add |= 0xc0;   //地址最高两位为 1  

150.        return(read_ds1302(add));        

151.}

这个函数我没有看出来怎么退出,无限嵌套?
回复

使用道具 举报

ID:894870 发表于 2021-5-3 16:16 | 显示全部楼层
birdzhyli 发表于 2021-5-2 23:37
你有什么问题,想问什么?
看了你的初始化数组init_ds,周你初始化个0x14进去,你让1302怎么想?
各种芯 ...

周是0x1呀,我的意思是显示屏显示的时候。周是显示0-7的数字,而正常的是1-7,这个问题怎么解决
回复

使用道具 举报

ID:230742 发表于 2021-5-4 16:25 | 显示全部楼层
周是用软件换算的。
建议你直接换一个例程。重新搬一下。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表