• stm32的flash地址起始于0x0800 0000,结束地址 是0x0800 0000加上芯片实际的flash大小,不同 的芯片flash大小不同。
• Flash中的内容一般用来存储代码和一些定义为 const的数据,断电不丢失。
• 内部Flash的构成:
• STM32 的内部 FLASH 包含主存储器、系统存储器、 OTP 区域以及选项字节区域。
• STM32 的内部 FLASH 包含主存储器、系统存储器、 OTP 区域以及选项字节区域。
• 主存储器:一般我们说 STM32 内部 FLASH 的时候,都是指这个主存储器区域它是 存储用户应用程序的空间,芯片型号说明中的 1M FLASH、 2M FLASH 都是指这个 区域的大小。与其它 FLASH 一样,在写入数据前,要先按扇区擦除。
• 系统存储区:系统存储区是用户不能访问的区域,它在芯片出厂时已经固化了启动 代码,它负责实现串口、 USB 以及 CAN 等 ISP 烧录功能。
• OTP 区域:OTP(One Time Program),指的是只能写入一次的存储区域,容量为 512 字节,写入后数据就无法再更改, OTP 常用于存储应用程序的加密密钥。
• 选项字节:选项字节用于配置 FLASH 的读写保护、电源管理中的 BOR 级别、软件 /硬件看门狗等功能,这部分共 32 字节。可以通过修改 FLASH 的选项控制寄存器 修改。
1、自定义工程名称。
2、选择英文路径,否则会丢 失启动文件而无法编译通过, 需要手动添加启动文件: startup_stm32l431xx.s
3、选择MDK-ARM V5开发软件, 即KEIL5软件
1、按键KEY1按下时,把数据写入MCU的flash
2、按键KEY2按下时,把写入MCU的flash数据并读取出来,打印数据。
调用函数:
1、HAL_FLASH_Unlock(void);//解锁
2、FLASH_EraseInitTypeDef FLASH_EraseInitSturcture;//配置需要擦除的参数
3、HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef pEraseInit, uint32_tPageError);//擦除
4、HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data);//写数据到flash
5、HAL_FLASH_Lock(void);//锁住
6、HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);//检测按键
7、void HAL_Delay(uint32_t Delay);//延时
8、HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);//点亮和熄灭LED
9、uint8_t OneWord=(__IO uint32_t)addr;//读取地址数据
10、printf();//打印数据到串口函数 需要重新定义函数fputc();才能正常使用printf();
int fputc(int ch,FILE*f)
{
uint8_t temp[1]={ch};
HAL_UART_Transmit(&huart1,temp,1,2);
return HAL_OK;
}
• FLASH读写流程:
1、对FLASH写入数据流程:
1)解锁FLASH:调用HAL_FLASH_Unlock(void);
2)擦除FLASH:调用HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef pEraseInit, uint32_t PageError);
3)写入数据到FLASH:调用HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data);
4)锁住FLASH:调用HAL_FLASH_Lock(void);
2、FLASH读取数据流程 直接读取相应的FLASH地址即可:通过(__IO uint32_t)ADDR读取该地址数据
#define strLen sizeof(strWriteToFlash1)/sizeof(uint8_t) //写入数据的长度
#define ADDR 0x0803f800 //写地址
写入FLASH数据:
void writeflash(int addr, uint32_t* writeFlashData)
{
uint32_t PageError = 0;
int i=0; HAL_FLASH_Unlock();
FLASH_EraseInitTypeDef f;
f.Banks=1;
f.NbPages=1;
f.Page=255;
f.TypeErase=0;
HAL_FLASHEx_Erase(&f,&PageError);
HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD,addr,writeFlashData[i]);
HAL_FLASH_Lock();
}
while(1)循环内程序:
if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin)==GPIO_PIN_RESET)
{
HAL_Delay(100);
if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin)==GPIO_PIN_RESET)
{
printf("KEY1 Press\r\n");
writeflash(ADDR,(uint32_t*)&writeFlashData);//擦除并写入数据 HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);//LED电平翻转
}
}
if(HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin)==GPIO_PIN_RESET)
{
HAL_Delay(100);
if(HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin)==GPIO_PIN_RESET)
{
printf("KEY2 Press\r\n"); ReadFlashData(ADDR,sizeof(writeFlashData),R_OldFlash);//读取写入的数据
HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin); //LED电平翻转 }}
```
**读取FLASH数据**:
`void ReadFlashData(int addr,uint32_t strSize,uint8_t* ReadData)
{
uint8_t OneWord; for(int i=0;i>%s<<,address:%x\r\n",ReadData,addr-strSize);// 显示该地址的数据
}`
**扩展实验**:将移植flash.c,该文件有实现写数 据到FLASH的多种方式,如写字符串数据到 FLASH等。