前言
flash有擦写次数限制,一般为10万次。如果单一地址高频次重复擦写,会严重影响flash的使用寿命。如果一分钟存储一次,10万次也就能够使用不到两年的时间。所以推荐使用循环存储。
使用场景:需要长时间高频次存储的重要数据,flash空间有富余,用空间来换取时间。如:比较频繁刷新又每次都要保存的数据。
优点:代码量低,程序简单,易于理解。能够高频次存取数据,断电复位不丢失,不出错。
缺点:一个扇区存储单一数据;只利于使用最后一次数据,不利用历史数据分析。
变量定义
#define FLASH_START_ADDRESS 0x0803F800
#define FLASH_END_ADDRESS 0x0803FFFF
typedef struct
{
uint32_t start_address;
uint32_t end_address;
uint32_t puiAddress;
} FLASH_Manage_TypeDef;
FLASH_Manage_TypeDef address;
uint16_t test_count = 0;
初始化函数
void flash_init_data(FLASH_Manage_TypeDef *address)
{
address->start_address = FLASH_START_ADDRESS;
address->end_address = FLASH_END_ADDRESS;
}
页擦除
static void sFLASH_PageErase(void)
{
static FLASH_EraseInitTypeDef EraseInitStruct;
uint32_t SECTORError = 0;
/* 解锁 */
HAL_FLASH_Unlock();
/* 擦除 */
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
EraseInitStruct.NbPages = 1;
EraseInitStruct.PageAddress = address.start_address;
if (HAL_FLASHEx_Erase(&EraseInitStruct, &SECTORError) != HAL_OK)
{
}
}
写函数
void flash_write_data(FLASH_Manage_TypeDef *address, uint16_t *data)
{
address->puiAddress += 2U;
if (address->puiAddress >= address->end_address)
{
/* 读出,页擦除 */
//memcpy((uint8_t *)test_read_buf,(uint8_t *)address->start_address,address->end_address - address->start_address);
sFLASH_PageErase();
address->puiAddress = address->start_address;
}
HAL_FLASH_Unlock();
HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, address->puiAddress,
//*(test_point++));
*data);
HAL_FLASH_Lock();
}
读函数
void flash_read_data(FLASH_Manage_TypeDef *address, uint16_t *data)
{
uint16_t *addr = (void*)(address->end_address-1);
while(addr)
{
/* code */
if((uint32_t)addr < (uint32_t)address->start_address)
{
/* 没有历史数据 */
*data =0;
address->puiAddress = (uint32_t)addr;
break;
}
if ((*addr) != 0xffff)
{
/* 读到历史数据,记录数值和位置 */
*data = *addr;
address->puiAddress = (uint32_t)addr;
break;
}
addr--;
}
}
函数调用
//初始化
flash_init_data(&address);
//读取flash历史数据
flash_read_data(&address,&test_count);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
/*stm32f030cc单片机总计256Kbyte flash,每个page大小2Kbyte,所以总计128个page,
1Kwork(4Kbyte)为一个sector。
先使用127page,地址为0x0803 F800 - 0x0803 FFFF
*/
test_count ++;
flash_write_data( &address, &test_count);
HAL_Delay(1000);
}
结果
总结
不用担心10万次擦写上限了,如果有多个需要保存的数据,可以多开几个扇区。这种数据太多,也可以打包一个结构体。