今天学习到STM32F4系列的片内FLASH资源。它有1M字节的主存储器容量,在不影响代码存储的前提下,可保存部分数据。本实验用到的是STM32F429IGT6,它有1个BANK,分为12个扇区。具体可参考STM32F4xx中文参考手册。
对于片内FLASH,主要有擦除编写和读取操作。擦除一般以扇区为单位,在编写之前,将4k的扇区擦除。读取就是从某个地址addr,读取一个字,可用如下语句实现,data=*(vu32*)addr。
以上,大致回顾了片内FLASH 的两种操作。在代码里的具体表现为,erasesector(void)//擦除, program(u32 data)//编程,flashreadword(u32 faddr)//读取三个函数。
其中,擦除函数的代码如下,首先是固定的解锁和等待,通过GetSectorFromAddress()函数,获取扇区编号,在FLASH_Erase_Sector()函数里完成扇区擦除操作。最后,等待完成并上锁。
```c//扇区擦除
void erasesector(void)
{
HAL_FLASH_Unlock(); //解锁
FLASH_WaitForLastOperation(FLASH_WAITETIME); //等待上次操作完成
int sect;
sect = GetSectorFromAddress(0x08010000);
FLASH_Erase_Sector(sect,FLASH_VOLTAGE_RANGE_3);
FLASH_WaitForLastOperation(FLASH_WAITETIME); //等待上次操作完成
HAL_FLASH_Lock(); //上锁
}
然后是编程函数,代码如下,解锁,等待完成,for循环里,通过 HAL_FLASH_Program()函数,实现数据的写入。最后,还有等待完成和上锁。
//编程
void program(u32 data)
{
HAL_FLASH_Unlock(); //解锁
FLASH_WaitForLastOperation(FLASH_WAITETIME); //等待上次操作完成
u32 i;
for(i = startAddr; i < endAddr; i += 4)
{
HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, i, data++);
}
FLASH_WaitForLastOperation(FLASH_WAITETIME); //等待上次操作完成
HAL_FLASH_Lock(); //上锁
}
读取数据的函数如下,通过指针完成地址标识和数据转换。
```c//数据读取
u32 flashreadword(u32 faddr)
{
return *(vu32*)faddr;
}
另外,还有一个扇区获取函数,其对应的代码如下,通过判断扇区首末地址,来确定扇区编号。
#define startAddr 0x08010000
#define endAddr 0x08010020
uint32_t sectStartAddr[13]=
{
0x08000000,//0
0x08004000,//1
0x08008000,//2
0x0800c000,//3
0x08010000,//4
0x08020000,//5
0x08040000,//6
0x08060000,//7
0x08080000,//8
0x080a0000,//9
0x080c0000,//10
0x080e0000,//11
0x08100000
};
//获取Sector的编号
int GetSectorFromAddress(uint32_t address)
{
int sect;
if( address < 0x08000000 || address > 0x080FFFFF )
return -1;
for( int i=0; i<12; i++ )
{
if( address >= sectStartAddr[i] && address < sectStartAddr[i+1] )
{
sect = i;
break;
}
}
return sect;
}
``
而在main主函数里,即是调用这几个函数来实现,按键按下,分别控制写入和读取功能。while循环里的代码如下,KEY1按下,擦除并写入,KEY0按下,读取数据并显示。
while(1)
{
key=KEY_Scan(0);
if(key==KEY1_PRES) //KEY1按下,写入STM32 FLASH
{
erasesector();
program(i++);
LCD_ShowString(30,170,200,16,16,"finished:");
LCD_ShowxNum(130,170,i-1,8,16,0);
}
if(key==KEY0_PRES) //KEY0按下,读取字符串并显示
{
LCD_ShowString(30,200,200,16,16,"ReadData:");
LCD_ShowxNum(130,200,STMFLASH_ReadWord(0x08010000),8,16,0);
}
}
注:以上部分代码来自于正点原子官方和嵌入式技术开发公众号,我所做的大部分工作,主要是整合。感谢支持。