以下将为你详细介绍 STM32 的 Flash 操作相关知识,包含基本原理、操作步骤,并给出具体的代码示例。
STM32 的 Flash 存储器用于存储程序代码和一些需要掉电保存的数据。它通常被划分为多个扇区,每个扇区有固定的大小。不同系列的 STM32 芯片,其 Flash 扇区大小和数量可能不同。例如,STM32F103 系列的 Flash 扇区大小有 1KB、2KB、4KB、16KB、64KB 和 128KB 等。
在进行写或擦除操作之前,需要先解锁 Flash。因为 Flash 默认是处于锁定状态的,以防止误操作。
如果要写入新的数据,需要先擦除相应的扇区。可以选择擦除单个扇区或多个扇区。
在扇区擦除完成后,就可以向 Flash 中写入数据了。写入数据时需要注意数据的对齐方式,通常是以半字(16 位)或字(32 位)为单位进行写入。
在完成写或擦除操作后,需要锁定 Flash,以保护数据安全。
#include "stm32f10x.h"
// 解锁Flash
void FLASH_Unlock(void)
{
if ((FLASH->CR & FLASH_CR_LOCK) != 0)
{
FLASH->KEYR = FLASH_KEY1;
FLASH->KEYR = FLASH_KEY2;
}
}
// 锁定Flash
void FLASH_Lock(void)
{
FLASH->CR |= FLASH_CR_LOCK;
}
// 擦除指定扇区
uint8_t FLASH_EraseSector(uint32_t Sector)
{
uint32_t timeout = 0xFFFF;
FLASH_Unlock();
FLASH->CR |= FLASH_CR_PER;
FLASH->AR = Sector;
FLASH->CR |= FLASH_CR_STRT;
while ((FLASH->SR & FLASH_SR_BSY) != 0)
{
if (timeout-- == 0)
{
FLASH->CR &= ~FLASH_CR_PER;
FLASH_Lock();
return 1; // 擦除超时
}
}
if ((FLASH->SR & FLASH_SR_EOP) != 0)
{
FLASH->SR |= FLASH_SR_EOP;
}
FLASH->CR &= ~FLASH_CR_PER;
FLASH_Lock();
return 0; // 擦除成功
}
// 写入半字数据到指定地址
uint8_t FLASH_WriteHalfWord(uint32_t Address, uint16_t Data)
{
uint32_t timeout = 0xFFFF;
FLASH_Unlock();
FLASH->CR |= FLASH_CR_PG;
*(__IO uint16_t*)Address = Data;
while ((FLASH->SR & FLASH_SR_BSY) != 0)
{
if (timeout-- == 0)
{
FLASH->CR &= ~FLASH_CR_PG;
FLASH_Lock();
return 1; // 写入超时
}
}
if ((FLASH->SR & FLASH_SR_EOP) != 0)
{
FLASH->SR |= FLASH_SR_EOP;
}
FLASH->CR &= ~FLASH_CR_PG;
FLASH_Lock();
return 0; // 写入成功
}
// 从指定地址读取半字数据
uint16_t FLASH_ReadHalfWord(uint32_t Address)
{
return *(__IO uint16_t*)Address;
}
int main(void)
{
uint32_t SectorAddress = 0x08004000; // 假设要操作的扇区地址
uint16_t WriteData = 0x1234;
uint16_t ReadData;
// 擦除扇区
if (FLASH_EraseSector(SectorAddress) == 0)
{
// 写入数据
if (FLASH_WriteHalfWord(SectorAddress, WriteData) == 0)
{
// 读取数据
ReadData = FLASH_ReadHalfWord(SectorAddress);
// 这里可以根据读取的数据进行相应的处理
}
}
while (1)
{
// 主循环
}
}
FLASH->KEYR
寄存器写入特定的解锁密钥来实现。FLASH->CR
寄存器的LOCK
位置 1。当不使用寄存器直接操作时,我们可以利用 STM32 HAL 库来进行 Flash 操作。HAL(Hardware Abstraction Layer)库是 ST 公司提供的硬件抽象层,它对底层寄存器操作进行了封装,使得代码的编写更加简洁和易于理解。以下是一个使用 STM32 HAL 库进行 Flash 操作的示例,以 STM32F4 系列为例:
#include "stm32f4xx_hal.h"
// 定义要操作的扇区和地址
#define FLASH_USER_START_ADDR ADDR_FLASH_SECTOR_6 // 假设使用扇区6
#define FLASH_USER_END_ADDR ADDR_FLASH_SECTOR_7 - 1
// 解锁Flash
void Flash_Unlock(void) {
HAL_FLASH_Unlock();
}
// 锁定Flash
void Flash_Lock(void) {
HAL_FLASH_Lock();
}
// 擦除指定扇区
uint8_t Flash_EraseSector(uint32_t Sector) {
FLASH_EraseInitTypeDef EraseInitStruct;
uint32_t SectorError;
EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;
EraseInitStruct.Sector = Sector;
EraseInitStruct.NbSectors = 1;
if (HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK) {
return 1; // 擦除失败
}
return 0; // 擦除成功
}
// 写入32位数据到指定地址
uint8_t Flash_WriteWord(uint32_t Address, uint32_t Data) {
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, Address, Data) != HAL_OK) {
return 1; // 写入失败
}
return 0; // 写入成功
}
// 从指定地址读取32位数据
uint32_t Flash_ReadWord(uint32_t Address) {
return *(__IO uint32_t*)Address;
}
int main(void) {
HAL_Init();
uint32_t WriteData = 0xABCD1234;
uint32_t ReadData;
// 解锁Flash
Flash_Unlock();
// 擦除扇区
if (Flash_EraseSector(FLASH_SECTOR_6) == 0) {
// 写入数据
if (Flash_WriteWord(FLASH_USER_START_ADDR, WriteData) == 0) {
// 读取数据
ReadData = Flash_ReadWord(FLASH_USER_START_ADDR);
// 这里可以根据读取的数据进行相应的处理
}
}
// 锁定Flash
Flash_Lock();
while (1) {
// 主循环
}
}
#include "stm32f4xx_hal.h"
#define FLASH_USER_START_ADDR ADDR_FLASH_SECTOR_6
#define FLASH_USER_END_ADDR ADDR_FLASH_SECTOR_7 - 1
#include "stm32f4xx_hal.h"
:包含 STM32F4 系列的 HAL 库头文件。FLASH_USER_START_ADDR
和 FLASH_USER_END_ADDR
:定义了要操作的 Flash 扇区的起始和结束地址。void Flash_Unlock(void) {
HAL_FLASH_Unlock();
}
void Flash_Lock(void) {
HAL_FLASH_Lock();
}
HAL_FLASH_Unlock()
:调用 HAL 库函数解锁 Flash。HAL_FLASH_Lock()
:调用 HAL 库函数锁定 Flash。uint8_t Flash_EraseSector(uint32_t Sector) {
FLASH_EraseInitTypeDef EraseInitStruct;
uint32_t SectorError;
EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;
EraseInitStruct.Sector = Sector;
EraseInitStruct.NbSectors = 1;
if (HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK) {
return 1; // 擦除失败
}
return 0; // 擦除成功
}
FLASH_EraseInitTypeDef
:定义一个 Flash 擦除初始化结构体,用于配置擦除操作的参数。HAL_FLASHEx_Erase()
:调用 HAL 库函数进行扇区擦除操作。uint8_t Flash_WriteWord(uint32_t Address, uint32_t Data) {
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, Address, Data) != HAL_OK) {
return 1; // 写入失败
}
return 0; // 写入成功
}
HAL_FLASH_Program()
:调用 HAL 库函数向指定地址写入 32 位数据。uint32_t Flash_ReadWord(uint32_t Address) {
return *(__IO uint32_t*)Address;
}
HAL_Init()
函数进行初始化。