STM32F103标准库开发:内部Flash的读写

本文章技术信息均出自:STM32F103系列超详细参考手册-中文版
STM32F103标准库开发—目录


一、STM32存储器介绍

STM32存储器分为以下两种:

1. 随机存储器—RAM

  • RAM是与CPU直接交换数据的内部存储器,也叫主存(内存)。
  • 它可以随时读写,而且速度很快,通常作为操作系统或其他正在运行中的程序的临时数据存储媒介。
  • 当电源关闭时RAM不能保留数据(掉电数据消失哦)如果需要保存数据,就必须把它们写入一个长期的存储设备中(例如硬盘)。

2. 只读存储器—ROM

  • ROM所存数据,一般是装入整机前事先写好的,整机工作过程中只能读出,而不像随机存储器那样能快速地、方便地加以改写。
  • ROM所存数据稳定,断电后所存数据也不会改变。

二、STM32F103系列存储器介绍

1. STM32F103系列存储器分类

具体分类如下:

型号 ROM容量(字节) RAM容量(字节)
stm32f103x6(小容量) 32K 10K
stm32f103x8(中容量) 64K 20K
stm32f103xB(中容量) 128K 20K
stm32f103xC(大容量) 256K 48K
stm32f103xE(大容量) 512K 64K
stm32f103xG(大容量) 1024K 96K

本文使用是STM32F103C8T6芯片,keil5环境下默认的内存配置见下图:
STM32F103标准库开发:内部Flash的读写_第1张图片

  • ROM区域 是0x8000000开始,大小是64K字节(0x10000)。
  • RAM区域 是0x20000000开始,大小是20K字节(0x5000)。

2. 内部Flash基本知识

内部Flash就是STM32存储器的ROM区域,掉电数据不丢失,但是Flash在STM32中比较重要,程序也是保存在这个地方,所以轻易不让用户进行随意的读写,以避免不必要的问题。

按内部Flash的容量大小,分类如下:

型号 容量(字节) 页(字节) 启动程序 宏定义
stm32f103X6(小容量) 32K 1K startup_stm32f10x_ld.s STM32F10X_LD
stm32f103X8(中容量) 64K 1K startup_stm32f10x_md.s STM32F10X_MD
stm32f103XB(中容量) 128K 1K startup_stm32f10x_md.s STM32F10X_MD
stm32f103XC(大容量) 256K 2K startup_stm32f10x_hd.s STM32F10X_HD
stm32f103XE(大容量) 512K 2K startup_stm32f10x_hd.s STM32F10X_HD

三、内部Flash的读取

对于内部Flash的读取操作比较简单,可以直接指针寻址读取数据。
具体程序如下:

/**
 *@功能:从内部Flash读取num字节数据
 *@参数1:ReadAddress:数据起始地址
 *@参数2:*dest_Data: 读取到的数据缓存首地址
 *@参数3:num:        读取字节个数
 */
void ReadFlashData(uint32_t ReadAddress, uint8_t *dest_Data, uint32_t num)
{
	for(uint32_t i=0;i<num;i++)
	{
		dest_Data[i]=*(uint8_t*)(STARTADDR+ReadAddress+i);	//读取数据
	}
}

四、内部Flash的写入

内部Flash 写入数据之前需要擦除 以前的数据为0xFF,不然写入数据只会覆盖上一次写入的数据,会产生数据错误。
例如:
上一次存数据为0x52,下次直接存储数据0x01。
如果不擦除,就写入数据,结果读出来就是0x51。

由于擦除操作,最少是一页擦除。所以我们写入数据也要一整页的写入,不可以分多次对一页写入数据,因为下一次的擦除会把上一次的数据擦除。

1. 具体操作步骤

  1. 解锁Flash写保护。
  2. 清除Flash所有标志。
  3. 擦除Flash数据。
  4. 写入Flash数据。
  5. 重新锁定Flash写保护。

2. 标准库函数

(1) Flash解锁和锁定函数

void FLASH_Unlock(void);    //解锁函数:在对Flash操作之前必须解锁
void FLASH_Lock(void);      //锁定函数:同理,操作完Flash之后必须重新上锁

(2) Flash清除标志函数

void FLASH_ClearFlag(uint32_t FLASH_FLAG);

(3) Flash擦除函数

FLASH_Status FLASH_ErasePage(uint32_t Page_Address);	//擦除一页
FLASH_Status FLASH_EraseAllPages(void);					//擦除所有页

(4) 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 位基本上没啥区别。

(5) 获取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;

(6) Flash等待操作完成函数

FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout);

注:在执行闪存写操作时,任何对闪存的读操作都会锁住总线,在写操作完成后读操作才能正确地进行;既在进行写或擦除操作时,不能进行代码或数据的读取操作。所以在每次操作之前,我们都要等待上一次操作完成这次操作才能开始。

3. 具体程序

此次操作Flash使用的MCU是STM32F103C8T6,在数据手册中,可以看到STM32F103C8T6的flash起始地址是0x0800 0000,而STM32F103C8T6的Flash大小为64K,可以计算出STM32F103C8T6的Flash地址范围是:0x0800 0000——0x0800 FFFF。这里选取0x0800 F000作为读写操作的起始地址,对于C8T6这款MCU,操作这个起始地址应该算是很安全的范围了。

#define STARTADDR 0x0800F000 //STM32F103C8T6适用
/**
 *@功能:向内部Flash写入数据
 *@参数1:WriteAddress:	数据要写入的目标地址(偏移地址)
 *@参数2:	*data: 	写入的数据首地址
 *@参数3:	num:       写入数据的个数
 */
void WriteFlashData(uint32_t WriteAddress, uint16_t *data, uint32_t num)
{
	uint16_t sign =	0;	//标志位
	
	FLASH_Unlock();     //解锁Flash
	FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);  // 清除所有标志
	sign = FLASH_ErasePage(STARTADDR);	//擦除整页
	if(sign == FLASH_COMPLETE)	//Flash操作完成
	{
		for(uint32_t i=0;i<num;i++)
		{
			FLASH_ProgramHalfWord(STARTADDR+WriteAddress+i*2, data[i]);	//写入数据
		}
	}
	FLASH_Lock();	//重新锁定Flash
}

你可能感兴趣的:(#,STM32F103标准库开发,stm32,arm,Flash)