STM32學習筆記19-FLASH

FLASH簡介

  • STM32F1系列的FLASH包含程序存儲器、系統存儲器和選項字節三個部分,通過閃存存儲器接口(外設)可以對程序存儲器和選項字節進行擦除和編程,讀取指定寄存器直接使用指針讀即可

  • 讀寫FLASH的用途:

?????? ?????? 利用程序存儲器的剩余空間來保存掉電不丟失的用戶數據

?????? ?????? 通過在程序中編程(IAP),實現程序的自我更新,類似于OTA

  • 在線編程(In-Circuit Programming – ICP)用于更新程序存儲器的全部內容,它通過JTAG、SWD協議或系統加載程序(Bootloader)下載程序
  • 在程序中編程(In-Application Programming – IAP)可以使用微控制器支持的任一種通信接口下載程序

STM32F10xxx閃存編程參考手冊

閃存模塊組織

????????特征與W25Q64類似

?????? 這里的存儲器分化:只有一個頁,每頁大小都是1K字節。地址范圍:起始地址:只要以000、400、800、C00結尾的。

FLASH基本結構

FLASH解鎖

  • FPEC共有三個鍵值:

?????????????? RDPRT鍵 = 0x000000A5——解除讀保護的密鑰

????????????????KEY1 = 0x45670123——這是自定義的密碼

? ? ? ? ? ????? KEY2 = 0xCDEF89AB

  • 解鎖:

?????????????? 復位后,FPEC被保護,不能寫入FLASH_CR

?????????????? 在FLASH_KEYR先寫入KEY1,再寫入KEY2,解鎖

?????????????? 錯誤的操作序列會在下次復位前鎖死FPEC和FLASH_CR

  • 加鎖:

?????????????? 設置FLASH_CR中的LOCK位鎖住FPEC和FLASH_CR

讀取:

使用指針訪問存儲器,因為STM32的內部存儲器是掛載在總線上的

  • 使用指針讀指定地址下的存儲器:
?????? uint16_t Data = *((__IO uint16_t *)(0x08000000));
  • 使用指針寫指定地址下的存儲器:——需要解鎖等提高權限
???? *((__IO uint16_t *)(0x08000000)) = 0x1234;
  • 其中:
?? #define ?__IO? volatile????? //防止編譯器優化

程序存儲器編程

程序存儲器頁擦除

程序存儲器全擦除

選項字節

  • RDP:寫入RDPRT鍵(0x000000A5)后解除讀保護
  • USER:配置硬件看門狗和進入停機/待機模式是否產生復位
  • Data0/1:用戶可自定義使用
  • WRP0/1/2/3:配置寫保護,每一個位對應保護4個存儲頁(中容量)
  • 帶n,當寫入USER時要同時在nUSET寫入數據的反碼,這樣才是有效的——一般函數會自動執行

選項字節編程

  • 解鎖閃存
  • 檢查FLASH_SR的BSY位,以確認沒有其他正在進行的編程操作
  • 解鎖FLASH_CR的OPTWRE位
  • 設置FLASH_CR的OPTPG位為1
  • 寫入要編程的半字到指定的地址
  • 等待BSY位變為0
  • 讀出寫入的地址并驗證數據

選項字節擦除

  • 解鎖閃存
  • 檢查FLASH_SR的BSY位,以確認沒有其他正在進行的閃存操作
  • 解鎖FLASH_CR的OPTWRE位
  • 設置FLASH_CR的OPTER位為1
  • 設置FLASH_CR的STRT位為1
  • 等待BSY位變為0
  • 讀出被擦除的選擇字節并做驗證

器件電子簽名

  • 電子簽名存放在閃存存儲器模塊的系統存儲區域,包含的芯片識別信息在出廠時編寫,不可更改,使用指針讀指定地址下的存儲器可獲取電子簽名
  • 閃存容量寄存器:

?????? ?????? 基地址:0x1FFF F7E0

?????? ?????? 大小:16位

  • 產品唯一身份標識寄存器:

?????? ?????? 基地址: 0x1FFF F7E8

?????? ?????? 大小:96位

接線圖:

15-1 讀寫內部FLASH

最底層模塊MyFALSH實現讀取、擦除和編程

再此模塊上建Store模塊,實現參數數據的讀寫和存儲管理:任意讀寫參數,并且這些參數是掉電不丟失的-定義SRAM數組,把需要掉電不丟失的數據放入到SRAM中,之后調用保存的函數使SRAM數組自動備份到閃存里;上電后,Store初始化,自動會把閃存里的數據讀回SRAM數組里——閃存管理策略

使用STM32 ST-LINK Utility進行調試:可以看到閃存里的數據;

?????? 注:使用完,記得斷開連接不然設備占用,導致程序運行不了

思路:

閃存不需要初始化

讀取:直接使用指針

擦除:先解鎖,調用全擦除函數或頁擦除函數,之后加鎖

編程:先解鎖,調用函數,之后加鎖

選項字節的操作與閃存類似,有對應的函數,但是同時是用軟件進行圖形化修改

FLASH相關函數:系統分為三大部分的庫函數——對應不同的配置,此實驗只用第一部分

void FLASH_Unlock(void);?????????? //解鎖

void FLASH_Lock(void);????????????? //加鎖

//對主閃存和選項字節的操作配置,返回值FLASH_Status一個執行狀態

FLASH_Status FLASH_ErasePage(uint32_t Page_Address);???????????? //閃存擦除某一頁

FLASH_Status FLASH_EraseAllPages(void);????????????? //全擦除

FLASH_Status FLASH_EraseOptionBytes(void);??????? //擦除選項字節

FLASH_Status FLASH_ProgramWord(uint32_t Address, uint32_t Data); ?????? //在指定地址寫入字

FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data); ?????? //在指定地址寫入半字

//選項字節的寫入

FLASH_Status FLASH_ProgramOptionByteData(uint32_t Address, uint8_t Data);??????????? //自定義的Data0和Data1

FLASH_Status FLASH_EnableWriteProtection(uint32_t FLASH_Pages);?? ?????? //寫保護

FLASH_Status FLASH_ReadOutProtection(FunctionalState NewState);? ?????? //讀保護

FLASH_Status FLASH_UserOptionByteConfig(uint16_t OB_IWDG, uint16_t OB_STOP, uint16_t OB_STDBY);???????? //用戶選項的三個配置位

//獲取選項字節當前的狀態

uint32_t FLASH_GetUserOptionByte(void);?????? //獲取用戶選項的三個配置位

uint32_t FLASH_GetWriteProtectionOptionByte(void); ????????? //獲取寫保護

FlagStatus FLASH_GetReadOutProtectionStatus(void); ???????? //獲取寫保護

//狀態位

FlagStatus FLASH_GetFlagStatus(uint32_t FLASH_FLAG);

void FLASH_ClearFlag(uint32_t FLASH_FLAG);

FLASH_Status FLASH_GetStatus(void);???????????? //獲取狀態

FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout);?????????? 等待上一次操作——在前面的函數中自調用了,一般不需要單獨調用


配置閃存地址空間——keil魔術棒里Debug對應設備的接口

手動分配閃存尾部的數據空間,給自己用;

擦除模式


判斷程序大小

分別是:代碼;只讀數據、讀寫數據、零初始化數據


main.c
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Store.h"
#include "Key.h"uint8_t KeyNum;					//定義用于接收按鍵鍵碼的變量int main(void)
{/*模塊初始化*/OLED_Init();				//OLED初始化Key_Init();					//按鍵初始化Store_Init();				//參數存儲模塊初始化,在上電的時候將閃存的數據加載回Store_Data,實現掉電不丟失/*顯示靜態字符串*/OLED_ShowString(1, 1, "Flag:");OLED_ShowString(2, 1, "Data:");while (1){KeyNum = Key_GetNum();		//獲取按鍵鍵碼if (KeyNum == 1)			//按鍵1按下{Store_Data[1] ++;		//變換測試數據Store_Data[2] += 2;Store_Data[3] += 3;Store_Data[4] += 4;Store_Save();			//將Store_Data的數據備份保存到閃存,實現掉電不丟失}if (KeyNum == 2)			//按鍵2按下{Store_Clear();			//將Store_Data的數據全部清0}OLED_ShowHexNum(1, 6, Store_Data[0], 4);	//顯示Store_Data的第一位標志位OLED_ShowHexNum(3, 1, Store_Data[1], 4);	//顯示Store_Data的有效存儲數據OLED_ShowHexNum(3, 6, Store_Data[2], 4);OLED_ShowHexNum(4, 1, Store_Data[3], 4);OLED_ShowHexNum(4, 6, Store_Data[4], 4);}
}
Store.c
#include "stm32f10x.h"                  // Device header
#include "MyFLASH.h"#define STORE_START_ADDRESS		0x0800FC00		//存儲的起始地址
#define STORE_COUNT				512				//存儲數據的個數uint16_t Store_Data[STORE_COUNT];				//定義SRAM數組/*** 函    數:參數存儲模塊初始化* 參    數:無* 返 回 值:無*/
void Store_Init(void)
{/*判斷是不是第一次使用*/if (MyFLASH_ReadHalfWord(STORE_START_ADDRESS) != 0xA5A5)	//讀取第一個半字的標志位,if成立,則執行第一次使用的初始化{MyFLASH_ErasePage(STORE_START_ADDRESS);					//擦除指定頁MyFLASH_ProgramHalfWord(STORE_START_ADDRESS, 0xA5A5);	//在第一個半字寫入自己規定的標志位,用于判斷是不是第一次使用for (uint16_t i = 1; i < STORE_COUNT; i ++)				//循環STORE_COUNT次,除了第一個標志位{MyFLASH_ProgramHalfWord(STORE_START_ADDRESS + i * 2, 0x0000);		//除了標志位的有效數據全部清0}}/*上電時,將閃存數據加載回SRAM數組,實現SRAM數組的掉電不丟失*/for (uint16_t i = 0; i < STORE_COUNT; i ++)					//循環STORE_COUNT次,包括第一個標志位{Store_Data[i] = MyFLASH_ReadHalfWord(STORE_START_ADDRESS + i * 2);		//將閃存的數據加載回SRAM數組}
}/*** 函    數:參數存儲模塊保存數據到閃存* 參    數:無* 返 回 值:無*/
void Store_Save(void)
{MyFLASH_ErasePage(STORE_START_ADDRESS);				//擦除指定頁for (uint16_t i = 0; i < STORE_COUNT; i ++)			//循環STORE_COUNT次,包括第一個標志位{MyFLASH_ProgramHalfWord(STORE_START_ADDRESS + i * 2, Store_Data[i]);	//將SRAM數組的數據備份保存到閃存}
}/*** 函    數:參數存儲模塊將所有有效數據清0* 參    數:無* 返 回 值:無*/
void Store_Clear(void)
{for (uint16_t i = 1; i < STORE_COUNT; i ++)			//循環STORE_COUNT次,除了第一個標志位{Store_Data[i] = 0x0000;							//SRAM數組有效數據清0}Store_Save();										//保存數據到閃存
}MyFLASH.c
#include "stm32f10x.h"                  // Device header/*** 函    數:FLASH讀取一個32位的字* 參    數:Address 要讀取數據的字地址* 返 回 值:指定地址下的數據*/
uint32_t MyFLASH_ReadWord(uint32_t Address)
{return *((__IO uint32_t *)(Address));	//使用指針訪問指定地址下的數據并返回
}/*** 函    數:FLASH讀取一個16位的半字* 參    數:Address 要讀取數據的半字地址* 返 回 值:指定地址下的數據*/
uint16_t MyFLASH_ReadHalfWord(uint32_t Address)
{return *((__IO uint16_t *)(Address));	//使用指針訪問指定地址下的數據并返回
}/*** 函    數:FLASH讀取一個8位的字節* 參    數:Address 要讀取數據的字節地址* 返 回 值:指定地址下的數據*/
uint8_t MyFLASH_ReadByte(uint32_t Address)
{return *((__IO uint8_t *)(Address));	//使用指針訪問指定地址下的數據并返回
}/*** 函    數:FLASH全擦除* 參    數:無* 返 回 值:無* 說    明:調用此函數后,FLASH的所有頁都會被擦除,包括程序文件本身,擦除后,程序將不復存在*/
void MyFLASH_EraseAllPages(void)
{FLASH_Unlock();					//解鎖FLASH_EraseAllPages();			//全擦除FLASH_Lock();					//加鎖
}/*** 函    數:FLASH頁擦除* 參    數:PageAddress 要擦除頁的頁地址* 返 回 值:無*/
void MyFLASH_ErasePage(uint32_t PageAddress)
{FLASH_Unlock();					//解鎖FLASH_ErasePage(PageAddress);	//頁擦除FLASH_Lock();					//加鎖
}/*** 函    數:FLASH編程字* 參    數:Address 要寫入數據的字地址* 參    數:Data 要寫入的32位數據* 返 回 值:無*/
void MyFLASH_ProgramWord(uint32_t Address, uint32_t Data)
{FLASH_Unlock();							//解鎖FLASH_ProgramWord(Address, Data);		//編程字FLASH_Lock();							//加鎖
}/*** 函    數:FLASH編程半字* 參    數:Address 要寫入數據的半字地址* 參    數:Data 要寫入的16位數據* 返 回 值:無*/
void MyFLASH_ProgramHalfWord(uint32_t Address, uint16_t Data)
{FLASH_Unlock();							//解鎖FLASH_ProgramHalfWord(Address, Data);	//編程半字FLASH_Lock();							//加鎖
}

15-2 讀取芯片ID

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
//#include "OLED_Font.h"
//4-1 OLED顯示屏
int main(void){OLED_Init();OLED_ShowString(1,1,"F_SIZE:");OLED_ShowHexNum(1,8,*((__IO uint16_t *)(0x1FFFF7E0)),4);//ID地址:0x1FFFF7E0//顯示UIDOLED_ShowString(2,1,"UID:");//偏移量OLED_ShowHexNum(2,6,*((__IO uint16_t *)(0x1FFFF7E8)),4);OLED_ShowHexNum(2,11,*((__IO uint16_t *)(0x1FFFF7E8+0x02)),4);OLED_ShowHexNum(3,1,*((__IO uint32_t *)(0x1FFFF7E8+0x04)),8);OLED_ShowHexNum(4,1,*((__IO uint32_t *)(0x1FFFF7E8+0x08)),8);while(1){}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/94192.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/94192.shtml
英文地址,請注明出處:http://en.pswp.cn/web/94192.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

電蚊拍的原理及電壓電容參數深度解析:從高頻振蕩到倍壓整流的完整技術剖析

1. 引言在炎炎夏日&#xff0c;蚊蟲成為人們生活中的一大困擾。電蚊拍作為一種高效、環保的物理滅蚊工具&#xff0c;憑借其便攜性和實用性在全球范圍內得到了廣泛應用。然而&#xff0c;許多用戶對這種看似簡單的小家電背后的工作原理知之甚少。電蚊拍是一種新型的滅蚊小家電&…

Mac簡單測試硬盤讀寫速度

一、下載軟件 Blackmagic Disk Speed Test 「達芬奇 磁盤速度測試」二、選中測試位置可以隨便選個文件比如“下載”目錄三、開始測速

? 零 ? ? 安全體系構建內容結構

&#x1f44d;點「贊」&#x1f4cc;收「藏」&#x1f440;關「注」&#x1f4ac;評「論」在金融科技深度融合的背景下&#xff0c;信息安全已從單純的技術攻防擴展至架構、合規、流程與創新的系統工程。作為一名從業十多年的老兵&#xff0c;系統闡述數字銀行安全體系的建設路…

XP系統安裝Android Studio 3.5.3并建立Java或Native C++工程,然后在安卓手機上運行

第一節 安裝Android Studio 3.5.3Android Studio 3.5.3下載地址&#xff1a;Android Studio 3.5.3 December 5, 2019 Windows (32-bit): android-studio-ide-191.6010548-windows32.zip (756.1 MB) https://redirector.gvt1.com/edgedl/android/studio/ide-zips/3.5.3.0/androi…

calchash.exe和chckhash.exe計算pe文件hash值的兩個實用小工具

第一部分&#xff1a; C:\WINDOWS\system32\CatRoot\{F750E6C3-38EE-11D1-85E5-00C04FC295EE}\NT5.CAT t部分內容B B D 0 2 2 2 1 A A 6 5 5 6 2 8 F 4 9 5 F 6 C D 3 0 3 9 0 8 B B E 0 0 F 9 5 9 5 第二部分&#xff1a; D:\>calchash.exe pidgen.dll BB D0 22 21 AA 65 …

lanczso算法中的額外正交化代碼解釋

額外正交化 定義&#xff1a;在Lanczos算法中&#xff0c;由于浮點誤差&#xff0c;生成的向量可能不完全正交&#xff0c;需要額外正交化步驟。代碼實現&#xff1a;def extra_orthogonalization(v, basis):for u in basis:v - u * (v.dot(u) / u.dot(u))

Rabbit 實戰指南-學習筆記

第 4 章 RabbitMQ 進階 mandatory 參數 Returning | RabbitMQ 當 mandatory 參數設為 true 時&#xff0c;交換器無法根據自身的類型和路由鍵找到一個符合條件的隊列&#xff0c;那么RabbitMQ 會調用 Basic.Return 命令將消息返回給生產者,通過調用channel.addReturnListener …

BEVDet4D

1. BEVDet4D算法動機及開創性思路 1&#xff09;BEVDet算法概述輸入輸出&#xff1a;輸入為6視角圖像&#xff08;NuScenes數據集&#xff09;&#xff0c;輸出為3D檢測結果核心模塊&#xff1a; 圖像編碼器&#xff1a;由Backbone網絡和多尺度特征融合網絡組成&#xff0c;處理…

當 AI 學會 “理解” 人類:自然語言處理的進化與倫理邊界

大家可以去我的資源看看&#xff0c;有很多關于AI的免費資源可以下載&#xff0c;不下載也可以看看&#xff0c;真的對你有用引言&#xff1a;從 “對話” 到 “理解”——AI 語言能力的時代躍遷現實錨點&#xff1a;以日常場景切入&#xff08;如 ChatGPT 流暢回應復雜問題、A…

WPF控件隨窗體大寬度高度改變而改變

前臺控件中&#xff1a;Width"{Binding RelativeSource{RelativeSource AncestorTypeWindow}, PathWidth}"后臺代碼&#xff1a;定義在加載事件里面this.SizeChanged ProductData_SizeChanged;private void ProductData_SizeChanged(object sender, SizeChangedEven…

E10 通過RPC實現賬號批量鎖定與解鎖

需求背景&#xff1a;賬號信息由三方系統管理&#xff0c;包含賬號狀態&#xff0c;所以需要通過提供給三方的 Rest 接口中&#xff0c;實現賬號鎖定與解鎖。參考基線版本&#xff1a;10.0.2506.01&#xff0c;過低的版本可能無法使用。 鎖定分為兩種&#xff1a; &#xff08;…

什么是AI寵物

什么是AI寵物AI寵物是由AI大腦驅動的生命體AI產品。它能主動產生情緒和意圖&#xff0c;并通過情緒和意圖去驅動自己的動作和行為。它根據自己的意愿和用戶互動&#xff0c;不受用戶控制。從一定意義上講&#xff0c;它擁有了人工生命和自由意志。它有自己的行為邏輯&#xff0…

簡單AI:搜狐公司旗下AI繪畫產品

本文轉載自&#xff1a;簡單AI&#xff1a;搜狐公司旗下AI繪畫產品 - Hello123工具導航 ** 一、平臺定位與技術特性 搜狐簡單 AI 是搜狐推出的多模態 AI 創作平臺&#xff0c;基于自研大模型提供文生圖、文生文等能力。它專注于零門檻內容生成&#xff0c;用戶無需專業技能即…

vue3 3d餅圖

完整3D餅圖項目下載 https://download.csdn.net/download/weixin_54645059/91716476 只有一個vue文件 直接下滑到完整代碼就闊以 本文介紹了如何使用ECharts和ECharts-GL插件實現3D餅圖效果&#xff0c;并提出了數值顯示未解決的問題。主要包含以下內容&#xff1a; 安裝所需…

全球電商業財一體化趨勢加速,巨益科技助力品牌出海精細化運營

行業背景&#xff1a;跨境電商進入品牌化發展新階段隨著國內電商市場競爭日趨激烈&#xff0c;跨境電商已成為中國品牌尋求增長突破的重要賽道&#xff0c;在TikTok、Temu等平臺出海浪潮推動下&#xff0c;越來越多的中國品牌開始布局全球市場。然而&#xff0c;從單一市場的鋪…

【序列晉升】13 Spring Cloud Bus微服務架構中的消息總線

Spring Cloud Bus作為微服務架構中的關鍵組件&#xff0c;通過消息代理實現分布式系統中各節點的事件廣播與狀態同步&#xff0c;解決了傳統微服務架構中配置刷新效率低下、系統級事件傳播復雜等問題。它本質上是一個輕量級的事件總線&#xff0c;將Spring Boot Actuator的端點…

[激光原理與應用-314]:光學設計 - 光學系統設計與電子電路設計的相似或相同點

光學系統設計與電子電路設計雖分屬不同工程領域&#xff0c;但在設計理念、方法論和工程實踐中存在諸多相似或相同點。這些共性源于兩者均需解決復雜系統的優化問題&#xff0c;并遵循工程設計的通用規律。以下是具體分析&#xff1a;一、設計流程的相似性需求分析與規格定義光…

Linux學習:信號的保存

目錄1. 進程的異常終止與core dump標志位1.1 進程終止的方式1.2 core方案的作用與使用方式2. 信號的保存2.1 信號的阻塞2.2 操作系統中的sigset_t信號集類型2.3 進程PCB中修改block表的系統調用接口2.4 信號阻塞的相關問題驗證1. 進程的異常終止與core dump標志位 1.1 進程終止…

數據分析編程第二步: 最簡單的數據分析嘗試

2.1 數據介紹有某公司的銷售數據表 sales.csv 如下:第一行是標題&#xff0c;解釋每一列存了什么東西。第二行開始每一行是一條數據&#xff0c;對應一個訂單。這種數據有個專業的術語&#xff0c;叫結構化數據。這是現代數據處理中最常見的數據類型。整個表格的數據統稱為一個…

UDP報文的數據結構

主要內容參照https://doc.embedfire.com/net/lwip/zh/latest/doc/chapter14/chapter14.html#id6&#xff0c;整理出來自用。 1. UDP 報文首部結構體&#xff08;udp_hdr&#xff09; 為清晰定義 UDP 報文首部的各個字段&#xff0c;LwIP 設計了udp_hdr結構體&#xff0c;其包含…