第66章 读写内部FLASH
第六十六章 读写内部FLASH
1. 硬件设计
本实验仅操作了STM32芯片内部的FLASH空间,无需额外的硬件。
2. 软件设计
2.1 编程大纲
-
对内部FLASH解锁
-
找出空闲页,擦除目标页
-
进行读写测试
2.2 代码分析
2.2.1 硬件定义
读写内部FLASH不需要用到任何外部硬件,不过在编写测试时我们要先确定内部FLASH的页大小以及要往哪些地址写入数据
/* STM32大容量产品每页大小2KByte,中、小容量产品每页大小1KByte */
#if defined (STM32F10X_HD) || defined (STM32F10X_HD_VL) || defined (STM32F10X_CL) || defined (STM32F10X_XL)
#define FLASH_PAGE_SIZE ((uint16_t)0x800) //2048
#else
#define FLASH_PAGE_SIZE ((uint16_t)0x400) //1024
#endif
// 写入的起始地址与结束地址
#define WRITE_START_ADDR ((uint32_t)0x08008000)
代码中首先根据芯片类型定义了宏FLASH_PAGE_SIZE,由于本工程使用的是STM32VET6芯片,在工程的C/C++选项中包含了STM32F10X_HD的定义, 所以FLASH_PAGE_SIZE被定义成0x800,即2048字节。
另外,WRITE_START_ADDR和WRITE_END_ADDR定义了后面本工程测试读写内部FLASH的起始地址与结束地址,这部分区域与map文件指示的程序本身占用的空间不重合, 所以在后面修改这些地址的内容时,它不会把自身的程序修改掉。
2.2.2 读写内部FLASH
一切准备就绪,可以开始对内部FLASH进行擦写,这个过程不需要初始化任何外设,只要按解锁、擦除及写入的流程走就可以了
// 对内部FLASH进行读写测试
int InternalFlash_Test(void)
{
uint32_t EraseCounter = 0x00; // 记录要擦除多少页
uint32_t Address = 0x00; // 记录写入的地址
uint32_t Data = 0x3210ABCD; // 记录写入的数据
uint32_t NbrOfPage = 0x00; // 记录写入多少页
FLASH_Status FLASHStatus = FLASH_COMPLETE; // 记录每次擦除的结果
TestStatus MemoryProgramStatus = PASSED; // 记录整个测试结果
FLASH_Unlock(); // 解锁FLASH
/* 计算要擦除多少页 */
NbrOfPage = (WRITE_END_ADDR - WRITE_START_ADDR) / FLASH_PAGE_SIZE;
/* 清空所有标志位 */
FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
/* 按页擦除*/
for(EraseCounter = 0; (EraseCounter < NbrOfPage) && (FLASHStatus == FLASH_COMPLETE); EraseCounter++)
{
FLASHStatus = FLASH_ErasePage(WRITE_START_ADDR + (FLASH_PAGE_SIZE * EraseCounter));
}
/* 向内部FLASH写入数据 */
Address = WRITE_START_ADDR;
while((Address < WRITE_END_ADDR) && (FLASHStatus == FLASH_COMPLETE))
{
FLASHStatus = FLASH_ProgramWord(Address, Data);
Address = Address + 4;
}
FLASH_Lock(); // 锁定FLASH
/* 检查写入的数据是否正确 */
Address = WRITE_START_ADDR;
while((Address < WRITE_END_ADDR) && (MemoryProgramStatus != FAILED))
{
if((*(__IO uint32_t*) Address) != Data)
{
MemoryProgramStatus = FAILED;
}
Address += 4;
}
return MemoryProgramStatus;
}
该函数的执行过程如下:
-
调用FLASH_Unlock解锁;
-
根据起始地址及结束地址计算要擦除多少页;
-
调用FLASH_ClearFlag清除各种标志位;
-
使用循环调用FLASH_ErasePage擦除页,每次擦除一页;
-
使用循环调用FLASH_ProgramWord函数向起始地址至结束地址的存储区域都写入变量 “Data” 存储的数值数值;
-
调用FLASH_Lock上锁;
-
使用指针读取写入的数据内容并校验。
2.2.3 主函数测试
int main(void)
{
USART_Config();
LED_Init();
LED_BLUE();
if(InternalFlash_Test()== PASSED)
{
LED_GREEN();
printf("读写内部FLASH测试成功\r\n");
}
else
{
printf("读写内部FLASH测试失败\r\n");
LED_RED();
}
while(1);
}
main函数中初始化了用于指示调试信息的LED及串口后,直接调用了InternalFlash_Test函数, 进行读写测试并根据测试结果输出调试信息。

浙公网安备 33010602011771号