<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 單片機(jī)中的掉電存儲(chǔ)管理

          單片機(jī)中的掉電存儲(chǔ)管理

          作者: 時(shí)間:2016-11-30 來(lái)源:網(wǎng)絡(luò) 收藏
          各位單片機(jī)程序猿們,在單片機(jī)程序設(shè)計(jì)的時(shí)候,經(jīng)常碰到一些數(shù)據(jù)的掉電存儲(chǔ)問(wèn)題。往往這些數(shù)據(jù)量又不是很大,但是操作起來(lái)特別麻煩。每次變更數(shù)據(jù)都得調(diào)用存儲(chǔ)函數(shù)進(jìn)行讀寫(xiě)操作。今天總結(jié)一下近幾天的思路,對(duì)普通單片機(jī)的的NV變量的管理給出一個(gè)較為方便的操作方法。

          一般,我們的數(shù)據(jù)都由8,16,32位組成,因此,在此例中,我給出16長(zhǎng)度數(shù)據(jù)的接口函數(shù),旨在表明這種方法的思路。具體讀者可以根據(jù)自己的使用環(huán)境,自己改進(jìn)。

          本文引用地址:http://www.ex-cimer.com/article/201611/323956.htm

          首先,說(shuō)明下筆者的編程習(xí)慣,筆者在編寫(xiě)單片機(jī)C程序的過(guò)程中,往往喜歡把程序中涉及的東西封裝成類(lèi)似于面向?qū)ο笏枷胫械念?lèi)。把數(shù)據(jù)結(jié)構(gòu)假想成類(lèi)的屬性,把對(duì)相應(yīng)數(shù)據(jù)結(jié)構(gòu)操作的函數(shù),假想成類(lèi)的方法。這種方法在實(shí)際編程過(guò)程中,往往給自己帶來(lái)很大的便利。不僅思路清晰,而且便于模塊化管理自己的程序。

          現(xiàn)在,我們創(chuàng)建兩個(gè)文件,分別為NV.h和NV.C,h文件作為NV管理的模塊。NV.h中我們來(lái)定義NV變量的數(shù)據(jù)結(jié)構(gòu)(即筆者所認(rèn)為的類(lèi)的屬性)和聲明對(duì)NV操作的函數(shù)。
          #ifndef _NV_
          #define _NV_

          //NV操作的狀態(tài)定義
          #define NV_Succeed 1

          #defineNV_Failed 0
          //定義16位長(zhǎng)度的NV變量數(shù)據(jù)結(jié)構(gòu)

          structNV_Struct16
          {
          u16 Val; //NV16變量的值
          u16 NVAddr; //NV16變量在存儲(chǔ)器中的首地址
          };
          //聲明外部調(diào)用函數(shù)
          extern void NV16_Get(struct NV_Struct16 *temp);
          u8 NV16_Set(struct NV_Struct16 *temp,u16 val);
          #endif

          在NV_Struct16中,我們封裝了一個(gè)叫做NV16的變量,其成員中有變量的值和在存儲(chǔ)器中的首地址。在這里,只是給它定義了一個(gè)數(shù)據(jù)的結(jié)構(gòu),并沒(méi)有定義實(shí)體變量,在C++或C#等面向?qū)ο蟪绦蛟O(shè)計(jì)方法中,這叫類(lèi)的定義,并沒(méi)有創(chuàng)建類(lèi)的實(shí)體。這樣做的目的,就是做到盡量把我們這個(gè)NV操作模塊從我們編寫(xiě)的其他應(yīng)用程序中抽象出來(lái)。

          那么,接下來(lái),我們就來(lái)編寫(xiě)NV16變量的操作函數(shù)。在NV.C中,我們添加兩個(gè)函數(shù),一個(gè)是獲取NV變量的值,另一個(gè)是修改NV變量的值。

          #include"NV.h"
          #include"24CXX.h"
          #defineCheckTimes 4 //寫(xiě)入時(shí)校驗(yàn)次數(shù)
          #defineNV8_Enable 1 //NV8使能開(kāi)關(guān)
          #defineNV16_Enable 1 //NV16使能開(kāi)關(guān)
          #defineNV32_Enable 1 //NV32使能開(kāi)關(guān)

          //以下是NV_Struct16的操作函數(shù)

          #ifNV16_Enable
          voidNV16_Get(struct NV_Struct16 *temp)
          {
          temp->Val=AT24CXX_ReadLenByte(temp->NVAddr,2);
          }
          u8NV16_Set(struct NV_Struct16 *temp,u16 val)
          {
          u8 cnt=0;
          if(temp->Val==val)returnNV_Succeed;
          temp->Val=val;
          AT24CXX_WriteLenByte(temp->NVAddr,temp->Val,2);
          while(cntNVAddr,2)!=temp->Val)
          cnt++;
          if(cnt else return NV_Succeed;
          }

          #endif
          在這個(gè)文件中,我們調(diào)用了一個(gè)24CXX.h文件中提供的24CXX的讀寫(xiě)函數(shù),這部分在我們移植的過(guò)程中是需要考慮的。下面貼出這個(gè)函數(shù)的原型,如果這個(gè)都不知道怎么寫(xiě)出來(lái),那我也無(wú)語(yǔ)了。

          //在AT24CXX里面的指定地址開(kāi)始讀出長(zhǎng)度為L(zhǎng)en的數(shù)據(jù)
          //該函數(shù)用于讀出16bit或者32bit的數(shù)據(jù).
          //ReadAddr :開(kāi)始讀出的地址
          //返回值 :數(shù)據(jù)
          //Len :要讀出數(shù)據(jù)的長(zhǎng)度2,4
          u32AT24CXX_ReadLenByte(u16 ReadAddr,u8 Len)
          {
          u8 t;
          u32 temp=0;
          for(t=0;t {
          temp<<=8;
          temp+=AT24CXX_ReadOneByte(ReadAddr+Len-t-1);
          }
          return temp;
          }

          //在AT24CXX里面的指定地址開(kāi)始寫(xiě)入長(zhǎng)度為L(zhǎng)en的數(shù)據(jù)
          //該函數(shù)用于寫(xiě)入16bit或者32bit的數(shù)據(jù).
          //WriteAddr :開(kāi)始寫(xiě)入的地址
          //DataToWrite:數(shù)據(jù)數(shù)組首地址
          //Len :要寫(xiě)入數(shù)據(jù)的長(zhǎng)度2,4
          voidAT24CXX_WriteLenByte(u16 WriteAddr,u32 DataToWrite,u8 Len)

          {
          u8 t;
          for(t=0;t {
          AT24CXX_WriteOneByte(WriteAddr+t,(DataToWrite>>(8*t))&0xff);
          }
          }


          用以上方法來(lái)管理我們的NV變量,在程序中會(huì)大大地減少我們的工作量。下面來(lái)舉一個(gè)簡(jiǎn)單的例子。記錄設(shè)備開(kāi)機(jī)次數(shù),并從串口打印出來(lái)。
          #include “相關(guān)頭文件”
          #include "NV.H"

          #define Flag 0x33 //存儲(chǔ)器初始化標(biāo)志
          #define FlagAddr 0x00
          #define PowerOnTimesAddr 0x10 //將開(kāi)機(jī)次數(shù)數(shù)據(jù)存儲(chǔ)在0x10位置
          //創(chuàng)建NV16非易失變量實(shí)體
          struct NV_Struct16 PowerOnTimes;
          struct NV_Struct16 MemFlag;

          void NV_Init()
          {
          //NV地址裝入
          MemFlag.NVAddr=FlagAddr;
          PowerOnTimes.NVAddr=PowerOnTimesAddr;
          //檢查存儲(chǔ)器是否初始化
          if(NV16_Get(&MemFlag)!=Flag)
          {
          NV16_Set(&MemFlag,Flag);
          NV16_Set(&PowerOnTimes,0);
          }
          }

          void main()
          {
          u16 times;
          NV_Init();
          times=NV16_Get(&PowerOnTimes);
          NV16_Set(&PowerOnTimes,times++);
          printf("%d",times);
          while(1);
          }
          哈哈,這樣子,你的應(yīng)用程序是不是很簡(jiǎn)潔呀。喜歡那就嘗試下吧!



          評(píng)論


          技術(shù)專(zhuān)區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();