范剑
(浙江台州学院 机械工程学院,台州 310018)
E2PROM是具有电可擦除特性的存储器。其优点是无需外加电源即可永久保存数据。基于这种优良特性,该器件广泛应用于对数据存储安全性及可靠性要求较高的应用场合。而且,越来越多的微控制器(MCU)生产厂家陆续推出了集成独立E2PROM数据存储器的产品,使其在结构、性能和功能等方面都有明显的提高。但是,E2PROM的缺点是数据的写入次数有限(指某一位由1写为0的次数),当前的工艺技术已经能做到不低于100万次。这虽然能够满足多数用户的要求,但对于E2PROM内的数据在系统运行过程中有频繁擦写的要求而言,当存放这些数据的片内存储单元擦写次数达到上限时,这个存储单元就不能再使用了,从而需要另辟蹊径,尽量提高E2PROM的写入寿命。姜金、李波等人利用空闲E2PROM空间,提出了一种存储失效检测和更新存储空间的动态E2PROM数据存储策略[1];李维平、张涛等人提出了在E2PROM空间做N次遍历存储的方法[2]。本文首先综合上述两种方案的优点,针对不同更新频率的变量,进一步提出分区域遍历轮循的数据动态存储策略,能有效延长E2PROM的写入寿命。本文最后针对设计一种增量型计数器,提出了另一种“写零计数”的E2PROM数据遍历轮循存储策略。
一般情况下,系统的设计者会把数据存储方式设定为静态,即为固定的地址存储指定的变量值。但是,考虑到单片机内部的E2PROM空间相对于有待保存的数据量来说是有很大富余的[1],从而可以用软件的方法,最大程度地利用E2PROM存储空间资源,以整体存储空间的使用寿命来扩展某局部、若干的存储器单元的使用寿命。所谓遍历轮循数据存储,指的是在设定区域内,将同一变量每一次的更新值,从设定的存储区域起始单元位置开始,依次按更新顺序逐个单元地保存,直到最末单元位置,即完成了一次该区域的遍历存储使用,然后又从该区域起始位置重新轮循。
根据系统的设计要求,大致估计每个变量的更新速度,将更新频繁的若干变量分别预先分配到不同的遍历轮循区域,更新快的设置较大的遍历轮循存储区域,更新慢的则设置较小的遍历轮循存储区域。对于更新很少和不更新的变量或数据表,将其设置在同一片存储区域(对于STC单片机内部集成的E2PROM,可以扇区为单位划分存储区域)。表1是以ATmega64为例对其内部2KB E2PROM空间分配设置的一种情形。
表1 ATmega64E2PROM空间某种分配设置
比如,为保存上表中变量temp的新值,其存储地址由地址变量addr_temp来确定,每一次保存完变量temp的值,存储地址addr_temp加1,指向下一个存储地址,指示下一次更新的数据放到这个指定的位置单元,直到更新数据写到了这个区域的最后一个字节。这时如有更新值需要写入,则对该区域执行一次擦除操作(每个位上全部写1),并将addr_temp存储地址重置为000H,再把更新数据写入到存储单元,然后存储地址addr_temp加1,如此循环。
由上述过程可以看出,将某个变量和指定的区域对应,采用软件的方法重复使用该区域的存储资源,当指定区域各单元都写完一遍后,做一次区域整体擦除,从而使得原先是一个单元的写入寿命扩展变通为一个区域的写入寿命。比如表1中,为变量temp分配了512字节,那么写入寿命扩展到了原先静态存储方式的512倍。如此类推,可知表1中变量value的写入寿命能扩展到1 024倍。程序设计者可以根据变量的实际可能更新频率,合理配置E2PROM的存储区域空间大小,延长其写入寿命。
嵌入式系统上电后一般先进行自检和初始化,其中初始化的过程就包含读取E2PROM数据的操作。那么在使用上述存储策略的情况下,如何识别有效的数据信息并将更新的地址位置读取出来呢?
仍以上述变量temp为例,假设断电之前addr_temp指向的存储地址是45H,那么该区域地址为44H的单元存储的是断电前的最后一个数值。由此可以断定,这个区域中,地址为44H的单元之后的值全为擦写后的状态值(即为FFH)。由此可以推断:从指定区域开始单元位置逐个查找判断,如果找到FFH值,有可能到达了断电前的最后一次更新值的位置。但另一方面,若系统在任何条件下的更新值都不可能是FFH值,则前述推断成立;但如果之前有更新值可以是FFH值,那么,刚才的结论无疑就被推翻了。这种情况下,可以结合更新数据自身的特点设计一个数据存储协议,比如使用“数据字节+特征字节”构成数据包的方式来存储,如“数据字节+00”。这样一来,根据存储数据包的特点,将存储区数据逐个分包读取和判断,当读取到字节包全为FFH值时,即可确定已找到断电前的最后一次更新值的地址位置。
存储变量数据到E2PROM的过程可以设计一个子程序专门来完成这项工作。首先根据该变量的当前存储地址写入指定值(数据包),然后采用地址值自加的方式更新存储地址指针值,以使其指向下一组数据的存储地址单元。接着判断该地址是否到达存储区域的最高地址,如果到达,就将地址设置成该区域的首字节的位置,否则就直接返回。该程序结构清晰,编程设计也比较简单。上述过程实现了“分区域遍历轮循的数据动态存储”策略,E2PROM数据动态存储模块程序流程如图1所示。
图1 E2PROM数据动态存储模块程序流程
该存储策略专门针对一种增量型实时计数和记录的特例而言,记录的数值呈单方向递增的特点。下面以笔者为某自动化生产流水线设计的一款产品计数器为例进行说明。该计数器连接了一个传感器(接近开关),用于检测流水线上产品经过计数检测口的信号。当接收到传感器下降沿信号时,系统进行加1计数。该模块电路比较简单,此处从略。
为了充分利用MCU内部的E2PROM存储器,设计中采用了“写零计数”方法。假定该计数器的记录上限值是10 000次。一般情况下,E2PROM存储器出厂时全部单元的数据被设置为初始态FFH。软件设计思路如下:首次使用时,系统每检测到1次传感器的下降沿跳变信号,就从存储器单元的首位依次逐位写0到对应的位上。比如,第一次到了就写FEH,第二次到了就写FCH,然后是F7H、F0H、E0H……(也就是逐次从低到高按位写0)。对于第一个字节来说,有8个位,用第一个起始字 58更新后,开始监测行信号到达,之后使能/WE,开始顺序读取图像。读完一帧图像后关闭/WE,单片机使能/RE,开始读取首行图像中的640个像素。本文采取边读边处理的方式,较好地解决了一帧图像多达3MB的问题。点光源标杆发出的红外光线在图像上呈现出若干个光晕区域,找到光晕中心就可以找到点光源的图像坐标,为此在读取的同时将各像素点与阈值进行比较,小于阈值的为疑似点光源并记录对应坐标;当读取完一行像素时,得到的将是一组疑似点光源坐标的像素位置,将其进行统计求平均,得出点光源在该行的坐标,最多12个字节(正面标杆6个,某侧标杆6个),远远小于整行640个字节。
图9 程序设计流程图
当读取完一帧像素时,得到最多12×480个字节,单片机64KB的容量完全可以存储,最后将行求平均,得出最终的点光源坐标。经验证,所需总时间在2.15帧图像内完成。
文中讨论了基于FIFO芯片和单片机实现的点光源图像采集系统,描述了单目点光源测距原理、图像采集系统硬件和软件设计方法,着重介绍了FIFO芯片在图像采集中的桥梁作用。通过系统样机检验,能够满足要求,达到了预期效果。
[1]邵贝贝.单片机嵌入式应用的在线开发方法[M].北京:清华大学出版社,2009.
[2]Freescale Semiconductor.MC9S12DG128Device User Guide[EB/OL].[2011-11].http://www.freescale.com.cn.
[3]OmniVision Technologies.OV7670/OV7171CMOS VGA 图像传感器[EB/OL].[2011-11].http://www.ovt.com/technologies/.
[4]Aver Logic.AL422DataSheet[EB/OL].[2011-11].http://www.averlogic.com/.