IAP15W413AS工业自动化控制之【14EEPROM实现数据掉电保存】

  • SingleYork
  • LV5工程师
  • |      2017-08-23 15:07:40
  • 浏览量 2697
  • 回复:5
本帖最后由 SingleYork 于 2017-9-16 16:44 编辑 bg1.png

在实际应用中,很多时候我们需要对一些设置参数实现掉电保持,以免每次上电都需要重新设置参数,或者产品在运行过程中,需要实时保存一些数据,下次开机后还能查询到。像这种应用场合,就需要用到单片机的EEPROM功能了,当然,也可以用到外部FLASH、EEPROM等芯片,只是,单片机本身自带EEPROM,又何必去另外花钱呢,对吧?

那么,本例笔者就来跟大家介绍一下这款IAP15W413AS控制板的掉电存储功能吧。首先,什么是EEPROM相信大家都应该知道了,不知道的也可以自行百度,毕竟这不是笔者要讲的重点,还是直接切入正题吧,从芯片手册上我们可以知道,IAP15W413AS这款单片机是没有专门的EEPROM的,纳尼?刚才不是说有EEPROM的么?怎么现在又说没有了呢,你是在逗我玩么?哈哈,别急,IAP15W413AS虽然没有专门的EEPROM,但是我们可以将用户程序区的FLASH当EEPROM来使用,也就是说,芯片的存储空间有多大,EEPROM就可以有多大,当然咯,这是比较理想的状况,实际上,我们的程序大小不可能为零,对吧?!

从上面表格中,我们可以知道,IAP15W413AS单片机的EEPROM最多可以分为26个扇区,每个扇区的大小为512个字节,如果我们需要同时操作的数据不大的话,一般只用一个扇区应该就够了,关于这部分详细的知识点,大家可以看芯片手册,笔者在此就不再赘述。本例中,笔者以一个电子钟的程序为例来进行讲解,需要保存的数据就是时、分、秒,很显然只有三个数,一个扇区足矣!那么我们就用使用最后一个扇区吧。

定义扇区的起始地址:

#define IAP_ADDRESS 0x3200                //0x3200-0x33FF   512BYTE

接下来,我们先来实现我们的电子钟程序部分吧,这里其实很简单,用一个定时器就搞定了:

/********************* Timer0中断函数************************/

void timer0_int (void) interrupt TIMER0_VECTOR        //1ms

{

  if(Time_EN)

  {

    if(++Time_Cnt>=1000)//1000ms

    {

      Time_Cnt    = 0;

      Uart1SendEN = 1;        //串口发送标志使能

      if(++Time_Sec>=60)      //60s

      {

        Time_Sec = 0;

        if(++Time_Min>=60)    //60Min

        {

          Time_Min = 0;

          if(++Time_Hour>=24) //24Hour

          {

            Time_Hour = 0;

          }

        }

      }        

    }

  }

}

其中,Time_EN为计时使能标志,Time_Cnt是用来1ms计数一次,Time_Sec是时间:秒,Time_Min是时间:分,Time_Hour是时间:时,Uart1SendEN是用来使能串口打印数据的,本例钟是1秒串口打印输出1次。程序逻辑很简单,相信有一点基础的基本都能看懂。为了让读者能够看到电子钟实时运行的效果,笔者是通过串口打印的方式来延时的,毕竟板子上也没有装数码管或者液晶屏之类的。

printf("%d:%d:%d\n",Time_Hour,Time_Min,Time_Sec);//串口打印输出时间

在使用printf函数的时候,有一点是特别需要注意的,那就是:在串口初始化的时候,我们需要将TI置1,否则将不能打印输出。关于这点,大家可以自行验证,笔者在此就略过了。

那么,现在我们就要来看数据保存的问题了,如果是要保存到某一秒的话,那么很显然,我们就需要让EEPROM的保存数据间隔小于或至少等于1秒,这样才能做到将时间秒也保存起来。这里顺便说一下,其实还有一种更好的方式,那就是利用单片机的掉电检测功能,搭建掉电检测电路,实现真正的在掉电瞬间进行数据保存。当然,这个就比较复杂了,而且笔者这款板子上也没有专门做这个电路,所以笔者就不在此讲解了,还是用这种比较笨的方式来实现吧。

本例中,笔者是每1秒保存一次数据,利用Uart1SendEN这个标志位来实现打印的同时保存数据:

if(Uart1SendEN)   //1秒打印输出一次

    {

      Uart1SendEN = 0;

      printf("%d:%d:%d\n",Time_Hour,Time_Min,Time_Sec);//串口打印输出时间

      

      EEPROM_SectorErase(IAP_ADDRESS);                                  //扇区擦除,为写EEPROM做准备

      

      EEPROM_Table = Time_Hour/256;

      EEPROM_Table = Time_Hour%256;

      EEPROM_Table = Time_Min/256;

      EEPROM_Table = Time_Min%256;

      EEPROM_Table = Time_Sec/256;

      EEPROM_Table = Time_Sec%256;

      

      EEPROM_write_n(IAP_ADDRESS,EEPROM_Table,6);        //将数据写到EEPROM

    }

数据保存操作这样就搞定了,那么,我们怎么知道数据到底有没有保存呢?也很简单,在上电的时候从保存的地址位置将数据一一读出来不就好了么?

  EEPROM_read_n(IAP_ADDRESS,EEPROM_Table,6);

  

  Time_Hour = EEPROM_Table*256 + EEPROM_Table;

  Time_Min  = EEPROM_Table*256 + EEPROM_Table;

  Time_Sec  = EEPROM_Table*256 + EEPROM_Table;

这里需要注意的是,数据的读写操作都是按字节来操作的。所以,在写操作之前,都需要对数据转换成字节,再进行写操作;再读出数据后,也需要将读出来的字节转换成字,因为Time_Hour、Time_Min、Time_Sec都是unsigned int类型。

那么,对EEPROM的读写操作就这样全部搞定了,是不是很简单?我们来看一下运行效果吧,为了区分数据,每次上电的时候都会先打印输出“printf test”:

printf("printf test!\n");//串口打印结果

从上图中我们可以看到,重新上电后,断电前的数据是保存了的。好了,关于IAP15W413AS这款控制板的数据掉电保持功能就介绍到这里了,有一个点笔者需要提醒大家,我们都知道,芯片的擦写次数是有上限的,一般都是在10万次或者100万次,不管是多少次,都意味着他是有寿命的,而我们进行EEPROM写操作的时候,每次都会需要先进行擦除操作,才能成功写入数据,既然这样,如果我们每秒来操作一次EEPROM的话,一天就需要擦写86400次,即使EEPROM的寿命有100万次,也就不到12天就要挂逼了。所以,实际应用中,我们是不允许这么平凡的操作EEPROM的,最理想的方式当然应该是做掉电检测电路来实现真正的掉电保存了,在一些要求不高的场合,也可以适当延长写操作时间间隔、换不同的扇区来实现,这些方法就留给读者去摸索了!

源代码:

  • 0
  • 收藏
  • 举报
  • 分享
我来回复

登录后可评论,请 登录注册

所有回答 数量:1
7943603 2017-08-23
写的贼拉好
0   回复
举报
发布
SingleYork 回复 2017-08-23
感谢大哥支持啊……:handshake
0   回复
举报
黄莨元 回复 2017-08-24
不错,学习了
0   回复
举报
lygo 回复 2017-09-14
赞一个
0   回复
举报
kidcando 回复 2018-01-18
学习学习了
0   回复
举报
x
收藏成功!点击 我的收藏 查看收藏的全部帖子