STM32讀寫內部FLASH讀取芯片id

文章目錄

  • 讀寫內部Flash
    • 接線
    • 程序編寫
    • 測試效果
    • 補充
  • 讀取芯片id
    • 代碼編寫


讀寫內部Flash

接線

在這里插入圖片描述

程序編寫

首先使用ThisFlash.c來寫入flash的基本操作,寫入、讀取、擦除,然后使用Store.c配合數組來進行主存與flash的交互
ThisFlash.c

#include "stm32f10x.h"                  // Device header
/*** @brief  讀取此地址一個字的數據* @param 	Address,頁地址* @retval 此地址的一個字的數據*/
uint32_t ThisFlash_ReadWord(uint32_t Address){return *((__IO uint32_t *)(Address));
}
/*** @brief  讀取此地址的半字數據* @param 	Address,頁地址* @retval 此地址的半字數據*/
uint16_t ThisFlash_ReadHalfWord(uint32_t Address){return *((__IO uint16_t *)(Address));
}
/*** @brief  讀取此地址一個字節的數據* @param 	Address,頁地址* @retval 此地址的一個字節的數據*/
uint8_t ThisFlash_ReadByte(uint32_t Address){return *((__IO uint8_t *)(Address));
}
/*** @brief  擦除整頁數據* @param 	無* @retval 無*/
void ThisFlash_EraseAllPages(void){FLASH_Unlock();	// 解鎖FLASH_EraseAllPages();	// 擦除所有頁FLASH_Lock();		// 重新上鎖
}
/*** @brief  擦除指定頁數據* @param 	無* @retval 無*/
void ThisFlash_ErasePage(uint32_t PageAddress){FLASH_Unlock();	// 解鎖FLASH_ErasePage(PageAddress);	// 擦除指定頁FLASH_Lock();		// 重新上鎖
}
/*** @brief  指定地址寫入一個字的數據* @param 	Address,頁地址		Data,數據* @retval 無*/
void ThisFlash_PragramWord(uint32_t Address,uint32_t Data){FLASH_Unlock();	// 解鎖FLASH_ProgramWord(Address,Data);	// 指定地址寫入一個字的數據FLASH_Lock();		// 重新上鎖
}
/*** @brief  指定地址寫入半字數據* @param 	Address,頁地址		Data,數據* @retval 無*/
void ThisFlash_PragramHalfWord(uint32_t Address,uint16_t Data){FLASH_Unlock();	// 解鎖FLASH_ProgramHalfWord(Address,Data);	// 指定地址寫入一個字的數據FLASH_Lock();		// 重新上鎖
}

ThisFlash.h

#ifndef __THISFLASH_H
#define __THISFLASH_H
uint32_t ThisFlash_ReadWord(uint32_t Address);
uint16_t ThisFlash_ReadHalfWord(uint32_t Address);
uint8_t ThisFlash_ReadByte(uint32_t Address);
void ThisFlash_EraseAllPages(void);
void ThisFlash_ErasePage(uint32_t PageAddress);
void ThisFlash_PragramWord(uint32_t Address,uint32_t Data);
void ThisFlash_PragramHalfWord(uint32_t Address,uint16_t Data);#endif

store.c

#include "stm32f10x.h"                  // Device header
#include "ThisFlash.h"// 用于與flash交互的數組,存儲與ram中
uint16_t Store_Data[512];/*** @brief  初始化最后一頁* @param 	無* @retval 無*/
void Store_Init(void){// 使用最后一頁第一個半字作為是否為第一次寫入的標志位if(ThisFlash_ReadHalfWord(0x0800fc00) != 0xa5a5){ThisFlash_ErasePage(0x0800fc00); 	// 第一次寫入,擦掉此頁數據ThisFlash_PragramHalfWord(0x0800fc00,0xa5a5);		// 寫入標志位for(uint16_t i=1;i<512;i++){ThisFlash_PragramHalfWord(0x0800fc00+i*2,0x0000);		}}for(uint16_t i=0;i<512;i++){Store_Data[i] = ThisFlash_ReadHalfWord(0x0800fc00+i*2);		// 寫入標志位}
}
/*** @brief  備份Store_Data到flash* @param 	無* @retval 無*/
void Store_Backup(void){ThisFlash_ErasePage(0x0800fc00);for(uint16_t i=0;i<512;i++){ThisFlash_PragramHalfWord(0x0800fc00+i*2,Store_Data[i]);		// 寫入標志位}
}
/*** @brief  擦除Store_Data并備份到flash* @param 	無* @retval 無*/
void Store_Clear(void){for(uint16_t i=0;i<512;i++){Store_Data[i] = 0x0000;		// 寫入標志位}Store_Backup();		// flash同步清空
}

store.h

#ifndef __STORE_H
#define	__STORE_H
extern uint16_t Store_Data[512];
void Store_Init(void);
void Store_Backup(void);
void Store_Clear(void);#endif

button.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"/*** @brief  初始化Button相關端口* @param 	無* @retval 無*/
void Button_Init(void){// 初始化時鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_11;	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		GPIO_Init(GPIOB, &GPIO_InitStructure);
}
/*** @brief  返回所按按鍵值* @param 	無* @retval KeyNum 按鍵值*/
uint8_t Key_Num(void){uint8_t KeyNum = 0;if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1)==0){Delay_ms(20);while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1)==0);Delay_ms(20);KeyNum = 1;}if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11)==0){Delay_ms(20);while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11)==0);Delay_ms(20);KeyNum = 11;}return KeyNum;
}

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Store.h"
#include "button.h"uint8_t KeyNum;int main(void)
{OLED_Init();Button_Init();Store_Init();// 為了不影響芯片的其他功能,在flash最后一頁寫入數據來測試while (1){KeyNum = Key_Num();if(KeyNum == 1){Store_Data[1] = 0x1314;Store_Data[3] = 0X3344;Store_Backup();}if(KeyNum == 11){Store_Clear();}OLED_ShowHexNum(1,1,Store_Data[1],4);OLED_ShowHexNum(2,1,Store_Data[3],4);	OLED_ShowString(3,1,"Flag:");OLED_ShowHexNum(3,7,Store_Data[0],4);}
}

測試效果

下載程序后按下b11的按鍵最后一頁數據清零,使用ST-LINK Utility查看
在這里插入圖片描述
然后按下復位鍵,初始化函數執行,標志位置a5a5(為小端對齊反式)
在這里插入圖片描述
然后按下b1按鍵,寫入數據到數組并備份到flash,并且掉電不丟失
在這里插入圖片描述

補充

還可以根據所需要的閃存空間來設置留給程序的閃存大小
在這里插入圖片描述

讀取芯片id

代碼編寫

根據手冊給出的器件id地址一一使用指針讀取

  • 顯示閃存大小

在這里插入圖片描述
顯示uid
在這里插入圖片描述
在這里插入圖片描述

main.c內容如下:

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"int main(void)
{OLED_Init();OLED_ShowString(1,1,"F_Size:");OLED_ShowHexNum(1,8,*((__IO uint16_t *)(0x1FFFF7E0)),4);OLED_ShowString(2,1,"U_ID:");OLED_ShowHexNum(2,8,*((__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(3,1,*((__IO uint32_t *)(0x1FFFF7E8+0x08)),8);while (1){}
}

在這里插入圖片描述


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

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

相關文章

為什么工控現場會用到Profinet轉Modbus網關設備

一、背景&#xff1a; 工控現場之所以需要使用Profinet轉Modbus網關&#xff0c;是因為工控系統中常常存在不同廠家設備之間通訊協議不一致的問題。而Modbus和Profinet分別代表著兩種不同的通信協議&#xff0c;Profinet通常用于較新的設備&#xff0c;而Modbus則是比較老的通…

思科防火墻ASA Version 9.1(1) 怎么配置靜態NAT,把內網ip192.168.1.10 端口1000映射到公網端口1000上?

環境: 思科防火墻5520 ASA Version 9.1(1) 問題描述: 思科防火墻ASA Version 9.1(1) 怎么配置靜態NAT,把內網ip192.168.1.10 端口1000映射到公網端口1000上? 解決方案: 舊版本8.0 1.做之前要先查一下有沒有端口被占用,要和業務確認2.sh Xlate | in 10011 端口 這條…

ch2應用層--計算機網絡期末復習

2.1應用層協議原理 網絡應用程序位于應用層 開發網絡應用程序: 寫出能夠在不同的端系統上通過網絡彼此通信的程序 2.1.1網絡應用程序體系結構分類: 客戶機/服務器結構 服務器: 總是打開(always-on)具有固定的、眾所周知的IP地址 主機群集常被用于創建強大的虛擬服務器 客…

MongoDB CRUD操作:快照查詢

MongoDB CRUD操作&#xff1a;快照查詢 文章目錄 MongoDB CRUD操作&#xff1a;快照查詢對比本地和快照的讀關注舉例從相同的時間點運行查詢從過去某個時刻讀取數據的一致狀態 配置快照保留時間磁盤空間和歷史記錄 使用快照查詢可以讀取最近某個時間點的數據&#xff0c;而且從…

基于51單片機的溫控風扇的設計–仿真設計

可實現通過DS18B20測量當前環境溫度 可實現通過溫度自動控制風扇轉速 可實現通過按鍵設置不同風速對應的溫度 可實現通過按鍵切換自動、手動模式 可實現在手動模式下通過按鍵調整風扇轉速 可實現通過LCD1602顯示溫度、風扇轉速擋位、自動/手動模式

【C++】模擬實現string類

&#x1f984;個人主頁:修修修也 &#x1f38f;所屬專欄:C ??操作環境:Visual Studio 2022 目錄 一.了解項目功能 二.逐步實現項目功能模塊及其邏輯詳解 &#x1f38f;構建成員變量 &#x1f38f;實現string類默認成員函數 &#x1f4cc;構造函數 &#x1f4cc;析構函數…

k8s 全面掌控日志系統

概述 為了提高系統運維和故障排查的效率&#xff0c; 日志系統采用 ELK&#xff08;Elasticsearch、Logstash、Kibana&#xff09;技術棧&#xff0c;通過 FileBeats 作為日志收集器&#xff0c;將來自不同節點的日志數據匯總并存儲在 Elasticsearch 中&#xff0c;最終通過 K…

創建一個新的Spring Security應用程序,并使用JDBC連接數據庫

創建一個新的Spring Security應用程序&#xff0c;并使用JDBC連接數據庫 在這個教程中&#xff0c;我們將學習如何創建一個新的Spring Security應用程序&#xff0c;使用JDBC連接數據庫以獲取用戶信息并進行認證。我們還將學習如何配置Spring Security以從數據庫中獲取用戶和權…

Vue3使用Composition API實現響應式

title: Vue3使用Composition API實現響應式 date: 2024/5/29 下午8:10:24 updated: 2024/5/29 下午8:10:24 categories: 前端開發 tags: Vue3CompositionRefsReactiveWatchLifecycleDebugging 1. 介紹 Composition API是Vue.js 3中新增的一組API&#xff0c;用于在組件中組…

SQL 語言:嵌入式 SQL 和動態 SQL

文章目錄 基本概述嵌入式 SQL動態 SQL總結 基本概述 嵌入式SQL和動態SQL是兩種在應用程序中嵌入和使用SQL語句的方法。它們都允許開發人員在編程語言中編寫SQL語句&#xff0c;以便在應用程序中執行數據庫操作。然而&#xff0c;這兩種方法在實現方式、性能和靈活性方面存在一…

Java數據結構與算法(紅黑樹)

前言 紅黑樹是一種自平衡二叉搜索樹&#xff0c;確保在插入和刪除操作后&#xff0c;樹的高度保持平衡&#xff0c;從而保證基本操作&#xff08;插入、刪除、查找&#xff09;的時間復雜度為O(log n)。 實現原理 紅黑樹具有以下性質&#xff1a; 每個節點要么是紅色&#…

go語言學習之旅之Go結構體

在Go語言中&#xff0c;結構體&#xff08;struct&#xff09;是一種用戶定義的數據類型&#xff0c;用于組合不同類型的數據項。結構體可以包含其他結構體或基本數據類型的字段。以下是關于Go語言結構體的基本知識&#xff1a; 定義結構體&#xff1a; package mainimport &…

Python 之微信指數小程序數據抓取

Fiddler安裝和設置 安裝 Fiddler 安裝包可以從這里獲取&#xff0c;如果失效了可以自己網上找一個安裝。 鏈接&#xff1a;https://pan.baidu.com/s/1N30BoDWm2_dBL8i8GRzK5g?pwd1znv 提取碼&#xff1a;1znv 然后就是點擊安裝就好了&#xff0c;沒什么好多說的。 啟用…

刷代碼隨想錄有感(83):貪心算法——最大子數組和

題干&#xff1a; 代碼&#xff1a; class Solution { public:int maxSubArray(vector<int>& nums) {int res INT_MIN;int count 0;for(int i 0; i < nums.size(); i){count nums[i];if(count > res) res count;if(count < 0)count 0;}return res;} …

【創作活動】探索 GPT-4o:下一代語言模型的技術革命

&#x1f604; 19年之后由于某些原因斷更了三年&#xff0c;23年重新揚帆起航&#xff0c;推出更多優質博文&#xff0c;希望大家多多支持&#xff5e; &#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有堅忍不拔之志 &#x1f390; 個人CSND主頁——Mi…

HTTP報文

HTTP報文 報文流 HTTP報文是在HTTP引用程序之間發送的數據塊&#xff0c;這些數據塊以一種文本形式的元信息開頭&#xff0c;這些信息描述了報文的內容和含義&#xff0c;后面跟著可選的數據部分&#xff0c;這些報文在客戶端&#xff0c;服務器和代理之間流動。 報文流入源…

git更改本地項目關聯到新倉庫

刪除現在遠程關聯的倉庫 git remote rm origin鏈接新倉庫 git remote add origin url(需要關聯的新倉庫地址)代碼提交到遠程倉庫master分支 git push --set-upstream origin master本地分支更新同步至遠程倉庫 比如本地有dev分支 git push origin dev:dev

前端項目開發,3個HTTP請求工具

這一小節&#xff0c;我們介紹一下前端項目開發中&#xff0c;HTTP請求會用到的3個工具&#xff0c;分別是fetch、axios和js-tool-big-box中的jsonp請求。那么他們都有哪些小區別呢&#xff1f;我們一起來看一下。 目錄 1 fetch 2 axios 3 js-tool-big-box 的 jsonp 請求 …

拷貝構造、移動構造、拷貝賦值、移動賦值

最近在學習C的拷貝構造函數時發現一個問題&#xff1a;在函數中返回局部的類對象時&#xff0c;并沒有調用拷貝構造函數。針對這個問題&#xff0c;查閱了一些資料&#xff0c;這里記錄整理一下。 調用拷貝構造函數的三種情況&#xff1a; ① 用一個類去初始化另一個對象時&a…

【數據結構與算法 | 基礎篇 | 隊列篇】力扣102, 107

1. 力扣102 : 二叉樹的層序遍歷 (1). 題 給你二叉樹的根節點 root &#xff0c;返回其節點值的 層序遍歷 。 &#xff08;即逐層地&#xff0c;從左到右訪問所有節點&#xff09;。 示例 1&#xff1a; 輸入&#xff1a;root [3,9,20,null,null,15,7] 輸出&#xff1a;[[3]…