日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

STM32的Flash

發布時間:2023/12/20 编程问答 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 STM32的Flash 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

STM32中存儲區分為:隨機存取存儲器RAM只讀存儲器ROM。?
其中:

  • RAM為常說的內存,比如手機的2G內存4G內存等,就是程序跑起來的時候所占用的存儲空間,特點是掉電數據丟失
  • ROM為常說的硬盤,比如手機的64G和128G等,可以簡單的理解為硬盤的存儲空間,特點是掉電數據不丟失,所以又叫“非易失性存儲器件”。?
    • ROM又包含:EEPROM和flash。

畫個嵌入式產品存儲器件的思維導圖如下(如有什么地方不對,懇請大神們進行指正):?

作為ROM的一份子,flash的特點自然是掉電數據不丟失。但是,flash在STM32中比較重要,程序也是保存在這個地方,所以輕易不讓用戶進行隨意的讀寫,以避免不必要的問題。

而這篇博客就先簡單記錄一下flash的訪問流程和方法(讀和寫),具體原理以后理解深刻了再做補充。

1、STM32 FLASH操作流程

Flash操作已經屬于嵌入式設備中很底層的操作了,直接對地址進行存取,簡單描述,Flash操作大致需要以下流程:

  • 1、確定要寫入Flash的首地址(稍后介紹確定地址的方法)
  • 2、解鎖Flash
  • 3、對Flash進行操作(寫入數據)
  • 4、對Flash重新上鎖

1.1 如何查找并選定要寫入Flash十六進制地址值的方法

要想選定安全的Flash地址進行讀寫,可以根據自己的STM32 MCU型號,查找數據手冊,確定FLASH的地址區段,因為起始段會存儲代碼,所以一定要避開起始段,以避免數據錯誤。(我一般是根據Flash大小計算Flash的最末尾地址,往前推一段地址空間,在這里一般不會對代碼中的數據產生覆蓋等影響)

我此次操作Flash使用的MCU是STM32103C8T6,所以以該型號MCU為例進行描述:

  • 在數據手冊中,可以看到STM32103C8T6的flash起始地址是0x0800 0000(如下圖所示),而STM32103C8T6的Flash大小為64K,可以計算出STM32103C8T6的Flash地址范圍是:0x0800 0000——0x0800 FFFF(計算方法參考另一篇博客:STM32內存大小與地址的對應關系以及計算方法)。這里選取0x0800 F000作為讀寫操作的起始地址,對于C8T6這款MCU,操作這個起始地址應該算是很安全的范圍了。?

2、Flash基本知識點

2.1 Flash容量

Flash根據容量大小可以分為以下三種:

  • 1、小容量產品:Flash大小為1-32KB(STM32F10X_LD)
  • 2、中容量產品:Flash大小為64-128KB(STM32F10X_MD)
  • 3、大容量產品:Flash大小為256KB以上(STM32F10X_HD)

2.2 ST庫對Flash操作的支持

ST庫中對Flash操作主要提供了以下幾類操作API函數:

  • 1、Flash解鎖、鎖定函數?
    • void FLASH_Unlock(void);//解鎖函數:在對Flash操作之前必須解鎖
    • void FLASH_Lock(void);//鎖定函數:同理,操作完Flash之后必須重新上鎖
  • 2、Flash寫操作函數?
    • FLASH_Status FLASH_ProgramWord(uint32_t Address, uint32_t Data);//32位字寫入函數
    • FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data);//16位半字寫入函數
    • FLASH_Status FLASH_ProgramOptionByteData(uint32_t Address, uint8_t Data);//用戶選擇字節寫入函數?
      注:這里需要說明,32 位字節寫入實際上是寫入的兩次 16 位數據,寫完第一次后地址+2,這與我們前面講解的 STM32 閃存的編程每次必須寫入 16 位并不矛盾。寫入 8位實際也是占用的兩個地址了,跟寫入 16 位基本上沒啥區別。
  • 3、Flash擦除函數?
    • FLASH_Status FLASH_ErasePage(uint32_t Page_Address);
    • FLASH_Status FLASH_EraseAllPages(void);
    • FLASH_Status FLASH_EraseOptionBytes(void);
  • 4、獲取Flash狀態?
    • FLASH_Status FLASH_GetStatus(void);?
      獲取Flash狀態函數,主要是為了獲取Flash的狀態,以便于根據狀態對Flash進行操作。該函數返回值是通過枚舉類型定義的,在代碼中可以看到FLASH_Status類型定義如下(具體含義看注釋即可):
    • ?????????????????????????????????????????????????typedef enum?
      ?????????????????????????????????????????????????{?
      ?????????????????????????????????????????????????   FLASH_BUSY = 1, ???????//忙?
      ?????????????????????????????????????????????????   FLASH_ERROR_PG, ?????//編程錯誤?
      ?????????????????????????????????????????????????   FLASH_ERROR_WRP,?? //寫保護錯誤?
      ?????????????????????????????????????????????????   FLASH_COMPLETE, ?????//操作完成?
      ?????????????????????????????????????????????????   FLASH_TIMEOUT ????????//操作超時?
      ????????????????????????????????????????????????? }FLASH_Status;
  • 5、等待操作完成函數?
    • FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout);?
      注:在執行閃存寫操作時,任何對閃存的讀操作都會鎖住總線,在寫操作完成后讀操作才能正確地進行;既在進行寫或擦除操作時,不能進行代碼或數據的讀取操作。所以在每次操作之前,我們都要等待上一次操作完成這次操作才能開始。

3、OK,上干貨,上代碼

根據ST庫提供的上述函數,我們可以自己編寫Flash的讀寫操作代碼如下:

3.1 先定義一個Flash操作的起始地址宏定義Flash狀態指示標志位

#define STARTADDR 0x0800F000 //STM32F103C8T6適用volatile FLASH_Status FLASHStatus = FLASH_BUSY; //Flash操作狀態變量

?

3.2 編寫各個讀寫函數

// // Name: WriteFlashOneWord // // Function: 向內部Flash寫入32位數據 // // Input: WriteAddress:數據要寫入的目標地址(偏移地址) // WriteData: 寫入的數據 // void WriteFlashOneWord(uint32_t WriteAddress, uint32_t WriteData) { FLASH_UnlockBank1();FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);FLASHStatus = 1; //清空狀態指示標志位FLASHStatus = FLASH_ErasePage(STARTADDR); if(FLASHStatus == FLASH_COMPLETE) { FLASHStatus = 1; //清空狀態指示標志位FLASHStatus = FLASH_ProgramWord(STARTADDR+WriteAddress, WriteData); //flash.c 中API函數}FLASHStatus = 1; //清空狀態指示標志位FLASH_LockBank1(); }// // Name: WriteFlashData // // Function: 向內部Flash寫入數據 // // Input: WriteAddress:數據要寫入的目標地址(偏移地址) // data[]: 寫入的數據首地址 // num: 寫入數據的個數 // void WriteFlashData(uint32_t WriteAddress, uint8_t data[], uint32_t num) {uint32_t i = 0;uint16_t temp = 0;FLASH_UnlockBank1(); //解鎖flashFLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR); FLASHStatus = 1; //清空狀態指示標志位FLASHStatus = FLASH_ErasePage(STARTADDR);//擦除整頁if(FLASHStatus == FLASH_COMPLETE)//flash操作完成{FLASHStatus = 1; //清空狀態指示標志位for(i=0; i<num; i++){temp = (uint16_t)data[i];FLASHStatus = FLASH_ProgramHalfWord(STARTADDR+WriteAddress+i*2, temp);//寫入數據}}FLASHStatus = 1; //清空狀態指示標志位FLASH_LockBank1(); //鎖定flash }
// // Name: ReadFlashNBtye // // Function: 從內部Flash讀取N字節數據 // // Input: ReadAddress:數據地址(偏移地址) // ReadBuf:讀取到的數據存放位置指針 // ReadNum:讀取字節個數 // // Output: 讀取的字節數 // int ReadFlashNBtye(uint32_t ReadAddress, uint8_t *ReadBuf, int32_t ReadNum) { int DataNum = 0;ReadAddress = (uint32_t)STARTADDR + ReadAddress; while(DataNum < ReadNum) { *(ReadBuf + DataNum) = *(__IO uint8_t*) ReadAddress++; DataNum++; }return DataNum; }// // Name: ReadFlashData // // Function: 從內部Flash讀取num字節數據 // // Input: ReadAddress:數據地址(偏移地址) // dest_Data: 讀取到的數據存放位置指針 // num: 讀取字節個數 // void ReadFlashData(uint32_t ReadAddress, uint8_t *dest_Data, uint32_t num) {int i = 0;ReadAddress = (uint32_t)STARTADDR + ReadAddress; while(i < num) {*(dest_Data+i) = *(__IO uint16_t*) ReadAddress;ReadAddress += 2;i++;} }來源:https://blog.csdn.net/Ace_Shiyuan/article/details/78196648

總結

以上是生活随笔為你收集整理的STM32的Flash的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。