STM32内置FLASH闪存详解及代码实现
STM32内置FLASH闪存详解及代码实现
本文详细介绍了STM32内置FLASH闪存的各个方面,包括其组成部分、存储作用、地址分布以及如何通过操作接口寄存器进行读取、编程和擦除等基本操作。文章以STM32F103ZET6芯片为例,该芯片的闪存容量为64K。
一、FLASH闪存
(1)组成部分
FLASH包含程序存储器、系统存储器和选项字节三个部分。通过闪存存储器接口可以对程序存储器和选项字节进行擦除和编程。
(2)存储作用
- 程序存储器:用来存储编译后的程序代码
- 系统存储器:用来存储BootLoader,用于串口下载,不能对其进行修改
- 选项字节:存储一些独立于程序代码的配置参数
(3)闪存模块地址分布
STM32F103ZET6的闪存容量为64K,属于中容量产品,其内部地址分布如下图所示。
1.主存储器
也就是程序存储器,用来储存编译后的程序代码。如图所示,主存储器共有128页,每页1K字节,但本文使用的芯片只有64K,所以是64页。并且每页的起始地址都是以000、400、800、C00结尾的。
2.用户选择字节
也就是选项字节,其主要功能是配置主储存器的读写保护。
3.启动程序代码
这一部分是不能进行修改的,是厂商自带的下载程序代码
4.闪存存储器接口寄存器(FPEC)
这一部分寄存器是用来管理主存储器和用户选择字节的,可以对其进行擦除和编程。
二、操作接口寄存器
上文讲述了寄存器是用来对主存储器和用户选择字节进行擦除和编程的,那么具体是如何操作的呢?
(1)解锁FLASH
解锁FLASH的目的是防止误操作。在复位后,FLASH默认锁死,我们需要在键寄存器内先写入KEY1,再写入KEY2,才能解锁。错误的键值会使FPEC和FLASH锁死,除非再次进行复位。FPEC共有三个键值:
- RDPRT键 = 0x000000A5 (解除读保护)
- KEY1 = 0x45670123(锁1)
- KEY2 = 0xCDEF89AB(锁2)
(2)加锁FLASH
解锁之后我们要尽快再锁上,防止出现意外情况。在FLASH_CR中的LOCK位 置“1”,即可加锁成功。
三、读取FLASH
(1) 代码实现
以下代码为读取指定地址下的数据,分别为一个字、半个字、一个字节
/*
函数:读取FLASH内一个32位的字
参数:Address 要读取数据的字地址
返回值:指定地址下的字数据
说明:无
*/
uint32_t Flash_ReadWord(uint32_t Address)
{
return *((__IO uint32_t *)(Address));
}
/*
函数:读取FLASH内一个16位的半字
参数:Address 要读取数据的半字地址
返回值:指定地址下的半字数据
说明:无
*/
uint16_t Flash_ReadHalfWord(uint32_t Address)
{
return *((__IO uint16_t *)(Address));
}
/*
函数:读取FLASH内一个8位的字节
参数:Address 要读取数据的字节地址
返回值:指定地址下的字节数据
说明:无
*/
uint32_t Flash_ReadByte(uint32_t Address)
{
return *((__IO uint8_t *)(Address));
}
(2)测试代码
为测试代码是否正确,我们可以将其显示在OLED显示屏上观察现象。
int main(void)
{
OLED_Init();
OLED_ShowHexNum(0, 0, Flash_ReadWord(0x08000000), 8, OLED_8X16);
OLED_ShowHexNum(0, 16, Flash_ReadHalfWord(0x08000000), 4, OLED_8X16);
OLED_ShowHexNum(0, 32, Flash_ReadByte(0x08000000), 2, OLED_8X16);
OLED_Update();
while (1)
{
}
}
可以看到一个字的数据是八位,半字和字节分别取八位的低四位和低二位。
四、编程FLASH
以下代码为编程字和半字
/*
函数:页编程字
参数:1、写入地址
2、写入的数据
返回值:无
说明:无
*/
void MyFlash_PageProgram_Word(uint32_t Address, uint32_t Data)
{
FLASH_Unlock();
FLASH_ProgramWord(Address, Data);
FLASH_Lock();
}
/*
函数:页编程半字
参数:1、写入地址
2、写入的数据
返回值:无
说明:无
*/
void MyFlash_PageProgram_HalfWord(uint32_t Address, uint16_t Data)
{
FLASH_Unlock();
FLASH_ProgramHalfWord(Address, Data);
FLASH_Lock();
}
五、擦除代码
以下代码为页擦除和全部擦除
/*
函数:擦除FLASH全部内容
参数:无
返回值:无
说明:无
*/
void MyFlash_EraseAllPages(void)
{
FLASH_Unlock();
FLASH_EraseAllPages();
FLASH_Lock();
}
/*
函数:擦除FLASH指定页内容
参数:指定页地址
返回值:无
说明:无
*/
void Flash_ErasePages(uint32_t Page_Address)
{
FLASH_Unlock();
FLASH_ErasePage(Page_Address);
FLASH_Lock();
}
总结
本文介绍了FLASH的基础知识,以及基本操作的代码实现,希望本文对各位读者有所帮助。