找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6586|回复: 14
打印 上一主题 下一主题
收起左侧

如何将DS1302的时间数据存入AT24C02中,再调用出来显示在LCD12864上?单片机小白求问

[复制链接]
跳转到指定楼层
楼主
我这边可以将数据写入AT24C02中,这证明我的模块不是坏的。我现在想把DS1302的时间先存入AT24C02,然后再调用出来显示在液晶屏上。我写了以下代码,还是不行。能帮我看一下吗?
  1. unsigned char table4[9]={'0','0',':','0','0',':','0','0','\0'};
  2. void display_time()
  3. {
  4.                uchar num,tmp0,tmp1,tmp2;
  5.                 uchar Second,Min,Hour;
  6.                 uchar Second0,Min0,Hour0;
  7.                 uchar Second1,Min1,Hour1;
  8.                 EEPROM_Software_Reset();
  9.         
  10.                 Second = ds1302_read(0x81);//读秒
  11.                 Min    = ds1302_read(0x83);//读分
  12.                 Hour   = ds1302_read(0x85);//读时
  13.         
  14.                 EEPROM_Byte_Write(0xa0,0x00,Second);
  15.                 EEPROM_Byte_Write(0xb0,0x00,Min);
  16.                 EEPROM_Byte_Write(0xc0,0x00,Hour);
  17.         
  18.                 tmp0 = EEPROM_CurrentAddr_Read(0xa1);
  19.                 tmp1 = EEPROM_CurrentAddr_Read(0xb1);
  20.                 tmp2 = EEPROM_CurrentAddr_Read(0xc1);
  21.         
  22.                 Second0 = (tmp0 & 0x0f) + 0x30;//秒的个位
  23.                 Second1 = ((tmp0 & 0x7f) >> 4) + 0x30;//秒的十位
  24.                 Min0 = (tmp1 & 0x0f) + 0x30;//分的个位
  25.                 Min1 = ((tmp1& 0x7f) >> 4) + 0x30;//分的十位
  26.                 Hour0 = (tmp2 & 0x0f) + 0x30;//秒的个位
  27.                 Hour1 = ((tmp2 & 0x7f ) >> 4) + 0x30;//时的十位

  28.                 table4[6]= Second1;
  29.                 table4[7]= Second0;

  30.                 table4[3]= Min1;
  31.                 table4[4]= Min0;
  32.         
  33.                 table4[0]= Hour1;
  34.                 table4[1]= Hour0;
  35.         
  36.                 lcd_pos(3,1); //显示在第四行第2个字符
  37.                 for(num=0;num<8;num++)//显示长度
  38.                 {
  39.                         lcd_wdat(table4[num]);
  40.                 }        
  41. }


  42. //////////////////AT24C02//////////////////
  43. void EEPROM_Software_Reset(void)
  44. {
  45.         uchar i;
  46.         IIC_Start();
  47.         //9 clocl
  48.         scl = 0;
  49.         sda = 1;
  50.         for(i=0;i<9;i++)
  51.         {
  52.                 scl = 0;
  53.                 _nop_();//delay
  54.                 _nop_();
  55.                 scl = 1;
  56.                 _nop_();//delay
  57.                 scl = 0;
  58.                 _nop_();//delay
  59.                 _nop_();
  60.   }
  61.         IIC_Start();
  62.         IIC_Stop();
  63. }

  64. void IIC_Start(void)
  65. {
  66.         scl = 0;
  67.         sda = 1;
  68.         scl = 1;
  69.         _nop_();
  70.         sda = 0;
  71.         nop_();
  72. }

  73. void IIC_Stop(void)
  74. {
  75.         scl = 0;
  76.         sda = 0;
  77.         scl = 1;
  78.         _nop_();
  79.         sda = 1;
  80. }

  81. void IIC_Write_Byte(uchar dataSend)
  82. {
  83.         uchar i;
  84.         for(i=0;i<8;i++)
  85.         {
  86.                 scl = 0;
  87.                 if(dataSend & 0x80)sda = 1;//′ó×î¸ßλ¿aê¼D′
  88.                 else sda = 0;
  89.                 _nop_();
  90.                 scl = 1;
  91.                 _nop_();
  92.                 scl = 0;
  93.                 _nop_();
  94.                 dataSend <<= 1;
  95.         }
  96. }

  97. uchar IIC_Read_Byte(void)
  98. {
  99.         uchar dataRead,i;
  100.         for(i=0;i<8;i++)
  101.         {
  102.                 dataRead <<= 1;
  103.                 scl = 0;
  104.                 sda = 1;
  105.                 _nop_();
  106.                 _nop_();
  107.                 scl = 1;
  108.                 _nop_();
  109.                 if(sda)dataRead |= 0x01;
  110.                 _nop_();
  111.                 scl = 0;
  112.                 _nop_();
  113.                 _nop_();
  114.         }
  115.         return dataRead;
  116. }

  117. bit IIC_Ack(void)
  118. {
  119.                 bit flag;
  120.                 scl = 0;
  121.                 sda = 1;
  122.                 _nop_();
  123.                 _nop_();
  124.                 scl = 1;
  125.                 _nop_();
  126.                 flag = sda;//¶áSDA
  127.                 _nop_();
  128.                 scl = 0;
  129.                 _nop_();
  130.                 _nop_();
  131.                 return flag;
  132. }


  133. void IIC_NoAck(void)
  134. {
  135.                 scl = 0;
  136.                 sda = 1;
  137.                 _nop_();
  138.                 _nop_();
  139.                 scl = 1;
  140.                 _nop_();
  141.                 _nop_();
  142.                 scl = 0;
  143.                 _nop_();
  144.                 _nop_();
  145. }

  146. void EEPROM_Byte_Write(uchar devAddr,uchar wordAddr,uchar dataSend)
  147. {
  148.   IIC_Start();
  149.         IIC_Write_Byte(devAddr);
  150.         IIC_Ack();
  151.         IIC_Write_Byte(wordAddr);
  152.         IIC_Ack();
  153.         IIC_Write_Byte(dataSend);
  154.         IIC_Ack();
  155.         IIC_Stop();
  156.         Delay5ms();
  157. }

  158. uchar EEPROM_CurrentAddr_Read(uchar devAddr)
  159. {
  160.                 uchar dataRead;
  161.                 IIC_Start();
  162.                 IIC_Write_Byte(devAddr);
  163.                 IIC_ACK();
  164.                 dataRead = IIC_Read_Byte();
  165.                 IIC_NoACK();
  166.                 ICC_Stop();
  167.                 return dataRead;
  168. }
复制代码


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:313294 发表于 2018-4-21 18:53 | 只看该作者
为什么要放到24c02?直接显示不好么,我这里有各自的驱动,你要吗??
回复

使用道具 举报

板凳
ID:111634 发表于 2018-4-21 19:12 | 只看该作者
这个问题分2部分,读写24c02和12864显示,分别弄懂,然后拼起来。
回复

使用道具 举报

地板
ID:296557 发表于 2018-4-21 20:32 | 只看该作者
huitata 发表于 2018-4-21 18:53
为什么要放到24c02?直接显示不好么,我这里有各自的驱动,你要吗??

感谢您的回复。ds1302的数据直接显示在12864上面这一部分我已经实现了。我现在需要的是将ds1302读到的秒数据写入at24c02中。
ds1302读到的数据是否要经过转换才能存进at24c02中?
回复

使用道具 举报

5#
ID:296557 发表于 2018-4-21 20:36 | 只看该作者
zl2168 发表于 2018-4-21 19:12
这个问题分2部分,读写24c02和12864显示,分别弄懂,然后拼起来。

您好,感谢您的回复。
首先我将0x55这单个数据存入12864是可以显示出来的,但是我将ds1302读到的数据存进at24c02中就不行,应该是没有存进,在12864上显示“7?”这个乱码,这个乱码像是没把ds1302接进电路读出来的是一样的。
我在想ds1302的数据要存进at24c02是不是得先经过转换?
回复

使用道具 举报

6#
ID:111634 发表于 2018-4-22 11:09 | 只看该作者
本帖最后由 zl2168 于 2018-4-22 11:10 编辑

介绍你一个读写24c02案例。
实例49  读写AT24C02

Proteus仿真一下,确认有效。 实例49 读写IIC AT24C02.rar (38.96 KB, 下载次数: 56)
以上摘自张志良编著《80C51单片机仿真设计实例教程——基于Keil CProteus》清华大学出版社ISBN 978-7-302-41682-1内有常用的单片机应用100案例,用于仿真实验操作,电路与程序真实可靠可信可行。书中电路和程序设计有详细说明,程序语句条条有注解。
回复

使用道具 举报

7#
ID:111634 发表于 2018-4-22 11:13 | 只看该作者
实例50  非零地址读写AT24C02
实例50 非零地址读写AT24C02.rar (39.09 KB, 下载次数: 30)

回复

使用道具 举报

8#
ID:313294 发表于 2018-4-22 14:01 | 只看该作者
LIN595 发表于 2018-4-21 20:32
感谢您的回复。ds1302的数据直接显示在12864上面这一部分我已经实现了。我现在需要的是将ds1302读到的秒 ...

一位位的存,不需要转换的
回复

使用道具 举报

9#
ID:296557 发表于 2018-4-22 16:11 | 只看该作者
huitata 发表于 2018-4-22 14:01
一位位的存,不需要转换的

感谢您的回复。
我现在已经能够将数据存进AT24C02中了,但是有一个问题是,我每次存新的数据都会将旧的数据覆盖掉。那么,现在有没有一种方法可以检测如果这个字节地址(AT24C02有256个字节地址)已经存了数据了,就自动跳到下一个字节地址继续写入,这样就可以实现保存多组数据而不是只能存储一组。
比如0x01这个字节地址存了东西,下一次再往AT24C02存数据时,自动跳到0x02这个字节地址来存储数据。
付上我写的程序:

unsigned char table4[9]={'0','0',':','0','0',':','0','0','\0'};

void display_time()
{
          uchar num,tmp,tmp1,tmp2;
                uchar Second,Min,Hour;//秒分时
                EEPROM_Software_Reset();
                Second = ds1302_read(0x81);//从ds1302取秒
                Min    = ds1302_read(0x83);//从ds1302取分
                Hour   = ds1302_read(0x85);//从ds1302取时

                EEPROM_Byte_Write(0xae,0x01,Second);
                EEPROM_Byte_Write(0xae,0x00,0);//修改指针地址,CurrentAddressRead自动加1
                tmp = EEPROM_CurrentAddr_Read(0xaf);
               
                EEPROM_Byte_Write(0xae,0x02,Min);
                EEPROM_Byte_Write(0xae,0x01,0);
                tmp1 = EEPROM_CurrentAddr_Read(0xaf);
               
                EEPROM_Byte_Write(0xae,0x03,Hour);
                EEPROM_Byte_Write(0xae,0x02,0);
                tmp2 = EEPROM_CurrentAddr_Read(0xaf);
        ///////////秒///////////
                table4[6]= ((tmp & 0x7f) >> 4) + 0x30;//秒的十位
                table4[7]= (tmp & 0x0f) + 0x30;//个位
        ///////////分///////////
                table4[3]= ((tmp1 & 0x7f) >> 4) + 0x30;//分的十位
                table4[4]= (tmp1 & 0x0f) + 0x30;//个位
        ///////////时///////////
                table4[0]= ((tmp2 & 0x7f ) >> 4) + 0x30;//时的十位
                table4[1]= (tmp2 & 0x0f) + 0x30;//个位
       
                lcd_pos(3,1); //显示在第4行第2个字符
                for(num=0;num<8;num++)
                {
                        lcd_wdat(table4[num]);//显示table4
                }       
}
回复

使用道具 举报

10#
ID:111634 发表于 2018-4-22 20:08 | 只看该作者
LIN595 发表于 2018-4-22 16:11
感谢您的回复。
我现在已经能够将数据存进AT24C02中了,但是有一个问题是,我每次存新的数据都会将旧的 ...

”“我现在已经能够将数据存进AT24C02中了,但是有一个问题是,我每次存新的数据都会将旧的数据覆盖掉。那么,现在有没有一种方法可以检测如果这个字节地址(AT24C02有256个字节地址)已经存了数据了,就自动跳到下一个字节地址继续写入,这样就可以实现保存多组数据而不是只能存储一组。”“

首先,要纠正你一个错误概念。即存储器中无论是什么,都是数据,不存在有或没有的概念。
其次,存数据是需要提供地址的,你每次存在原来的单元,当然是被覆盖咯。
若要存入新单元,可设置一个地址计数器,每次存后,单元地址+1。满一定数量(例如8个),循环覆盖。
回复

使用道具 举报

11#
ID:314090 发表于 2018-4-22 22:16 | 只看该作者
你这个做的很到位
回复

使用道具 举报

12#
ID:515137 发表于 2019-4-18 06:07 来自手机 | 只看该作者
楼主可以将你这个调试好的代码给我吗?我最近也做这个,
回复

使用道具 举报

13#
ID:356167 发表于 2019-4-21 10:09 | 只看该作者
rtyyu 发表于 2019-4-18 06:07
楼主可以将你这个调试好的代码给我吗?我最近也做这个,

你做的怎么样了,我也在做这个,咱们可以交流交流
回复

使用道具 举报

14#
ID:373388 发表于 2019-4-21 11:41 | 只看该作者
DS1302读出来的秒数是10进制,不是16进制,比如读出来是 0x39 就是10进制39, 当作16进制处理就错了。
回复

使用道具 举报

15#
ID:434390 发表于 2019-4-21 18:55 | 只看该作者
读出来啥字节,就写啥字节,不用管什么进制的
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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