在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

            EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > STM32 使用 Flash 存儲數據時的一種管理辦法

            STM32 使用 Flash 存儲數據時的一種管理辦法

            作者: 時間:2016-11-13 來源:網絡 收藏
            使用 stm32f3xx,需要存儲一些掉電不丟失的校準信息,查閱手冊得知:1、stm32 寫 flash 的長度是固定的 16bit;2、擦除時必須整塊(2Kbytes)擦除,給出某 flash 塊內的地址,執(zhí)行擦除命令就可以了;3、參考手冊給出了最小擦寫次數為 10K。
            以上三點對于實際使用時的影響,首先,寫數據必須以 16bit 為單位,很多 32bit 長度的值就不能直接使用類似 A = B 的賦值語句的方法去操作了,可以統(tǒng)一轉化為指向 16bit 無符號整形值的指針來處理。舉例,有一個 32bit 長度的 float 變量 v_float,要存入地址為 (FLASH_ADDRESS)的 flash中:
            #define FLASH_ADDRESS (0x0803F800)
            if(FLASH->CR &= FLASH_CR_LOCK) //解鎖flash
            {
            FLASH->KEYR = (FLASH_KEYR_FKEYR & FLASH_KEY1);
            FLASH->KEYR = (FLASH_KEYR_FKEYR & FLASH_KEY2);
            while(FLASH->CR & FLASH_CR_LOCK);
            }
            while(FLASH->SR &= FLASH_SR_BSY);
            FLASH->CR |= FLASH_CR_PG; //功能選擇,寫flash
            {
            *((unsigned short *)(FLASH_ADDRESS) + 0 ) = *((unsigned short *)(&v_float) + 0 );
            *((unsigned short *)(FLASH_ADDRESS) + 1 ) = *((unsigned short *)(&v_float) + 1 );
            }
            FLASH->CR &= ~FLASH_CR_PG;
            FLASH->CR |= FLASH_CR_LOCK; //鎖flash
            如果需要讀取寫入到 flash 中的浮點數到 ram 中的變量 a_float,使用如下語句:
            a_float = *((float *) FLASH_ADDRESS);
            這樣,寫入和讀取就完成了,下面是擦除,按照參考手冊的流程來就可以了:
            if(FLASH->CR &= FLASH_CR_LOCK) //解鎖flash
            {
            FLASH->KEYR = (FLASH_KEYR_FKEYR & FLASH_KEY1);
            FLASH->KEYR = (FLASH_KEYR_FKEYR & FLASH_KEY2);
            while(FLASH->CR & FLASH_CR_LOCK);
            }
            while(FLASH->SR &= FLASH_SR_BSY); //Wait until flash not busy
            FLASH->CR |= FLASH_CR_PER; //功能選擇,擦除頁
            FLASH->AR = FLASH_ADDRESS; //寫入flash地址
            FLASH->CR |= FLASH_CR_STRT; //開始擦除
            while(FLASH->SR &= FLASH_SR_BSY); //等待
            if(FLASH->SR &= FLASH_SR_EOP)
            {
            FLASH->SR |= FLASH_SR_EOP; //重置EOP
            }
            FLASH->CR &= ~FLASH_CR_PER;
            FLASH->CR |= FLASH_CR_LOCK; //鎖flash
            以上代碼會擦除 FLASH_ADDRESS 所在的整個 flash 頁。
            實現少量數據的讀寫和擦除操作以后,下一步要開始組織 flash 中存儲的數據,這樣以后閱讀和修改都更為方便,我使用類似 stm32 官方寄存器配置文件的方式,用結構體來組織。假設我要將某個人的個人信息儲存在 flash 中地址為(FLASH_ADDRESS)的位置,包括:姓名、性別、身高、體重,代碼如下:
            typedef struct //構造結構體
            {
            unsigned char name[16];
            unsigned char male;
            float height;
            float weight;
            }Personal_Information_TypeDef;
            #define FLASH_ADDRESS (0x0803F800) //flash地址
            #define Personal_Data ((Personal_Information_TypeDef *) FLASH_ADDRESS )
            以上代碼在起始地址為(FLASH_ADDRESS)的 flash 中,定義了用于儲存?zhèn)€人信息的結構體指針 Personal_Data,也就是說 Personal_Data 這個指針的值就是 FLASH_ADDRESS,只不過除了這個指針的值以外,我們還定義了這個指針所指向的數據的結構。要讀出這些儲存于 flash 中的值,使用讀取結構體指針的方式:
            Temp_variable = Personal_Data -> male;
            寫 flash 的時候,因為每次只能寫 16bit,所以除了 short 類型以外,類似 int 和 float 這種 32bit 的數據,都要取地址強制轉化為 16bit 類型后再取值最后寫入,方法類似一開始的 float 類型數據寫入 flash 的操作。我為了操作方便,在 ram 中建立了一個和 flash 內結構相同的結構體,每次需要寫入 flash 的時候,就將 ram 中結構體的所有值全部寫入 flash:
            typedef struct //構造結構體
            {
            unsigned char name[16];
            unsigned char male;
            float height;
            float weight;
            }Personal_Information_TypeDef;
            #define Length (5) //結構體總長(16bit單位)
            #define FLASH_ADDRESS (0x0803F800) //flash地址
            #define Personal_Data ((Personal_Information_TypeDef *) FLASH_ADDRESS )
            Personal_Information_TypeDef Personal_Data_Mirror; //ram中的結構體
            /* 寫入過程 */
            (unsigned short *)WriteAddress = (unsigned short *)Personal_Data;
            (unsigned short *)ReadAddress = (unsigned short *)(&Personal_Data_Mirror);
            if(FLASH->CR &= FLASH_CR_LOCK) //解鎖flash
            {
            FLASH->KEYR = (FLASH_KEYR_FKEYR & FLASH_KEY1);
            FLASH->KEYR = (FLASH_KEYR_FKEYR & FLASH_KEY2);
            while(FLASH->CR & FLASH_CR_LOCK);
            }
            FLASH->CR |= FLASH_CR_PG; //功能選擇,寫入
            while(Length > 0)
            {
            *WriteAddress = *ReadAddress; //Ram to Flash program, 16bit each
            while(FLASH->SR &= FLASH_SR_BSY);
            WriteAddress += 1;
            ReadAddress += 1;
            Length -= 1;
            }
            FLASH->CR &= ~FLASH_CR_PG; //Clear PG bit
            FLASH->CR |= FLASH_CR_LOCK; //Lock flash
            以上的寫入過程之前,必須確保要寫入的 flash 位置首先擦除過,或者說要保證要寫入數據的地方的值為0xFFFFFFFF,否則無法寫入,硬件會有標志位來報錯。
            這樣以結構體為單位擦寫 flash 的好處是,如果需要修改要儲存的數據數量或類型的話,只需要修改結構體定義就可以了,而且用結構體來管理變量,程序的可讀性較好。
            最后就是 flash 的擦寫次數問題了,最少10k次的擦寫壽命,對于某些需要頻繁更新的內容還是太少了,比EEPROM 通常的 100k 少了一個數量級,而且即使是改動一個變量,也必須首先擦除整個 flash 塊,更加速了 flash 的消耗。但是 stm32 的 flash 容量還是不錯的,動輒 256Kbytes,所以我們可以用容量換壽命,
            具體思路就是不要在同一個地址重復擦寫,寫的時候不停的變換地址,寫滿以后再擦除。比如,需要儲存的結構體長度為 20x16bit,那么一個 2Kbytes 的 flash 頁就可以儲存 50 個相同的結構體,那么執(zhí)行完 50 次寫操作以后才需要執(zhí)行一次擦除操作,flash 的使用壽命隨之大為延長。
            還是以儲存一個結構體為例說明如何實現這種儲存方式,首先定義結構體,除了你需要儲存的數據以外,還要額外增加一個變量,用于識別你當前讀寫的 flash 地址:
            typedef struct //構造結構體
            {
            unsigned char flag; //用于識別當前地址的標記
            unsigned char name[16];
            unsigned char male;
            float height;
            float weight;
            }Personal_Information_TypeDef;
            #define Length (6) //結構體總長(16bit單位)
            #define FLASH_ADDRESS (0x0803F800) //flash地址
            #define Personal_Data ((Personal_Information_TypeDef *) FLASH_ADDRESS )
            Personal_Information_TypeDef Personal_Data_Mirror; //ram中的結構體
            這部分除了結構體中增加了一個標記(flag)變量以外,其它部分相同,但是思想上,我們其實是在 flash 中定義了一個結構體數組,只不過沒有使用通常的[]來遍歷數組變量,取而代之的是直接使用指針來操作。每次寫入時,將 flag 變量固定寫為 0x00。需要讀取 flash 數據時,就可以根據標記變量 flag 的值找到最新的 flash 數據地址:
            #define FLASH_ADDRESS_MAX; //最大偏移量,防止跨區(qū)塊操作
            unsigned short FlashAddress_Offset = 0; //用于儲存flash地址偏移量的臨時變量
            while( (Personal_Data + FlashAddress_Offset) -> flag == 0x00)
            {
            FlashAddress_Offset += 1;
            if( (FlashAddress_Offset + FlashAddress_Offset) > MAX_OFFSET)
            {
            break;
            }
            }
            找到寫有數據的 flash 地址以后,后繼的寫操作和讀操作和單個結構體的操作相似,寫的地址變?yōu)椋?Personal_Data + FlashAddress_Offset)
            讀的地址是:
            (Personal_Data + FlashAddress_Offset - 1)
            具體實現時要注意,結構體的長度要算好,不能出現兩個結構體交叉寫入;擦除 flash 需要時間,此間最好不進行需要讀取 flash 的操作。



            評論


            技術專區(qū)

            關閉