找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 9646|回复: 12
收起左侧

利用AT24C02来保存,精华都在程序中。。。。。

  [复制链接]
ID:69862 发表于 2015-1-10 23:57 | 显示全部楼层 |阅读模式
本帖最后由 xiao_yp2014 于 2016-1-21 14:33 编辑

功能需求:
            开机后两位数码管显示0到99之间的某一个数值,用一个按键可以不断的递增,用另外一个按键可以不断的递减。断电后此数据可保存,下次通电               开机的时候还是从那个保存的数据开始显示。

程序如下:
main.c
  1. /*EEPROM篇--利用AT24C02存储数据
  2. 功能需求:
  3.         开机后两位数码管显示0到99之间的某一个数值,用一个按键可以不断的递增,
  4.             用另外一个按键可以不断的递减。断电后此数据可保存,下次通电开机的时候
  5.             还是从那个保存的数据开始显示。
  6. */

  7. #include<reg52.h>             //头文件
  8. #include"AT24C02.h"          //IIC自定义头文件
  9. #include"Key_Scan.h"         //按键自定义头文件
  10. #include"display.h"             //数码管显示自定义头文件

  11. sbit beep_dr = P3^6;         //蜂鸣器

  12. unsigned int uiVoiceCnt = 0;   //蜂鸣器时间变量
  13. unsigned char ucSetNumber = 0; //设定值变量
  14.         
  15. void Init_All();                           //初始化全部程序
  16. void Timer_T0();                      //TO定时器中断

  17. void main()
  18. {
  19.     Init_All();                               //初始化全部

  20.         while(1)
  21.         {
  22.                  display();                   //调用数码管显示函数
  23.                  Key_Service();          //调用按键服务函数,放在主函数里
  24.         }
  25. }

  26. void Init_All()
  27. {
  28.         TH0=0xf8;   //重装初始值(65535-2000)=63535=0xf82f
  29.         TL0=0x2f;
  30.         EA = 1;
  31.         ET0 = 1;
  32.         TR0=1;  //开中断

  33.         ucSetNumber = read_eeprom(128);        //上电开机读取EEPROM数据,128是一个我任意选的一个存储地址

  34.         if(ucSetNumber > 99)
  35.         {
  36.             write_eeprom(128,0); //往一个地址存入一个字节数据,128是一个我任意选的一个存储地址
  37.         }
  38. }

  39. void Timer_T0() interrupt 1
  40. {
  41.         TF0=0;  //清除中断标志
  42.         TR0=0; //关中断

  43.         Key_Scan();         //按键扫描放在中断里

  44.         if(uiVoiceCnt!=0)   //蜂鸣器
  45.         {
  46.            uiVoiceCnt--;     //每次进入定时中断都自减1,直到等于零为止。才停止鸣叫
  47.            beep_dr = 0;    //蜂鸣器是PNP三极管控制,低电平就开始鸣叫
  48.         }
  49.         else
  50.         {
  51.            beep_dr = 1;   //蜂鸣器是PNP三极管控制,高电平就停止鸣叫。
  52.         }

  53.         TH0=0xf8;        //重装初始值(65535-2000)=63535=0xf82f
  54.         TL0=0x2f;
  55.         TR0=1;             //开中断
  56. }
复制代码

AT24C02.c
  1. #include<intrins.h>
  2. #include"AT24C02.h"

  3. sbit eeprom_scl_dr  = P3^4;      //时钟线
  4. sbit eeprom_sda_dr = P3^5;      //数据输出线


  5. //AT24C02驱动程序
  6. void start24()  //开始位
  7. {
  8.     eeprom_sda_dr=1;
  9.     eeprom_scl_dr=1;
  10.     Delay_time(15);
  11.     eeprom_sda_dr=0;
  12.     Delay_time(15);
  13.     eeprom_scl_dr=0;   
  14. }


  15. void ack24()  //确认位
  16. {
  17.     eeprom_scl_dr=1;
  18.     Delay_time(15);
  19.     eeprom_scl_dr=0;
  20.     Delay_time(15);
  21. }

  22. void stop24()  //停止位
  23. {
  24.     eeprom_sda_dr=0;
  25.     eeprom_scl_dr=1;
  26.     Delay_time(15);
  27.     eeprom_sda_dr=1;
  28. }

  29. unsigned char read24()  //读取一个字节的时序
  30. {
  31.         unsigned char outdata,tempdata;

  32.         outdata=0;
  33.         _nop_();         //空指令,相当于一个机器周期
  34.             _nop_();     //空指令,相当于一个机器周期

  35.         for(tempdata=0;tempdata<8;tempdata++)
  36.         {
  37.                         eeprom_scl_dr=0;
  38.                         _nop_();         //空指令,相当于一个机器周期
  39.                         _nop_() ;         //空指令,相当于一个机器周期
  40.                         eeprom_scl_dr=1;
  41.                         _nop_() ;         //空指令,相当于一个机器周期
  42.                         _nop_() ;         //空指令,相当于一个机器周期
  43.                         outdata<<=1;
  44.                         if(eeprom_sda_dr==1)
  45.                         {
  46.                                 outdata++;
  47.                         }        
  48.                         _nop_() ;  //空指令,相当于一个机器周期
  49.                         _nop_() ;  //空指令,相当于一个机器周期
  50.         }
  51.     return(outdata);
  52.      
  53. }

  54. void write24(unsigned char dd) //发送一个字节的时序
  55. {
  56.         unsigned char tempdata;

  57.         for(tempdata=0;tempdata<8;tempdata++)
  58.         {
  59.                 if(dd>=0x80)
  60.                                 {
  61.                                      eeprom_sda_dr=1;
  62.                                 }
  63.                 else
  64.                                 {
  65.                                          eeprom_sda_dr=0;
  66.                                 }
  67.                 dd<<=1;
  68.                 _nop_() ;                 //空指令,相当于一个机器周期
  69.                 eeprom_scl_dr=1;
  70.                 _nop_() ;                 //空指令,相当于一个机器周期
  71.                                 _nop_() ; //空指令,相当于一个机器周期
  72.                                 _nop_() ; //空指令,相当于一个机器周期
  73.                                 _nop_() ; //空指令,相当于一个机器周期
  74.                 eeprom_scl_dr=0;
  75.         }
  76. }


  77. unsigned char read_eeprom(unsigned int address)   //从一个地址读取出一个字节数据
  78. {
  79.         unsigned char dd,cAddress;  
  80.         
  81.         cAddress=address; //把低字节地址传递给一个字节变量。
  82.         start24();          //开始
  83.         write24(0xA0);  //此字节包含读写指令和芯片地址两方面的内容。
  84.                                  //指令为写指令。地址为"000"的信息,此信息由A0,A1,A2的引脚决定
  85.         ack24();            //发送应答信号
  86.         write24(cAddress); //发送读取的存储地址(范围是0至255)
  87.         ack24();           //发送应答信号
  88.         start24();         //开始
  89.         write24(0xA1); //此字节包含读写指令和芯片地址两方面的内容。
  90.                                //指令为读指令。地址为"000"的信息,此信息由A0,A1,A2的引脚决定
  91.         ack24();          //发送应答信号
  92.         dd=read24(); //读取一个字节
  93.         ack24();         //发送应答信号
  94.         stop24();       //停止
  95.         Delay_time(800);  //此处最关键,此处的延时时间一定要,而且要足够长
  96.         return(dd);
  97. }

  98. void write_eeprom(unsigned int address,unsigned char dd) //往一个地址存入一个字节数据
  99. {
  100.         unsigned char cAddress;   
  101.         
  102.         cAddress=address; //把低字节地址传递给一个字节变量。
  103.         start24();             //开始
  104.         write24(0xA0); //此字节包含读写指令和芯片地址两方面的内容。
  105.                                 //指令为写指令。地址为"000"的信息,此信息由A0,A1,A2的引脚决定
  106.         ack24();           //发送应答信号
  107.         write24(cAddress);   //发送写入的存储地址(范围是0至255)
  108.         ack24();           //发送应答信号
  109.         write24(dd);     //写入存储的数据
  110.         ack24();           //发送应答信号
  111.         stop24();         //停止
  112.         Delay_time(2000);  //此处最关键,此处的延时时间一定要,而且要足够长
  113. }

  114. void Delay_time(unsigned int Delay11_MS)  
  115. {
  116.      unsigned int Delay11_us;

  117.      for(Delay11_us=0;Delay11_us<Delay11_MS;Delay11_us++)
  118.      {
  119.                 _nop_();     
  120.      }
  121. }
复制代码


AT24C02.h
  1. #ifndef __AT24C02_H__
  2. #define __AT24C02_H__

  3. #include<reg52.h>

  4. unsigned char read_eeprom(unsigned int address);   //从一个地址读取出一个字节数据
  5. void start24(); //开始位
  6. void ack24();   //确认位
  7. void stop24();  //停止位
  8. unsigned char read24();  //读取一个字节的时序
  9. void write24(unsigned char dd); //发送一个字节的时序
  10. void write_eeprom(unsigned int address,unsigned char dd); //往一个地址存入一个字节数据
  11. void Delay_time(unsigned int Delay11_MS); //延时程序  

  12. #endif
复制代码

Key_Scan.c
  1. #include"Key_Scan.h"                     //按键自定义头文件
  2. #include"AT24C02.h"                      //IIC自定义头文件

  3. #define const_KeyTimeLevel  100   //按键消抖的时间,可以修改
  4. #define const_VoiceCntLevel  150  //蜂鸣器鸣叫的时间

  5. sbit Key_s1 = P1^6;        //数据加
  6. sbit Key_s2 = P1^7;        //数据减

  7. unsigned int uiKeyTimeCnt1 = 0;          //按键延时计数器
  8. unsigned int uiKeyTimeCnt2 = 0;          //按键延时计数器
  9. unsigned char ucKeyLock1 = 0;           //按键自锁标志位,防止按键一直触发
  10. unsigned char ucKeyLock2 = 0;           //按键自锁标志位,防止按键一直触发
  11. unsigned char KeySec = 0;                  //按键编号

  12. void Key_Scan()                                  //按键扫描程序
  13. {
  14.     if(Key_s1 == 1)
  15.         {
  16.            uiKeyTimeCnt1 = 0;             //延时计数器清零
  17.            ucKeyLock1 = 0;                 //自锁标志位清零
  18.         }
  19.         else if(ucKeyLock1 == 0)         //当有按键按下
  20.         {
  21.                    uiKeyTimeCnt1++;       //延时计数器加1

  22.                  if(uiKeyTimeCnt1 >= const_KeyTimeLevel)  //去抖动时间到
  23.                  {
  24.                           uiKeyTimeCnt1 = 0;      //延时计数器清零
  25.                          ucKeyLock1 = 1;            //按键自锁
  26.                          KeySec = 1;                    //触发1号键
  27.                  }
  28.         }

  29.         if(Key_s2 == 1)
  30.         {
  31.            uiKeyTimeCnt2 = 0;                //延时计数器清零
  32.            ucKeyLock2 = 0;                    //自锁标志位清零
  33.         }
  34.         else if(ucKeyLock2 == 0)           //当有按键按下
  35.         {
  36.                    uiKeyTimeCnt2++;         //延时计数器加1

  37.                  if(uiKeyTimeCnt2 >= const_KeyTimeLevel)  //去抖动时间到
  38.                  {
  39.                           uiKeyTimeCnt2 = 0;     //延时计数器清零
  40.                          ucKeyLock2 = 1;          //按键自锁
  41.                          KeySec = 2;                 //触发2号键
  42.                  }
  43.         }

  44. }

  45. void Key_Service()                                //按键服务函数
  46. {
  47.     switch(KeySec)
  48.         {
  49.             case 0:break;
  50.                 case 1:
  51.                       ucSetNumber++;           //设定值自加1

  52.                        if(ucSetNumber >= 99)  //当加到99,就赋值成0
  53.                            {
  54.                                ucSetNumber = 0;  //赋值
  55.                            }
  56.                           write_eeprom(128,ucSetNumber); //往一个地址存入一个字节数据

  57.                       uiVoiceCnt = const_VoiceCntLevel;//蜂鸣器
  58.                           KeySec = 0;   //清零按键标志
  59.                 break;                      //跳出
  60.                      
  61.                 case 2:
  62.                       ucSetNumber--;              //设定值自减1
  63.                           if(ucSetNumber>=99) //减到大于99,赋值成99
  64.                           {
  65.                                     ucSetNumber = 99;
  66.                           }
  67.                           write_eeprom(128,ucSetNumber); //往一个地址存入一个字节数据

  68.                       uiVoiceCnt = const_VoiceCntLevel;       //蜂鸣器
  69.                           KeySec = 0;                                     //清零按键标志位
  70.                        break;

  71.                 default : break;
  72.         }
  73. }
复制代码


Key_Scan.h
  1. #ifndef __Key_Scan_H__
  2. #define __Key_Scan_H__

  3. #include<reg52.h>

  4. void Key_Scan();                               //按键扫描程序
  5. void Key_Service();                            //按键服务程序
  6. extern unsigned int uiVoiceCnt;          //变量全局声名
  7. extern unsigned char ucSetNumber;  //变量全局声名
  8. extern unsigned char ucSetNumber;  //变量全局声名extern可置于变量或者函数前,以表示变量或者函数的定义在别的文件中,
  9.                                    //提示编译器遇到此变量和函数时在其他模块中寻找其定义
  10. #endif
复制代码


Display.c
  1. #include"display.h"             //显示头文件
  2. #include"delay.h"                //延时头文件

  3. unsigned char code array[]= {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff};

  4. void display()
  5. {
  6.            static unsigned char ucNumber_left = 0;  //左边数码管显示的实际内容
  7.         static unsigned char ucNumber_right = 0;  //右边数码管显示的实际内容
  8.         static unsigned char ucDisplayStep = 1;     //显示步骤切换变量

  9.         if(ucSetNumber >= 10)                              //在显示的数值小于10时,左边数码管不显示
  10.         {
  11.             ucNumber_left = ucSetNumber/10;        //得到左边显示的值
  12.         }
  13.         else
  14.         {
  15.                 ucNumber_left = 10;                          //小于10就不显示
  16.         }

  17.         ucNumber_right = ucSetNumber%10;       //右边数码管显示的值

  18.         switch(ucDisplayStep)
  19.         {
  20.                 case 1:                                                //左边数码管显示驱动
  21.                        P0 = array[ucNumber_left];
  22.                            P2 = 0xfe;
  23.                            ucDisplayStep = 2;
  24.                            delay_10ms();
  25.                            P2 = 0xff;
  26.                        break;

  27.                 case 2:
  28.                            P0 = array[ucNumber_right];    //右边数码管显示驱动
  29.                    P2 = 0xfd;
  30.                            ucDisplayStep = 1;
  31.                            delay_10ms();
  32.                            P2 = 0xff;
  33.                        break;
  34.         }
  35. }
复制代码


Display.h

  1. #ifndef __display_h__
  2. #define __display_h__

  3. #include<reg52.h>
  4. void display();
  5. extern unsigned char ucIICDataTemp;       //声名全局变量
  6. extern unsigned char ucSetNumber;          //声名全局变量
  7. #endif
复制代码

delay.c
  1. #include"delay.h"

  2. void delay_10ms()           //延时函数
  3. {
  4.    unsigned int x,y;
  5.     for(x = 0;x<10;x++)
  6.           for(y = 0;y<10;y++);
  7.       
  8. }
复制代码


delay.h
  1. #ifndef __delay_h__
  2. #define __delay_h__

  3. void delay_10ms();           //函数声名

  4. #endif
复制代码





            打包程序下载——>   EEPROM篇—用AT24C02数据保存数据.zip (108.42 KB, 下载次数: 254)

评分

参与人数 4黑币 +73 收起 理由
xiaomage + 10 非常棒的程序,规范,整洁,值得学习!
admin + 50 共享资料的积分奖励!
liuyy + 5 赞一个!
liuyuxi + 8 很给力!

查看全部评分

回复

使用道具 举报

ID:72008 发表于 2015-1-11 02:59 | 显示全部楼层
谢谢版主提供 这么好的学习资料。先下了看看
回复

使用道具 举报

ID:72008 发表于 2015-1-11 03:01 | 显示全部楼层
楼主程序文件很多,但是注释详细非常好。有电路图吗?
回复

使用道具 举报

ID:69862 发表于 2015-1-11 19:55 | 显示全部楼层
liuyy 发表于 2015-1-11 02:59
谢谢版主提供 这么好的学习资料。先下了看看

资料还有,我会慢慢的奉献的。。。。。
回复

使用道具 举报

ID:69862 发表于 2015-1-11 19:58 | 显示全部楼层
liuyy 发表于 2015-1-11 03:01
楼主程序文件很多,但是注释详细非常好。有电路图吗?

文件分得很细,是为了以后方便移植,我是用的开发板,原理图就不上了,很简单的。可以根据程序来画原理图。。。
回复

使用道具 举报

ID:73539 发表于 2015-2-11 15:02 | 显示全部楼层
顶一下!好东西!谢谢楼主,正找这个呢!
回复

使用道具 举报

ID:95691 发表于 2016-7-25 09:20 | 显示全部楼层
赞一个,很好的资料!
回复

使用道具 举报

ID:104845 发表于 2016-8-17 23:13 | 显示全部楼层
多谢无私分享
回复

使用道具 举报

ID:214494 发表于 2018-1-22 13:45 | 显示全部楼层
谢谢版主提供 这么好的学习资料
回复

使用道具 举报

ID:614257 发表于 2019-12-6 17:11 | 显示全部楼层
看一看
回复

使用道具 举报

ID:689314 发表于 2020-4-26 22:50 | 显示全部楼层
写得太棒了!
回复

使用道具 举报

ID:933601 发表于 2023-11-14 08:57 | 显示全部楼层
这么详细,讲究
回复

使用道具 举报

ID:1076665 发表于 2023-12-18 22:03 | 显示全部楼层
很不错,很详细,值得研究
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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