STM32-Flash闪存

目录

一、简介

1、闪存模块组织

2、FLASh基本结构

3、FLash写入和读取操作

4、编程流程

5、选项字节格式

6、选项字节编程步骤

二、读写芯片内部FLASH编程

三、器件电子签名

1、简介

2、编程实现


一、简介

  • STM32F1系列的FLASH包含程序存储器、系统存储器和选项字节三个部分,通过闪存存储器接口(外设)可以对程序存储器和选项字节进行擦除和编程
  • 读写FLASH的用途:利用程序存储器的剩余空间来保存掉电不丢失的用户数据;通过在程序中编程(IAP),实现程序的自我更新。
  • 在线编程(In-Circuit Programming -- ICP)用于更新程序存储器的全部内容,它通过JTAG、SWD协议或系统加载程序(Bootloader)下载下载程序
  • 在程序中编程(In-Application Programming -- IAP),可以使用微控制器支持的任一种通信接口下载程序
  • STM32F103C8T6 中Flash为64字节

ROM和RAM存储 :

1、闪存模块组织

主存储器利用页单元来存储数据,每个页的大小为1KByte,C8T6芯片64KByte ,所以只用了前64页。

启动程序代码即系统存储器,大小为2KByte

2、FLASh基本结构

3、FLash写入和读取操作

  • 先解锁

**FPEC(闪存编程/擦除控制器)**共有三个键值:

|--------|------------|
| 键 | 值 |
| RDPRT键 | 0x000000A5 |
| KEY1 | 0x45670123 |
| KEY2 | 0xCDEF89AB |

解锁:

复位后,FPEC被保护 ,不能写入FLASH_CR

在FLASH_KEYR先写入KEY1 ,再写入KEY2,解锁

错误的操作序列会在下次复位前锁死FPEC和FLASH_CR

加锁:

设置FLASH_CR中的LOCK位锁住FPEC和FLASH_CR

  • 读写
    • 使用指针 指定地址下的存储器: uint16_t Data = *((__IO uint16_t *)(0x08000000));
    • 使用指针指定地址下的存储器: *((__IO uint16_t *)(0x08000000)) = 0x1234;
    • 其中: #define __IO volatile

volatile告诉编译器这个变量是易变的,不要去优化它,每次必须从内存中读取。

4、编程流程

FLASH_CR寄存器中某位:

  • LOCK :锁,只能写'1'。 当该位为'1'时表示FPEC和FLASH_CR被锁住。在检测到正确的解 锁序列后,硬件清除此位为'0'。 在一次不成功的解锁操作后,下次系统复位前,该位不能再被改变。
  • PG:编程,选择编程操作,置'1'。
  • PER:页擦除,选择整页擦除,置'1'。
  • START:开始,当该位为1时将触发一次擦除操作。该位只可由软件置1,并在BSY变为'1'时,清为'0'。
  • MER:全擦除,选择擦除所有用户页,置'1'

FLASH_SR寄存器中某位:

  • BSY:忙,该位指示闪存操作正在进行。在闪存操作开始时,该位被设置为'1';在操作结束或发生错误时该位被清除为'0'

  • 编程过程

  • 闪存页擦除
  • 闪存全擦除

5、选项字节格式

每个选择位都在信息 块中有它的反码位,在装载选择位时反码位用于验证选择位是否正确,如果有任何的差别,将 产生一个选择字节错误标志(OPTERR)

  • RDP:写入RDPRT键(0x000000A5)后解除读保护
  • USER:配置硬件看门狗和进入停机/待机模式是否产生复位
  • Data0/1:用户可自定义使用 WRP0/1/2/3:配置写保护,每一个位对应保护4个存储页(中容量)

6、选项字节编程步骤

  • 选项字节编程
    • 检查FLASH_SR的BSY位,以确认没有其他正在进行的编程操作
    • 解锁FLASH_CR的OPTWRE(允许写选择字节),当该位为1时 ,允许对选择字节进行编程操作。当在FLASH_OPTKETR寄存器写入正确的键序列后,该位被置为'1'。软件可清除此位。
    • 设置FLASH_CR的OPTPG位为1
    • 写入要编程的半字到指定的地址
    • 等待BSY位变为0
    • 读出写入的地址并验证数据
  • 选项字节擦除
    • 检查FLASH_SR的BSY位,以确认没有其他正在进行的闪存操作
    • 解锁FLASH_CR的OPTWRE位
    • 设置FLASH_CR的OPTER位为1
    • 设置FLASH_CR的OPTER位为1
    • 等待BSY位变为0
    • 读出被擦除的选择字节并做验证

二、读写芯片内部FLASH编程

MyFlash.c:

cpp 复制代码
#include "stm32f10x.h"                  // Device header


uint32_t MyFlash_ReadWord(uint32_t Address)
{
	return *((__IO uint32_t *)(Address));     //32位
}

uint16_t MyFlash_ReadHalfWord(uint32_t Address)
{
	return *((__IO uint16_t *)(Address));
}

uint8_t MyFlash_ReadByte(uint32_t Address)
{
	return *((__IO uint16_t *)(Address));
}

void MyFlash_EraseAllPages(void)
{
	FLASH_Unlock();
   FLASH_EraseAllPages();
	FLASH_Lock();
	
}

void MyFlash_ErasePage(uint32_t PageAddress)
{
	FLASH_Unlock();
   FLASH_ErasePage(PageAddress);
	FLASH_Lock();
	
}

void MyFlash_ProgramWord(uint32_t Address,uint32_t Data)
{
	
	FLASH_Unlock();
   FLASH_ProgramWord(Address,Data);
	FLASH_Lock();
	
}

void MyFlash_ProgramHalfWord(uint32_t Address,uint16_t Data)
{
	
	FLASH_Unlock();
   FLASH_ProgramHalfWord(Address,Data);
	FLASH_Lock();
	
}

MyFlash.h:

cpp 复制代码
#ifndef _MYFLASH_H
#define _MYFLASH_H

uint32_t MyFlash_ReadWord(uint32_t Address);

uint16_t MyFlash_ReadHalfWord(uint32_t Address);

uint8_t MyFlash_ReadByte(uint32_t Address);

void MyFlash_EraseAllPages(void);


void MyFlash_ErasePage(uint32_t PageAddress);

void MyFlash_ProgramWord(uint32_t Address,uint32_t Data);

void MyFlash_ProgramHalfWord(uint32_t Address,uint16_t Data);

#endif

Store.c:

用来在Flash内部储存数据

cpp 复制代码
#include "stm32f10x.h"                  // Device header
#include  "MyFlash.h"

#define STORE_START_ADDRESS   0x0800FC00
#define STORE_COUNT  512


uint16_t Store_Data[STORE_COUNT];
uint16_t i=0;

void Store_Init(void)
{
	
	
	if(MyFlash_ReadHalfWord(STORE_START_ADDRESS)!=0xA5A5)
	{
		MyFlash_ErasePage(STORE_START_ADDRESS);
		MyFlash_ProgramHalfWord(STORE_START_ADDRESS,0xA5A5);
		for(i=1;i<STORE_COUNT;i++)
		{
			MyFlash_ProgramHalfWord(STORE_START_ADDRESS+i*2,0x0000);
		}
	}
	for(i=0;i<STORE_COUNT ;i++)
	{
		Store_Data[i]=MyFlash_ReadHalfWord(STORE_START_ADDRESS+i*2);
	}
}

void Store_Save(void)
{
	MyFlash_ErasePage(STORE_START_ADDRESS);
	for(i=0;i<STORE_COUNT;i++)
	{
		MyFlash_ProgramHalfWord(STORE_START_ADDRESS+i*2,Store_Data[i]);
	}
	
}


void Store_Clear(void)
{
	for(i=1;i<STORE_COUNT;i++)
	{
		Store_Data[i]=0x0000;
	}
	
	 Store_Save();
}

Store.h:

cpp 复制代码
#ifndef _STORE_H
#define _STORE_H

extern uint16_t Store_Data[];

void Store_Init(void);

void Store_Save(void);

void Store_Clear(void);

#endif

main.c:

cpp 复制代码
#include  "stm32f10x.h"                  // Device header
#include  "OLED.h"
#include  "delay.h"
#include  "Store.h"
#include  "MyFlash.h"


int main(void)
{
	
   OLED_Init();
	Store_Init();
	//擦除后数据位全都变为1
	//MyFlash_EraseAllPages();  
	OLED_ShowString(1,1,"Flag:");
	OLED_ShowString(2,1,"Data:");	
	
	while(1) 
	{
		  
	     OLED_ShowHexNum(1,6,Store_Data[0],4);
		  OLED_ShowHexNum(2,6,Store_Data[1],4);
	     OLED_ShowHexNum(3,6,Store_Data[2],4);
      
    	  Store_Data[1]++;
	     Store_Data[2]+=2;
	     Store_Save();
		  Delay_ms(1000);
	}
	
}

三、器件电子签名

1、简介

  • 电子签名存放在闪存存储器模块的系统存储区域,包含的芯片识别信息在出厂时编写,不可更改,使用指针读指定地址下的存储器可获取电子签名
  • 闪存容量寄存器:
    基地址:0x1FFF F7E0 大小:16位
  • 产品唯一身份标识寄存器:
    基地址:0x1FFF F7E8 大小:96位

2、编程实现

main.c:

cpp 复制代码
#include  "stm32f10x.h"                  // Device header
#include  "OLED.h"
#include  "delay.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,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) 
	{

	}
	
}
相关推荐
weixin_452600697 小时前
《青牛科技 GC6125:驱动芯片中的璀璨之星,点亮 IPcamera 和云台控制(替代 BU24025/ROHM)》
人工智能·科技·单片机·嵌入式硬件·新能源充电桩·智能充电枪
weixin_452600699 小时前
【青牛科技】14W 高保真音频放大电路——D2030
科技·单片机·嵌入式硬件·音视频·电动工具·智能电表
小刘同学-很乖16 小时前
MQTT从入门到精通之MQTT Dashboard
spring boot·stm32·物联网·iot
YuCaiH16 小时前
【STM32】USART串口数据包
笔记·stm32·单片机·嵌入式硬件
Kasen's experience18 小时前
STM32 GPIO 配置
stm32·单片机·嵌入式硬件
知行电子-18 小时前
Proteus中数码管动态扫描显示不全(已解决)
单片机·proteus·嵌入式
学习路上_write19 小时前
FPGA/Verilog,Quartus环境下if-else语句和case语句RT视图对比/学习记录
单片机·嵌入式硬件·qt·学习·fpga开发·github·硬件工程
非概念19 小时前
stm32学习笔记----51单片机和stm32单片机的区别
笔记·stm32·单片机·学习·51单片机
jjjxxxhhh12321 小时前
FPGA,使用场景,相比于单片机的优势
单片机·嵌入式硬件·fpga开发