OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 10387|回复: 13

FLASH模拟EEPROM,设置参数保存,掉电后,读出的参数又为0了,请问怎么解决?

[复制链接]

6

主题

58

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
341
金钱
341
注册时间
2013-11-10
在线时间
91 小时
发表于 2014-9-11 15:47:18 | 显示全部楼层 |阅读模式
5金钱
我修改了原子哥的例程,256K Flash。FLASH模拟EEPROM,设置参数保存,掉电后,读出的参数又为0了,请问怎么解决?
源码如下:
以下为main文件:   开机读取参数
ReadFlashData(); //读取Flash参数

以下为stmflash.h文件
[mw_shl_code=c,true]#ifndef __STMFLASH_H__ #define __STMFLASH_H__ #include "sys.h" ////////////////////////////////////////////////////////////////////////////////// //本程序只供学习使用,未经作者许可,不得用于其它任何用途 //ALIENTEK战舰STM32开发板 //STM32 FLASH 驱动代码 //正点原子@ALIENTEK //技术论坛:www.openedv.com //修改日期:2012/9/13 //版本:V1.0 //版权所有,盗版必究。 //Copyright(C) 广州市星翼电子科技有限公司 2009-2019 //All rights reserved ////////////////////////////////////////////////////////////////////////////////// #define FlashSIZE 25 //参数保存区的大小 extern u16 RW_Buffer[FlashSIZE]; extern u16 RY_Buffer[FlashSIZE]; //用户根据自己的需要设置 #define STM32_FLASH_SIZE 256 //所选STM32的FLASH容量大小(单位为K) #define STM32_FLASH_WREN 1 //使能FLASH写入(0,不是能;1,使能) ////////////////////////////////////////////////////////////////////////////////////////////////////// //FLASH起始地址 #define STM32_FLASH_BASE 0x08000000 //STM32 FLASH的起始地址 #define FLASH_SAVE_ADDR 0X08030000 //设置FLASH 保存地址(必须为偶数) //FLASH解锁键值 u16 STMFLASH_ReadHalfWord(u32 faddr); //读出半字 void STMFLASH_WriteLenByte(u32 WriteAddr,u32 DataToWrite,u16 Len); //指定地址开始写入指定长度的数据 u32 STMFLASH_ReadLenByte(u32 ReadAddr,u16 Len); //指定地址开始读取指定长度数据 void STMFLASH_Write(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite); //从指定地址开始写入指定长度的数据 void STMFLASH_Read(u32 ReadAddr,u16 *pBuffer,u16 NumToRead); //从指定地址开始读出指定长度的数据 //测试写入 void Test_Write(u32 WriteAddr,u16 WriteData); void SaveFlashData(void); //保存Flash参数 void ReadFlashData(void); //读取Flash参数 void RecyFlashData(void); //恢复Flash参数 #endif [/mw_shl_code]

以下为stmflash.c文件
[mw_shl_code=c,true]#include "stmflash.h" #include "delay.h" #include "gui.h" //#include "usart.h" ////////////////////////////////////////////////////////////////////////////////// //本程序只供学习使用,未经作者许可,不得用于其它任何用途 //ALIENTEK战舰STM32开发板 //STM32 FLASH 驱动代码 //正点原子@ALIENTEK //技术论坛:www.openedv.com //修改日期:2012/9/13 //版本:V1.0 //版权所有,盗版必究。 //Copyright(C) 广州市星翼电子科技有限公司 2009-2019 //All rights reserved ////////////////////////////////////////////////////////////////////////////////// u16 RW_Buffer[FlashSIZE]; u16 RY_Buffer[FlashSIZE]; //保存Flash参数 void SaveFlashData(void) { RY_Buffer[0] = t_ylsw[0];//压力水位采集时间 RY_Buffer[1] = t_ylsw[1]; RY_Buffer[2] = t_ylsw[2]; RY_Buffer[3] = t_ylsw[3]; RY_Buffer[4] = t_ylsw[4]; RY_Buffer[5] = t_qpsw[0];//气泡水位采集时间 RY_Buffer[6] = t_qpsw[1]; RY_Buffer[7] = t_qpsw[2]; RY_Buffer[8] = t_qpsw[3]; RY_Buffer[9] = t_qpsw[4]; RY_Buffer[10] = t_scsj[0];//上传数据时间 RY_Buffer[11] = t_scsj[1]; RY_Buffer[12] = t_scsj[2]; RY_Buffer[13] = t_scsj[3]; RY_Buffer[14] = t_scsj[4]; RY_Buffer[15] = d_dizhi;//本站地址 RY_Buffer[16] = d_ylbhl;//压力变化量 RY_Buffer[17] = d_qpbhl;//气泡变化量 RY_Buffer[18] = d_llbhl;//流量变化量 RY_Buffer[19] = d_sqbhl;//墒情变化量 RY_Buffer[20] = d_cjjg; //采集间隔 RY_Buffer[21] = d_dsjg; //定时间隔 RY_Buffer[22] = d_yllc; //压力量程 RY_Buffer[23] = d_szmm; //设置密码 RY_Buffer[24] = d_cjmm; //超级密码 STMFLASH_Write(FLASH_SAVE_ADDR,(u16*)RW_Buffer,FlashSIZE); } //读取Flash参数 void ReadFlashData(void) { STMFLASH_Read(FLASH_SAVE_ADDR,(u16*)RW_Buffer,FlashSIZE); t_ylsw[0] = RY_Buffer[0]; //压力水位采集时间 t_ylsw[1] = RY_Buffer[1]; t_ylsw[2] = RY_Buffer[2]; t_ylsw[3] = RY_Buffer[3]; t_ylsw[4] = RY_Buffer[4]; t_qpsw[0] = RY_Buffer[5]; //气泡水位采集时间 t_qpsw[1] = RY_Buffer[6]; t_qpsw[2] = RY_Buffer[7]; t_qpsw[3] = RY_Buffer[8]; t_qpsw[4] = RY_Buffer[9]; t_scsj[0] = RY_Buffer[10];//上传数据时间 t_scsj[1] = RY_Buffer[11]; t_scsj[2] = RY_Buffer[12]; t_scsj[3] = RY_Buffer[13]; t_scsj[4] = RY_Buffer[14]; d_dizhi = RY_Buffer[15];//本站地址 d_ylbhl = RY_Buffer[16];//压力变化量 d_qpbhl = RY_Buffer[17];//气泡变化量 d_llbhl = RY_Buffer[18];//流量变化量 d_sqbhl = RY_Buffer[19];//墒情变化量 d_cjjg = RY_Buffer[20]; //采集间隔 d_dsjg = RY_Buffer[21];//定时间隔 d_yllc = RY_Buffer[22];//压力量程 d_szmm = RY_Buffer[23];//设置密码 d_cjmm = RY_Buffer[24];//超级密码 } //恢复Flash参数 void RecyFlashData(void) { RY_Buffer[0] = 14;//压力水位采集时间 RY_Buffer[1] = 1; RY_Buffer[2] = 1; RY_Buffer[3] = 0; RY_Buffer[4] = 0; RY_Buffer[5] = 14;//气泡水位采集时间 RY_Buffer[6] = 1; RY_Buffer[7] = 1; RY_Buffer[8] = 0; RY_Buffer[9] = 0; RY_Buffer[10] = 14;//上传数据时间 RY_Buffer[11] = 1; RY_Buffer[12] = 1; RY_Buffer[13] = 0; RY_Buffer[14] = 0; RY_Buffer[15] = 1;//本站地址 RY_Buffer[16] = 10;//压力变化量 RY_Buffer[17] = 10;//气泡变化量 RY_Buffer[18] = 10;//流量变化量 RY_Buffer[19] = 10;//墒情变化量 RY_Buffer[20] = 5; //采集间隔 RY_Buffer[21] = 1; //定时间隔 RY_Buffer[22] = 10;//压力量程 RY_Buffer[23] = 1; //设置密码 RY_Buffer[24] = 9988; //超级密码 STMFLASH_Write(FLASH_SAVE_ADDR,(u16*)RY_Buffer,FlashSIZE); } //读取指定地址的半字(16位数据) //faddr:读地址(此地址必须为2的倍数!!) //返回值:对应数据. u16 STMFLASH_ReadHalfWord(u32 faddr) { return *(vu16*)faddr; } #if STM32_FLASH_WREN //如果使能了写 //不检查的写入 //WriteAddr:起始地址 //pBuffer:数据指针 //NumToWrite:半字(16位)数 void STMFLASH_Write_NoCheck(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite) { u16 i; for(i=0;i<NumToWrite;i++) { FLASH_ProgramHalfWord(WriteAddr,pBuffer); WriteAddr+=2;//地址增加2. } } //从指定地址开始写入指定长度的数据 //WriteAddr:起始地址(此地址必须为2的倍数!!) //pBuffer:数据指针 //NumToWrite:半字(16位)数(就是要写入的16位数据的个数.) #if STM32_FLASH_SIZE<256 #define STM_SECTOR_SIZE 1024 //字节 #else #define STM_SECTOR_SIZE 2048 #endif u16 STMFLASH_BUF[STM_SECTOR_SIZE/2];//最多是2K字节 void STMFLASH_Write(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite) { u32 secpos; //扇区地址 u16 secoff; //扇区内偏移地址(16位字计算) u16 secremain; //扇区内剩余地址(16位字计算) u16 i; u32 offaddr; //去掉0X08000000后的地址 if(WriteAddr<STM32_FLASH_BASE||(WriteAddr>=(STM32_FLASH_BASE+1024*STM32_FLASH_SIZE)))return;//非法地址 FLASH_Unlock(); //解锁 offaddr=WriteAddr-STM32_FLASH_BASE; //实际偏移地址. secpos=offaddr/STM_SECTOR_SIZE; //扇区地址 0~127 for STM32F103RBT6 secoff=(offaddr%STM_SECTOR_SIZE)/2; //在扇区内的偏移(2个字节为基本单位.) secremain=STM_SECTOR_SIZE/2-secoff; //扇区剩余空间大小 if(NumToWrite<=secremain)secremain=NumToWrite;//不大于该扇区范围 while(1) { STMFLASH_Read(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE,STMFLASH_BUF,STM_SECTOR_SIZE/2);//读出整个扇区的内容 for(i=0;i<secremain;i++)//校验数据 { if(STMFLASH_BUF[secoff+i]!=0XFFFF)break;//需要擦除 } if(i<secremain)//需要擦除 { FLASH_ErasePage(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE);//擦除这个扇区 for(i=0;i<secremain;i++)//复制 { STMFLASH_BUF[i+secoff]=pBuffer; } STMFLASH_Write_NoCheck(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE,STMFLASH_BUF,STM_SECTOR_SIZE/2);//写入整个扇区 }else STMFLASH_Write_NoCheck(WriteAddr,pBuffer,secremain);//写已经擦除了的,直接写入扇区剩余区间. if(NumToWrite==secremain)break;//写入结束了 else//写入未结束 { secpos++; //扇区地址增1 secoff=0; //偏移位置为0 pBuffer+=secremain; //指针偏移 WriteAddr+=secremain; //写地址偏移 NumToWrite-=secremain; //字节(16位)数递减 if(NumToWrite>(STM_SECTOR_SIZE/2))secremain=STM_SECTOR_SIZE/2;//下一个扇区还是写不完 else secremain=NumToWrite;//下一个扇区可以写完了 } }; FLASH_Lock();//上锁 } #endif //从指定地址开始读出指定长度的数据 //ReadAddr:起始地址 //pBuffer:数据指针 //NumToWrite:半字(16位)数 void STMFLASH_Read(u32 ReadAddr,u16 *pBuffer,u16 NumToRead) { u16 i; for(i=0;i<NumToRead;i++) { pBuffer=STMFLASH_ReadHalfWord(ReadAddr);//读取2个字节. ReadAddr+=2;//偏移2个字节. } } ////////////////////////////////////////////////////////////////////////////////////////////////////// //WriteAddr:起始地址 //WriteData:要写入的数据 void Test_Write(u32 WriteAddr,u16 WriteData) { STMFLASH_Write(WriteAddr,&WriteData,1);//写入一个字 } [/mw_shl_code]




最佳答案

查看完整内容[请看2#楼]

你先搞定1个字节的读写,不要一下就搞这么一堆。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165516
金钱
165516
注册时间
2010-12-1
在线时间
2116 小时
发表于 2014-9-11 15:47:19 | 显示全部楼层
你先搞定1个字节的读写,不要一下就搞这么一堆。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

6

主题

58

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
341
金钱
341
注册时间
2013-11-10
在线时间
91 小时
 楼主| 发表于 2014-9-11 15:47:19 | 显示全部楼层
你没发现RY_Buffer和RW_Buffer我弄错了吗
回复

使用道具 举报

120

主题

7878

帖子

13

精华

资深版主

Rank: 8Rank: 8

积分
12012
金钱
12012
注册时间
2013-9-10
在线时间
427 小时
发表于 2014-9-12 08:11:14 | 显示全部楼层
原子哥说的对,将一个搞定了再搞一堆的
现在,程序把烂铜烂铁变得智能化了,人呢,一旦离开了这烂铜烂铁就不知道干啥了
回复

使用道具 举报

0

主题

4

帖子

0

精华

新手入门

积分
24
金钱
24
注册时间
2014-9-8
在线时间
0 小时
发表于 2014-9-14 20:07:22 | 显示全部楼层
你的256KB是外置的FALSH吗?
回复

使用道具 举报

6

主题

58

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
341
金钱
341
注册时间
2013-11-10
在线时间
91 小时
 楼主| 发表于 2014-9-16 11:55:44 | 显示全部楼层
片上Flash,内置的。
回复

使用道具 举报

19

主题

122

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
218
金钱
218
注册时间
2014-8-20
在线时间
0 小时
发表于 2014-9-17 11:06:49 | 显示全部楼层
哥们,搞定了没?
我最近也在弄这个,弄明白了,指导一下哦。。。
回复

使用道具 举报

6

主题

58

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
341
金钱
341
注册时间
2013-11-10
在线时间
91 小时
 楼主| 发表于 2014-9-17 11:11:38 | 显示全部楼层
我搞定了,犯了个低级错误
回复

使用道具 举报

19

主题

122

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
218
金钱
218
注册时间
2014-8-20
在线时间
0 小时
发表于 2014-9-17 11:21:31 | 显示全部楼层
回复【7楼】lijunlinv:
---------------------------------
我看你的程序没什么问题。
回复

使用道具 举报

19

主题

122

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
218
金钱
218
注册时间
2014-8-20
在线时间
0 小时
发表于 2014-9-18 10:00:39 | 显示全部楼层
回复【9楼】lijunlinv:
---------------------------------
能不能传一下你的修改后可以用的程序?
回复

使用道具 举报

13

主题

276

帖子

0

精华

高级会员

Rank: 4

积分
697
金钱
697
注册时间
2014-6-20
在线时间
146 小时
发表于 2014-12-10 23:32:46 | 显示全部楼层
回复【9楼】lijunlinv:
---------------------------------
我正好也需要啊,正准备做一个,数据量相当小,20字节左右
回复

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
21
金钱
21
注册时间
2014-12-24
在线时间
0 小时
发表于 2014-12-24 11:41:09 | 显示全部楼层
朋友,谢谢把你源码给我看看。
回复

使用道具 举报

1

主题

3

帖子

0

精华

新手入门

积分
27
金钱
27
注册时间
2014-9-8
在线时间
0 小时
发表于 2015-3-5 20:56:15 | 显示全部楼层
void RecyFlashData(void)函数中STMFLASH_Write(FLASH_SAVE_ADD,(u16*)RY_Buffer,FlashSize);应该是写到(u16*)RW_Buffer。
回复

使用道具 举报

7

主题

51

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
232
金钱
232
注册时间
2016-5-9
在线时间
58 小时
发表于 2016-9-29 15:52:11 | 显示全部楼层
楼主能不能发一份源程序给我参考一下,我也在做这一块,新手好多不会,谢谢!!!!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-24 16:38

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表