范劍
(浙江臺州學院 機械工程學院,臺州 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/.