MCU 内部flash的读写操作
在一些时候,需要存储一些数据,但是又不想接外部的flash,那我们可以知道,其实还有内部的flash可以使用, 需要注意的是内部flash,读写次数有限,所以需要控制擦写次数
1. 硬件连接
无
因为有flash大小的区分,所以需要注意设备进行页擦除的最大地址
C6T6 32k 最大地址 0x08007FF0
C8T6 64k 最大地址 0x0800FFE0
小容量产品:主存储块1-32KB, 每页1KB。系统存储器2KB
中容量产品:主存储块64-128KB, 每页1KB。系统存储器2KB
大容量产品:主存储块256KB以上, 每页2KB。系统存储器2KB
互联型产品:主存储块256KB以上, 每页2KB。系统存储器18KB
下图是 闪存模块的组织(中容量产品)
需要注意的是,前面一般都是放置代码的,所以擦写的时候尽量只擦写最后一个快的区域,防止误擦除。
2. CubeMX生成代码
可以看到,配置了3个部分
- 外部时钟
- SWD 接口
- 串口输出
- GPIO
3. 编写代码
重定向串口
C
/* USER CODE BEGIN PV */
#include "stdio.h"
int fputc(int ch,FILE *f)
{
HAL_UART_Transmit (&huart1 ,(uint8_t *)&ch,1,HAL_MAX_DELAY );
return ch;
}
/* USER CODE END PV */
申明一些变量
C
/* USER CODE BEGIN 0 */
//debug 查看对应地址,是否正确,如果显示的是问号,则无此位置
//C6T6 32k 最大地址 0x08007FF0
//C8T6 64k 最大地址 0x0800FFE0
#define FLASH_SAVE_ADDR 0x08007000
static FLASH_EraseInitTypeDef EraseInitStruct = {
.TypeErase = FLASH_TYPEERASE_PAGES, //页擦除
.PageAddress = FLASH_SAVE_ADDR, //擦除地址
.NbPages = 1 //擦除页数
};
/* USER CODE END 0 */
下面代码执行擦写的操作
C
while (1)
{
HAL_FLASH_Unlock();
uint32_t PageError = 0;
__disable_irq(); //擦除前关闭中断
if (HAL_FLASHEx_Erase(&EraseInitStruct,&PageError) == HAL_OK)
{
printf("擦除 成功\r\n");
}
__enable_irq(); //擦除后打开中断
uint32_t writeFlashData = 0x55555555; //待写入的值
uint32_t addr = FLASH_SAVE_ADDR; //写入的地址
HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,addr, writeFlashData);
printf("at address:0x%x, read value:0x%x\r\n", addr, *(__IO uint32_t*)addr);
HAL_FLASH_Lock();
while(1);//代码停住,限制擦写次数
}
4. 后记
内部的flash有擦写的次数限制,所以尽量只存储少量和擦写次数少的内容。
写的时候需要注意程序占用的空间,不要将程序误擦除。