在有些场合掉电保存是很有用的,但一般都是用EEPROM,要新增硬件电路,比较麻烦。stm32有一个Flash控制器,用户可以在线读写Flash,这样一定情况下可以用读写Flash做掉电保存,挺方便的。擦写不多于10万次。
我用的是stm32F10x3ZET6的Flash(512K)结构如下:
存储区的地址:0x0800 0000--0x0807 FFFF
这一段存储区使用存储程序的,用户也可以读写这一块区域。当然你得保证你读写的区域不是你的程序存储的区域。为此你要对你的编程器进行设置,如何你是用的j-link,用keil直接下载的,你可以进行一下设置,进入 “魔术棒”---utilities--seting
程序编程区域设为0x0800 0000--0x0007 0000 。
这样这之后的区域就0x0007 0001--0x0807 FFFF你就可以任意读写了。
程序:
1、一定要开启HSI时钟。
2、先擦除后写入。擦除时只能按页擦除。
3、读写必须是半字(16 bit)。
下面为读写配置函数。
flash.c
#include "flash.h"
void Flash_Init(void)
{
RCC_HSICmd(ENABLE);//开启内部高速时钟
}
uint8_t Flash_Write(uint32_t STARTADDR, uint16_t data[], uint16_t len)//擦除一页从这一页的开始写一组数据,成功返回0,不成功返回1
{
FLASH_Status flashStatus = FLASH_COMPLETE;
uint16_t i=0;
FLASH_Unlock(); //解锁
FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR); //清除flag
flashStatus = FLASH_ErasePage(STARTADDR); //擦除以STARTADDR开始的那一页
if(flashStatus != FLASH_COMPLETE)//是否擦除成功,不成功返回1
return 1;
for(i=0; i<len; i++)
FLASH_ProgramHalfWord(STARTADDR+2*i, data[i]); //写入数组
FLASH_Lock();//锁定flash
return 0;
}
void Flash_Read(uint32_t startaddr, uint16_t data[], uint16_t len)
{
uint16_t i=0;
for(i=0; i<len; i++)
data[i] = *(vu16*)(startaddr+i*2);//为什么这个指针是指向flash,而不是内存呢?因为
//在arm中ram,sdram,flash都映射到同一套地址中,在startaddr所在的这一片地址就是对应着flash
}
测试程序,写进去再读出来,发到串口。
#include "stm32f10x.h"
#include "stm32f10x_it.h"
#include "led.h"
#include "usart.h"
#include "stdio.h"
#include "timer.h"
#include "dma.h"
#include "adc.h"
#include "flash.h"
void init()
{
Usart1_Init(115200);
Flash_Init();
}
#define STARTADDR 0x0807f800
int main()
{
uint8_t flag = 0;
uint8_t i=0;
uint16_t data[5]={1, 2, 3, 4, 5};
uint16_t num[5]={0};
init();
//printf("hello");
Flash_Write(STARTADDR, data, 5);
Flash_Read(STARTADDR, num, 5);
for(i=0; i<5; i++)
{
printf("%d", num[i]);
}
while(1);
}
认为重要的就这些了,其他的问题可以百度到。