STM32读写内部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)
	{
    
    
		
	}
}

在这里插入图片描述


猜你喜欢

转载自blog.csdn.net/qq_53922901/article/details/139300525