1.掉电检测
CubeMX配置
只需使能PVD中断即可
但是使能了PVD中断后还需要自行配置一些PWR寄存器中的参数,我也通过HAL库进行编写
void PVD_config(void)
{
//配置PWR
PWR_PVDTypeDef sConfigPVD;
sConfigPVD.PVDLevel = PWR_PVDLEVEL_7; //低于2.9V触发掉电中断
sConfigPVD.Mode = PWR_PVD_MODE_IT_RISING; //掉电后PVDO会置一,因此选择上升沿触发
HAL_PWR_ConfigPVD(&sConfigPVD); //HAL库配置PVD函数
//使能PVD
HAL_PWR_EnablePVD(); //开启掉电中断
}
因为我们使用了CubeMX配置了中断优先级,因此此处不需要再次配置,
优先级在void HAL_MspInit(void)中配置
2.Flash的读写
我使用的是stm32f103c8t6 flash最大地址为 0x08010000
这里我把数据存放在0x0800C000
a).flash的擦除
在写之前需要擦除flash中的内容
flash擦除函数
HAL_StatusTypeDef HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef *pEraseInit,uint32_t *SectorError)
描述 : 擦除指定的Flash页
返回 : 状态 HAL_OK HAL_ERROR HAL_TIMEOUT
参数1 : 擦除flash时使用的结构体指针
参数2 : 错误信息
擦除flash时使用的结构体指针
typedef struct
{
uint32_t TypeErase; //擦除方式 : 批量擦除或页面擦除
uint32_t Banks; //
uint32_t PageAddress; //要擦除的首地址 (0x08000000 - FLASH_BANKx_END)
uint32_t NbPages; //待擦除的页面数 (1 - max number of pages - value of initial page)
} FLASH_EraseInitTypeDef;
擦除方式
#define FLASH_TYPEERASE_PAGES 0x00U /*!<Pages erase only*/
#define FLASH_TYPEERASE_MASSERASE 0x02U /*!<Flash mass erase activation*/
FLASH_BANKx_END stm32f103c8t6的最大地址是0x08010000(64kb)
b).flash的写入
flash写入函数
HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data)
描述 : 向flash中的一页写入数据
返回 : 状态 HAL_OK HAL_ERROR HAL_TIMEOUT
参数1 : 传输的数据类型
参数2 : 要写入的首地址
参数3 : 要写入的数据
传输的数据类型
#define FLASH_TYPEPROGRAM_HALFWORD 0x01U
#define FLASH_TYPEPROGRAM_WORD 0x02U
#define FLASH_TYPEPROGRAM_DOUBLEWORD 0x03U
c).flash的读取
*(__IO uint32_t *)Flash_Addr;
Flash_Addr : 要读取的首地址
在擦除和写入前都需要解锁flash结束后需要上锁
//解锁
HAL_FLASH_Unlock();
//上锁
HAL_FLASH_Lock();
实例代码
/******************************************************************************
function : void erase_flash(uint32_t addr)
describtion : 擦除flash的一个扇区
input : uint32_t addr //擦除的首地址
return : void
******************************************************************************/
void erase_flash(uint32_t addr)
{
uint32_t Errcode = 0;
//初始化擦除结构体
FLASH_EraseInitTypeDef Erase;
Erase.TypeErase = FLASH_TYPEERASE_PAGES;
Erase.PageAddress = FLASH3_ADDR;
Erase.NbPages = 1;
//解锁
HAL_FLASH_Unlock();
//擦除要写入的扇区
if(HAL_FLASHEx_Erase(&Erase,&Errcode) != HAL_OK)
{
return;
}
//上锁
HAL_FLASH_Lock();
}
/******************************************************************************
function : uint16_t read_flash(uint32_t addr)
describtion : 读flash中的一个16位数据
input : uint32_t addr //读取的首地址
return : uint16_t //读到的数据
******************************************************************************/
uint16_t read_flash(uint32_t addr)
{
return *((__IO uint32_t *)addr);
}
/******************************************************************************
function : void write_flash(uint32_t addr , uint16_t w_data)
describtion : 将一个十六位数据写入flash
input : void
return : void
******************************************************************************/
void write_flash(uint32_t addr , uint16_t w_data)
{
//解锁
HAL_FLASH_Unlock();
//写入数据
if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,addr,w_data) != HAL_OK)
{
return;
}
//上锁
HAL_FLASH_Lock();
}
如果要实现掉电写入数据,只需要在程序读完数据后擦除flash,然后在掉电中断的回调函数中写入flash即可
注:不可以在掉电回调函数中擦除,因为擦除比较费时,掉电的时间可能不够!
有哪里写的不好欢迎在评论区讨论!