STM32 FLASH操作

1.stm32f10xxx閃存編程參考手冊寫的很詳細。

2.主閃存編程:

對主閃存編程每次可以寫入16位。當FLASH_CR寄存器的PG位爲’1’時,在一個閃存地址寫入一個半字將啓動一次編程;寫入任何非半字的數據,FPEC都會產生總線錯誤。在編程過程中(BSY位爲’1’),任何讀寫閃存的操作都會使CPU暫停,直到此次閃存編程結束。

這裏寫圖片描述

3.

這裏寫圖片描述

這裏寫圖片描述

4. 寫入flash函數

代碼正點原子例程。
用一個數組u16(半字)存放數據,然後在解鎖的情況下,一個一個的複製到被寫入的flash地址中去。
這裏沒有跨越頁區。

這裏寫圖片描述

//從指定地址開始寫入指定長度的數據
//WriteAddr:起始地址(此地址必須爲2的倍數!!)
//pBuffer:數據指針
//NumToWrite:半字(16位)數(就是要寫入的16位數據的個數.)
#if STM32_FLASH_SIZE<256
#define STM_SECTOR_SIZE 1024 //字節
#else 
#define STM_SECTOR_SIZE 2048
#endif       
u16 STMFLASH_BUF[STM_SECTOR_SIZE/2];//最多是2K字節
void STMFLASH_Write(u32 WriteAddr,u16 * pBuffer,u16 NumToWrite) 
{
    u32 secpos;    //扇區地址
    u16 secoff;    //扇區內偏移地址(16位字計算)
    u16 secremain; //扇區內剩餘地址(16位字計算)       
    u16 i;    
    u32 offaddr;   //去掉0X08000000後的地址

    if(WriteAddr<STM32_FLASH_BASE||(WriteAddr>=(STM32_FLASH_BASE+1024*STM32_FLASH_SIZE)))return;//非法地址

    FLASH_Unlock();                     //解鎖

    offaddr=WriteAddr-STM32_FLASH_BASE;     //實際偏移地址.
    secpos= offaddr / STM_SECTOR_SIZE;          //扇區地址  0~127 for STM32F103RBT6
    secoff=(offaddr % STM_SECTOR_SIZE)/2;       //在扇區內的偏移(2個字節爲基本單位.)
    secremain=STM_SECTOR_SIZE/2-secoff;     //扇區剩餘空間大小        
    if(NumToWrite<=secremain)secremain=NumToWrite;//不大於該扇區範圍
    //爲後面的循環寫入提供方便,第92行的判斷

    while(1) 
    {   
        STMFLASH_Read(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE,STMFLASH_BUF,STM_SECTOR_SIZE/2);//讀出整個扇區的內容
        for(i=0;i<secremain;i++)//校驗數據
        {
            if(STMFLASH_BUF[secoff+i]!=0XFFFF)break;//需要擦除        
        }
        if(i<secremain)//需要擦除
        {
            FLASH_ErasePage(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE);//擦除這個扇區
            for(i=0;i<secremain;i++)//複製
            {
                STMFLASH_BUF[i+secoff]=pBuffer[i];    
            }
            STMFLASH_Write_NoCheck(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE,STMFLASH_BUF,STM_SECTOR_SIZE/2);//寫入整個扇區  
        }else STMFLASH_Write_NoCheck(WriteAddr,pBuffer,secremain);//寫已經擦除了的,直接寫入扇區剩餘區間.                    
        if(NumToWrite==secremain)break;//寫入結束了
        else//寫入未結束
        {
            secpos++;               //扇區地址增1
            secoff=0;               //偏移位置爲0     
            pBuffer+=secremain;     //指針偏移
            WriteAddr+=secremain;   //寫地址偏移    
            NumToWrite-=secremain;  //字節(16位)數遞減
            if(NumToWrite>(STM_SECTOR_SIZE/2))secremain=STM_SECTOR_SIZE/2;//下一個扇區還是寫不完
            else secremain=NumToWrite;//下一個扇區可以寫完了
        }    
    };  
    FLASH_Lock();//上鎖
}    
#endif

5# 速度匹配問題

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章