大家好,欢迎来到IT知识分享网。
概述:
通过地址的偏移,巧妙的避开Flash擦除长时间占用CPU的使用。
MCU-STM32H743,编译环境-Keil
说明:
基础知识可以看:Flash读写 其中包含了本代码涉及到的所有函数。
原理: 以空间换取时间。
正文:
首先要明白Flash擦除需要很长的时间,写用不了多少时间,所以我们可以在写之前执行擦除指令,使Flash在待写状态,这样再写的时候就不会占用大量的CPU时间。下图为H7写Flash时间和擦除Flash的时间,可以看出写都是us级的,而擦除则是s级的。
思路:
利用Flash的两个扇区进行擦写
//使用Flash的扇区1和扇区2
#define FLASH_SAVE_ADDR 0x08020000//扇区1
#define FLASH_USER_ADDR 0x08040000//扇区2
●FLASH_USER_ADDR 地址处的Flash在程序每次初始化的时候将内容擦除。
●FLASH_SAVE_ADDR 地址处保存FLASH_USER_ADDR 地址擦除前的内容。
我们每次可以在FLASH_SAVE_ADDR 地址提取数据,在FLASH_USER_ADDR 地址处写数据,这样擦除都在初始化的时候完成,这样写Flash就不会长时间占用CPU的正常运行。
★上电只能写一次Flash代码
uint32_t Flash_UserBuff[8]={
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000};
uint32_t Flash_SaveBuff[8]={
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000};//保存的数据
int main(void)
{
/*初始化*/
STMFLASH_Read(FLASH_USER_ADDR,(uint32_t*)Flash_UserBuff,8);//将FLASH_USER_ADDR地址中的数据读出至Flash_UserBuff[]数组中
if(Flash_UserBuff[0] != 0xFFFFFFFF)//判断该值是否全F,如果不等于全F,则该地址为上次写入的数据,将数据读出放入FLASH_SAVE_ADDR地址中,如果全F则已经被擦除过,不保存擦出过的数据
{
STMFLASH_Write(FLASH_SAVE_ADDR,(uint32_t*)Flash_UserBuff,8);//数据读出放入FLASH_SAVE_ADDR地址
}
STMFLASH_Read(FLASH_SAVE_ADDR,(uint32_t*)Flash_SaveBuff,8);//将上次保存的数据读出,用于这次程序的使用
STMFLASH_OnlyErase(FLASH_USER_ADDR,8);//擦除FLASH_USER_ADDR地址的内容,用于这次数据的存储。
/*主循环*/
while(1)
{
//用户任务,在任务中只能写入一次数据,因为初始化只擦了一次
}
★上电多次写Flash代码
因为Flash擦除是一整个扇区擦除,详情看上一个博客Flash读写。
●FLASH_USER_ADDR 地址处的Flash在程序每次初始化的时候将内容擦除。
●FLASH_SAVE_ADDR 地址处保存FLASH_USER_ADDR 地址擦除前的内容。
写 在FLASH_USER_ADDR中写入一次数据后我们地址偏移32字节作为下一次数据写入的首地址,因为STM32H7每次写入数据必须为8个字(32字节),因此我们存放的数据如下图所示,每次都占用Flash的32个字节。
读 在写的时候比如我们写了4次,则第四次尾地址后的数据全为FFFFFFFF,我们遍历FLASH_USER_ADDR 地址的数据,直到找到FFFFFFFF的数据,然后向前偏移32字节则为我们在扇区2 中上次写入数据的首地址(FLASH_USER_ADDR +偏移量),因此就找到了上次写入的数据,按下述代码思想就可提取数据。
我们每次可以在初始化时在上述找到的首地址(FLASH_USER_ADDR +偏移量) 中提取数据保存在FLASH_SAVE_ADDR地址中,然后擦除FLASH_USER_ADDR 地址处写数据,这样擦除在初始化的时候完成,这样写Flash就不会长时间占用CPU的正常运行。用数据是将数据从FLASH_SAVE_ADDR处读出即可。
代码如下:
uint32_t Flash_UserBuff[8]={
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000};
uint32_t Flash_SaveBuff[8]={
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000};//保存的数据
int main(void)
{
/*初始化*/
STMFLASH_Read(FLASH_USER_ADDR,(uint32_t*)Flash_UserBuff,8);//提前读一次
if(Flash_UserBuff[0] != 0xFFFFFFFF)//如果上次被写入
{
while(Flash_UserBuff[0] != 0xFFFFFFFF)//遍历找到没被写的区域,就找到上次写入的地址(循环退出的地址减32字节就是保存ID的地址)
{
STMFLASH_Read(FLASH_USER_ADDR+32*Flash_Cnt,(uint32_t*)Flash_UserBuff,8);//遍历找到没被写的区域后退出
Flash_Cnt++;
}
STMFLASH_Read(FLASH_USER_ADDR+32*(Flash_Cnt-2),(uint32_t*)Flash_UserBuff,8);//找到的没被写的区域往前偏移32字节,从该地址就可以读出上次写入的数据
STMFLASH_Write(FLASH_SAVE_ADDR,(uint32_t*)Flash_UserBuff,8);//写入读取的数据放置在0x08020060(扇区2)flash地址中(转存上一次写入的数据)
STMFLASH_OnlyErase(FLASH_USER_ADDR,8);//将FLASH_USER_ADDR位置的数据擦除,准备这次的数据写入
}
STMFLASH_Read(FLASH_SAVE_ADDR,(uint32_t*)Flash_SaveBuff,8);//在FLASH_SAVE_ADDR(扇区1)地址,读取一次数据放置内存中(这次程序使用)
/*主循环*/
while(1)
{
//用户任务,在任务中可多次写入,因为每次写入Flash会地址偏移
/*----多次写----*/
Write_FlashAddress = FLASH_USER_ADDR + Write_Cnt*32;//写一次地址偏移32Byte
Write_Cnt++;//写一次加一
STMFLASH_OnlyWrite(Write_FlashAddress,(uint32_t*)Flash_WData,8);//不擦除写
/*-------------*/
}
通过以上方法可以避免在程序运行中Flash擦除占用CPU的时间,因为擦除都是在初始化的时候完成的。
★★★如有错误欢迎指导!!!
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/26067.html