<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > stm32的flash如何寫(xiě)數據和當做eerom使用

stm32的flash如何寫(xiě)數據和當做eerom使用

作者: 時(shí)間:2016-11-27 來(lái)源:網(wǎng)絡(luò ) 收藏
STM32本身沒(méi)有自帶EEPROM,但是STM32具有IAP(在應用編程)功能,所以我們可以把它的FLASH當成EEPROM來(lái)使用,同時(shí),開(kāi)發(fā)者為了維護后期的版本升級,應該考慮到升級的可能和可行性,總不能讓用戶(hù)拿著(zhù)仿真器在線(xiàn)升級或現場(chǎng)調試吧很尷尬的,其次建議串口升級是目前較為被大眾接受的方式,stm32的串口升級時(shí)BOOT0在上啦的情況下升級只需要硬件設計時(shí)考慮到就ok。程序一般燒寫(xiě)在flash里邊,地址0x8000000開(kāi)始,升級的原理就是就是有一個(gè)寫(xiě)好的bootloader引導程序,它占用一定的空間比如0x800000-0x80002000這是這段代碼的空間,那么用戶(hù)程序就是實(shí)現功能的程序就要從0x80002001k開(kāi)始執行了,在這里設置的時(shí)候還要注意嵌套中斷的NVIC是有區別的。
在bootloader里NVIC_configuration()
是這樣的
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;

#ifdefVECT_TAB_RAM
/* Set the Vector Table base location at 0x20000000 */
NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else/* VECT_TAB_FLASH*/
/* Set the Vector Table base location at 0x08000000 */
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0);
#endif
/* Configure one bit for preemption priority */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
}

在功能程序里邊就要將0X8000000改成0x8000001l了。在keil編譯軟件里要設置一下。在general options里。那么FLASH可以存放程序,當然也可以當EEROM用了就是這個(gè)道理。
STM32FLASH簡(jiǎn)介
不同型號的STM32,其FLASH容量也有所不同,最小的只有16K字節,最大的則達到了1024K字節。戰艦STM32開(kāi)發(fā)板選擇的STM32F103ZET6的FLASH容量為512K字節,屬于大容量產(chǎn)品(另外還有中容量和小容量產(chǎn)品),
STM32的閃存模塊由:主存儲器、信息塊和閃存存儲器接口寄存器等3部分組成。
主存儲器,該部分用來(lái)存放代碼和數據常數(如const類(lèi)型的數據)。對于大容量產(chǎn)品,其被劃分為256頁(yè),每頁(yè)2K字節。注意,小容量和中容量產(chǎn)品則每頁(yè)只有1K字節。從上圖可以看出主存儲器的起始地址就是0X08000000,B0、B1都接GND的時(shí)候,就是從0X08000000開(kāi)始運行代碼的。
信息塊,該部分分為2個(gè)小部分,其中啟動(dòng)程序代碼,是用來(lái)存儲ST自帶的啟動(dòng)程序,用于串口下載代碼,當B0接V3.3,B1接GND的時(shí)候,運行的就是這部分代碼。另一部分用戶(hù)選擇字節,則一般用于配置寫(xiě)保護、讀保護等功能,
閃存存儲器接口寄存器,該部分用于控制閃存讀寫(xiě)等,是整個(gè)閃存模塊的控制機構。
閃存的讀取
內置閃存模塊可以在通用地址空間直接尋址,任何32位數據的讀操作都能訪(fǎng)問(wèn)閃存模塊的內容并得到相應的數據。讀接口在閃存端包含一個(gè)讀控制器,還包含一個(gè)AHB接口與CPU銜接。這個(gè)接口的主要工作是產(chǎn)生讀閃存的控制信號并預取CPU要求的指令塊,預取指令塊僅用于在I-Code總線(xiàn)上的取指操作,數據常量是通過(guò)D-Code總線(xiàn)訪(fǎng)問(wèn)的。這兩條總線(xiàn)的訪(fǎng)問(wèn)目標是相同的閃存模塊,訪(fǎng)問(wèn)D-Code將比預取指令優(yōu)先級高
這里要特別留意一個(gè)閃存等待時(shí)間,因為CPU運行速度比FLASH快得多,STM32F103的FLASH最快訪(fǎng)問(wèn)速度≤24Mhz,如果CPU頻率超過(guò)這個(gè)速度,那么必須加入等待時(shí)間,比如我們一般使用72Mhz的主頻,那么FLASH等待周期就必須設置為2,該設置通過(guò)FLASH_ACR寄存器設置,具體代碼體現在RCC_Configuration()內部這句話(huà)
/*設置FLASH延時(shí)周期數為2 */
FLASH_SetLatency(FLASH_Latency_2);。
使用STM32的官方固件庫操作FLASH的幾個(gè)常用函數。這些函數和定義分布在文件stm32f10x_flash.c以及stm32f10x_flash.h文件中。
1.鎖定解鎖函數
在對FLASH進(jìn)行寫(xiě)操作前必須先解鎖,解鎖操作也就是必須在FLASH_KEYR寄存器寫(xiě)入特定的序列(KEY1和KEY2),固件庫函數實(shí)現很簡(jiǎn)單:
voidFLASH_Unlock(void);
同樣的道理,在對FLASH寫(xiě)操作完成之后,我們要鎖定FLASH,使用的庫函數是:
voidFLASH_Lock(void);
2.寫(xiě)操作函數
固件庫提供了三個(gè)FLASH寫(xiě)函數:
FLASH_StatusFLASH_ProgramWord(uint32_tAddress,uint32_tData);
FLASH_StatusFLASH_ProgramHalfWord(uint32_tAddress,uint16_tData);
FLASH_StatusFLASH_ProgramOptionByteData(uint32_tAddress,uint8_tData);
顧名思義分別為:FLASH_ProgramWord為32位字寫(xiě)入函數,其他分別為16位半字寫(xiě)入和用戶(hù)選擇字節寫(xiě)入函數。這里需要說(shuō)明,32位字節寫(xiě)入實(shí)際上是寫(xiě)入的兩次16位數據,寫(xiě)完第一次后地址+2,這與我們前面講解的STM32閃存的編程每次必須寫(xiě)入16位并不矛盾。寫(xiě)入8位實(shí)際也是占用的兩個(gè)地址了,跟寫(xiě)入16位基本上沒(méi)啥區別。
3.擦除函數
固件庫提供三個(gè)FLASH擦除函數:
FLASH_StatusFLASH_ErasePage(uint32_tPage_Address);
FLASH_StatusFLASH_EraseAllPages(void);
FLASH_StatusFLASH_EraseOptionBytes(void);
這三個(gè)函數可以顧名思義了,非常簡(jiǎn)單。
4.獲取FLASH狀態(tài)
主要是用的函數是:
FLASH_StatusFLASH_GetStatus(void);
返回值是通過(guò)枚舉類(lèi)型定義的:
typedefenum
{
  FLASH_BUSY=1,//忙
  FLASH_ERROR_PG,//編程錯誤
  FLASH_ERROR_WRP,//寫(xiě)保護錯誤
  FLASH_COMPLETE,//操作完成
  FLASH_TIMEOUT//操作超時(shí)
}FLASH_Status;
從這里面我們可以看到FLASH操作的5個(gè)狀態(tài),每個(gè)代表的意思我們在后面注釋了。
5.等待操作完成函數
在執行閃存寫(xiě)操作時(shí),任何對閃存的讀操作都會(huì )鎖住總線(xiàn),在寫(xiě)操作完成后讀操作才能正確地進(jìn)行;既在進(jìn)行寫(xiě)或擦除操作時(shí),不能進(jìn)行代碼或數據的讀取操作。所以在每次操作之前,我們都要等待上一次操作完成這次操作才能開(kāi)始。使用的函數是:
FLASH_StatusFLASH_WaitForLastOperation(uint32_tTimeout)
入口參數為等待時(shí)間,返回值是FLASH的狀態(tài),這個(gè)很容易理解,這個(gè)函數本身我們在固件庫中使用得不多,但是在固件庫函數體中間可以多次看到。
6.讀FLASH特定地址數據函數
有寫(xiě)就必定有讀,而讀取FLASH指定地址的半字的函數固件庫并沒(méi)有給出來(lái),這里我們自己寫(xiě)的一個(gè)函數:
u16STMFLASH_ReadHalfWord(u32faddr)
{
return*(vu16*)faddr;
}


而流程就是

觸發(fā)條件----àFlashunlockàserialdown--àflashlock
看了半天,原來(lái)只要幾句就可以解決,當然是不考慮其他功能,只是簡(jiǎn)單的讀寫(xiě)操作。
其中寫(xiě)操作如下:
FLASH_Unlock();//解鎖FLASH編程擦除控制器
FLASH_ClearFlag(FLASH_FLAG_BSY|FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR);//清除標志位
/*********************************************************************************
// FLASH_FLAG_BSY FLASH忙標志位
// FLASH_FLAG_EOP FLASH操作結束標志位
// FLASH_FLAG_PGERR FLASH編寫(xiě)錯誤標志位
// FLASH_FLAG_WRPRTERR FLASH頁(yè)面寫(xiě)保護錯誤標凈
**********************************************************************************/
FLASH_ErasePage(FLASH_START_ADDR); //擦除指定地址頁(yè)
FLASH_ProgramHalfWord(FLASH_START_ADDR+(addr+i)*2,dat); //從指定頁(yè)的addr地址開(kāi)始寫(xiě)
FLASH_ClearFlag(FLASH_FLAG_BSY|FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR);//清除標志位
FLASH_Lock(); //鎖定FLASH編程擦除控制器

從上面可以看出基本順序是:解鎖-》清除標志位(可以不要)-》擦除-》寫(xiě)半字16位-》清楚標志位(也可以不要)-》上鎖。其中FLASH_START_ADDR是宏定義的0x8000000+2048*255,0x8000000是Flash的起始地址,2048是因為我用的是大容量芯片,根據上一筆記Flash地址可以看出芯片每頁(yè)容量2K,即2048字節,255表示芯片的最后一頁(yè),這個(gè)根據不同芯片而定。之所以從后面頁(yè)寫(xiě)起可以防止儲存數據破壞用戶(hù)程序。addr*2是因為每個(gè)數據占用2字節(半字),雖然寫(xiě)入的是1字節數據,但是編程是2字節為單位,也就是說(shuō)一個(gè)字節的數據也會(huì )占用兩個(gè)字節地址。
用YMODEM協(xié)議(ymodem協(xié)議自己腦補)燒寫(xiě)會(huì )用到flasheraser,剩下的就是要寫(xiě)的數據地址,數據包大小處理,怎么寫(xiě)到每一頁(yè)去,以后更新!


關(guān)鍵詞: stm32flash寫(xiě)數據eero

評論


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

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>