资料源码:https://gitee.com/yang456/OpenProgrammingModuleForMCU.git
说明1:知识从未如此性感。 烂程序员关心的是代码,好程序员关心的是数据结构和它们之间的关系!
说明2:学的是思想,而非程序!此代码思路适用于所有的单片机。
说明3:学会以后,下面的代码可能会跟你一辈子!
说明4:这一系列文章是为大幅度裁剪本人博客文章!使博客文章更有条理。便于推其它教程!
说明
因为用到了STM32F407系列的单片机的flash存储数据,所以写了这套程序.
目的是为了在便于存储.
关于407的Flash
1.F407xxx系列的flash都是这个样子
STM32F405xx/407xx and STM32F415xx/417xx 也是这样子
主存储区总共12个扇区,Sector0 - Sector11;
Sector0 - Sector3 每个扇区是16KB = 16*1024 = 16384字节; 总共4个扇区 = 16384*4=65536字节
Sector4 扇区是64KB = 64*1024 = 65536字节;
Sector5 - Sector11 每个扇区是128KB = 128*1024 = 131072字节; 总共7个扇区 = 131072*7=917504字节
这些扇区加起来总共是1M字节
2.关于flash的擦除
2.1
F407的flash擦除的时候要求每次只能擦除某个扇区;
擦除函数是: FLASH_EraseSector(uint32_t FLASH_Sector, uint8_t VoltageRange)
函数的第一个参数是扇区编号,第二个参数填写自己芯片的供电电压范围.一般都是填写 VoltageRange_3
2.2 关于怎么获取这个编号
所以擦除一般都写成: FLASH_EraseSector(/*获取地址对应的扇区编号*/STMFLASH_GetFlashSector(要擦除的地址), VoltageRange_3)
2.3 提供给用户的擦除函数
2.关于flash的写入
用户只需要记住,写入的时候写的地址必须是4的倍数,最少写入一个字(4字节)
提供给用户的写入函数:(一般的数据咱不直接使用这个函数存储数据,具体接着往下看)
3.关于flash的读取
关于本节封装的Flash写读函数思路
1.使用其中一个扇区存储数据,假设使用11扇区,准备一个固定大小(假设是512)的u32类型的数组用来存储数据
记住一句话:只要擦除过了的地方,不需要再次擦除就可以写入数据
在下载程序的时候.默认所有的flash都是已经擦除过的.
2.第一次存储
把整个数组全部写到扇区的最前面
3.第二次存储(不需要擦除,直接写入就可以,因为后面都已经擦除过了)
把整个数组紧接着写到后面
4.第三次存储(不需要擦除,直接写入就可以,因为后面都已经擦除过了)
把整个数组紧接着写到后面
5.假设写到最后了
我后面空了一点是因为定义的数组大小不一样,不一定正好占满.
6.接着再写
检测不够了以后,擦除下这个扇区,把数据从头开始存储.
源码使用
1.打开这节的程序
2.使用下面两个文件
3.提示:存储数据的时候是把数据放到这个数组里面,然后调用一下刷新函数.
4.存储数据
flash_helper_init(ADDR_FLASH_SECTOR_11); flash_helper_struct.FlashHelperData[0]=12345; flash_helper_struct.FlashHelperData[1]=6666; flash_helper_update();
5.读取存储的数据(直接从数组获取) 推荐
因为数组里面的值就是存储在flash里面的,所以直接从数组里面获取即可
flash_helper_struct.FlashHelperData[0] flash_helper_struct.FlashHelperData[1]
6.读取存储的数据(从flash里面获取),一般用于查看下存储的对不对
例如,获取数组的第一位存储在flash里面的值
u32 data; flash_helper_get(0,&data,1); printf("get0=%d\r\n",data);
例如,获取数组的第二位存储在flash里面的值
flash_helper_get(1,&data,1); printf("get1=%d\r\n",data);
例如,获取多个数据
u32 data_temp[200]; flash_helper_get(0,data_temp,200); for(i=0;i<200;i++){ printf("%d ",data_temp[i]); }
提示:前面两个是存储的正常的数据,后面全是0.因为数组除了最后一位是0x55555555,其它位置默认是0
7.单片机一上电,获取先前存储的数据
flash_helper_init 函数会把以前的数据缓存到 flash_helper_struct.FlashHelperData 数组.
所以获取以前存储的数据只需要从数组里面获取即可.
推荐使用方式(新建一个falsh_data文件)
1.假设使用数组其中一个位置记录数据
2.再来一个这种的
3.假设使用数组的其中一个位置记录四个单字节数据
数组是4字节的,如果当做一个使用就有点浪费了.
为了4字节和单字节快速分离出来,我直接使用了共用体
如果不使用共用体,就要写什么右移24位,16位,8位啥的转换为单字节.太麻烦.
关于转换的详细使用看下面链接文章
单片机模块化程序: IEEE754规约,浮点数和16进制之间的转换
用数组的其中一位记录水位,湿度,XXX,XXXX
4.假设需要记录最大1000个字节的数据
我加大了些缓存,2000个字节
移植使用
把下面文件放到自己的工程里面,按照上面的说明使用即可.