完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
电子发烧友论坛|
|
|
相关推荐
1个回答
|
|
|
在我们应用开发时,经常会有一些程序运行参数需要保存,如一些修正系数。这些数据的特点是:数量少而且不需要经常修改,但又不能定义为常量,因为每台设备可能不一样而且在以后还有修改的可能。将这类数据存在指定的位置,需要修改时直接修改存储位置的数值,需要使用时则直接读取,会是一种方便的做法。考虑到这些数据量比较少,使用专门的存储单元既不经济,也没有必要,而STM32F4内部的Flash容量较大,而且ST的库函数中还提供了基本的Flash操作函数,实现起来也比较方便。
本代码用于上电时读取flash数据给滤波器权重参数(float型),再有其他信号时可以修改flash数据(未做)。 基本知识 STM32F40xx/41xx 的闪存模块组织如图 所示 主存储器,该部分用来存放代码和数据常数(如 const 类型的数据),主存储器的起始地址就是 0X08000000, B0、 B1 都接 GND 的时候,就是从 0X08000000 开始运行代码的。 代码块 ST的库函数包含了对flash的基本操作,为了使用方面,根据我们自己的需要对其进行再次封装。 对于读操作相对比较简单,内置闪存模块可以在通用地址空间直接寻址,就像读取变量一样。 对于写操作相对来说要复杂得多,写操作包括对用户数据的写入和擦除。为了防止误操作还有写保护锁。但这些基本的操作ST的库函数已经为我们写好了,我们只需要调用即可。 #define FLASH_SAVE_ADDR 0X08020000 //设置FLASH 保存地址(必须为偶数,且所在扇区,要大于本代码所占用到的扇区.//否则,写操作的时候,可能会导致擦除整个扇区,从而引起部分程序丢失.引起死机 #define FLASH_SAVE_ADDR 0X08020000 //设置FLASH 保存地址(必须为偶数,且所在扇区,要大于本代码所占用到的扇区. //否则,写操作的时候,可能会导致擦除整个扇区,从而引起部分程序丢失.引起死机. #define STM32_FLASH_BASE 0x08000000 //STM32 FLASH的起始地址 #define SIZE 4 float vel_filter_weight_read[SIZE] = {0.0}; float vel_filter_weight_write[SIZE] = {0.0}; float x_filter_0 = 0.0, x_filter_1 = 0.0; float yaw_filter_0 = 0.0, yaw_filter_1 = 0.0; //FLASH 扇区的起始地址 #define ADDR_FLASH_SECTOR_0 ((u32)0x08000000) //扇区0起始地址, 16 Kbytes #define ADDR_FLASH_SECTOR_1 ((u32)0x08004000) //扇区1起始地址, 16 Kbytes #define ADDR_FLASH_SECTOR_2 ((u32)0x08008000) //扇区2起始地址, 16 Kbytes #define ADDR_FLASH_SECTOR_3 ((u32)0x0800C000) //扇区3起始地址, 16 Kbytes #define ADDR_FLASH_SECTOR_4 ((u32)0x08010000) //扇区4起始地址, 64 Kbytes #define ADDR_FLASH_SECTOR_5 ((u32)0x08020000) //扇区5起始地址, 128 Kbytes #define ADDR_FLASH_SECTOR_6 ((u32)0x08040000) //扇区6起始地址, 128 Kbytes #define ADDR_FLASH_SECTOR_7 ((u32)0x08060000) //扇区7起始地址, 128 Kbytes #define ADDR_FLASH_SECTOR_8 ((u32)0x08080000) //扇区8起始地址, 128 Kbytes #define ADDR_FLASH_SECTOR_9 ((u32)0x080A0000) //扇区9起始地址, 128 Kbytes #define ADDR_FLASH_SECTOR_10 ((u32)0x080C0000) //扇区10起始地址,128 Kbytes #define ADDR_FLASH_SECTOR_11 ((u32)0x080E0000) //扇区11起始地址,128 Kbytes /**获取某个地址所在的flash扇区 *addr:flash地址 *返回值:0~11,即addr所在的扇区 */ uint16_t STMFLASH_GetFlashSector(u32 addr) { if(addr return FLASH_Sector_11; } /**读取指定地址的字(32位数据) *faddr:读地址 *返回值:对应数据 */ u32 STMFLASH_ReadWord(u32 faddr) { return *(vu32*)faddr; } /**从指定地址开始读出指定长度的数据 *ReadAddr:起始地址 *pBuffer:数据指针 *NumToRead:字(4位)数 */ void STMFLASH_Read(u32 ReadAddr,u32 *pBuffer,u32 NumToRead) { u32 i; for(i=0;i pBuffer=STMFLASH_ReadWord(ReadAddr);//读取4个字节. ReadAddr+=4;//偏移4个字节. } } /**WriteAddr:起始地址(此地址必须为4的倍数!!) *pBuffer:数据指针 *NumToWrite:字(32位)数(就是要写入的32位数据的个数.) */ void STMFLASH_Write(u32 WriteAddr,u32 *pBuffer,u32 NumToWrite) { FLASH_Status status = FLASH_COMPLETE; u32 addrx=0; u32 endaddr=0; if(WriteAddr FLASH_Unlock(); //解锁 FLASH_DataCacheCmd(DISABLE); //FLASH擦除期间,必须禁止数据缓存 addrx=WriteAddr; //写入的起始地址 endaddr=WriteAddr+NumToWrite*4; //写入的结束地址 if(addrx<0X1FFF0000) //只有主存储区,才需要执行擦除操作!! { while(addrx if(STMFLASH_ReadWord(addrx)!=0XFFFFFFFF) //有非0XFFFFFFFF的地方,要擦除这个扇区 { status=FLASH_EraseSector(STMFLASH_GetFlashSector(addrx),VoltageRange_3);//VCC=2.7~3.6V之间!! if(status!=FLASH_COMPLETE)break; //发生错误了 } else addrx+=4; } } if(status==FLASH_COMPLETE) { while(WriteAddr if(FLASH_ProgramWord(WriteAddr,*pBuffer)!=FLASH_COMPLETE)//写入数据 { break;//写入异常 } WriteAddr+=4; pBuffer++; } } FLASH_DataCacheCmd(ENABLE);//FLASH擦除结束,开启数据缓存 FLASH_Lock();//上锁 } void Flash_Read(void) { u32 *Ptr = (u32*)vel_filter_weight_read; u32 Read[4]; STMFLASH_Read(FLASH_SAVE_ADDR,(u32*)vel_filter_weight_read,SIZE); Read[0] = *Ptr; Read[1] = *(Ptr+1); Read[2] = *(Ptr+2); Read[3] = *(Ptr+3); if((Read[0] != 0xFFFFFFFF)&&(Read[0] != 0)&&(Read[1] != 0xFFFFFFFF)&&(Read[1] != 0)) //flash 中存入了正确数据则读取数据,否则使用默认数据 { x_filter_0 = vel_filter_weight_read[0]; x_filter_1 = vel_filter_weight_read[1]; }else { x_filter_0 = 0.99; x_filter_1 = 0.01; } if((Read[2] != 0xFFFFFFFF)&&(Read[2] != 0)&&(Read[3] != 0xFFFFFFFF)&&(Read[3] != 0)) { yaw_filter_0 = vel_filter_weight_read[2]; yaw_filter_1 = vel_filter_weight_read[3]; } else { yaw_filter_0 = 0.95; yaw_filter_1 = 0.05; } } int main(void) { System_Init();//其他初始化函数 Flash_Read(); while(1) { //if(Flag == 1) //STMFLASH_Write(FLASH_SAVE_ADDR,(u32*)vel_filter_weight_write,SIZE);//根据实际情况添加 } } |
|
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
4204 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
3263 浏览 1 评论
2795 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
2227 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
15146 浏览 2 评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
3168浏览 4评论
stm32f4下spi+dma读取数据不对是什么原因导致的?
1942浏览 3评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
2108浏览 3评论
2019浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
2216浏览 3评论
/9
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-12-13 15:41 , Processed in 1.327454 second(s), Total 72, Slave 55 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191

淘帖
3591