历史上的今天
返回首页

历史上的今天

今天是:2024年12月17日(星期二)

正在发生

2018年12月17日 | 利用STM32的FLASH模拟 EEPROM(F103)系列

2018-12-17 来源:eefocus

       STM32的FLASH是用来存储主程序的,ST公司为了节约成本,没有加入 EEPROM,但是许多场合下我们需要用EEPROM;不过FLASH的容量还是可观的,我们可以利用FLASH模拟EEPROM。


       根据《STM32F10X闪存编程》中的介绍,FLASH除了保存用户代码的部分,其余部分我们是可以利用其作为数据存储使用的。stm32的FLASH分为主存储块和信息块。主存储块用于保存具体的程序代码和用户数据,信息块用于负责由stm32出厂是放置2KB的启动程序(Bootloader)并锁死,用户无法更改。选项字节存储芯片的配置信息及对主存储块的保护信息。STM32的FLASH主存储块按页组织,有的产品每页1KB,有的产品每页2KB。页面典型的用途就是用于按页擦除FLASH。从这点来看,页面有点像通用FLASH的扇区。


      通常情况下程序也不会把FLASH写满;在没满的时候我们可以把最后一或两页用来模拟EEPROM;这样我们就可以不用在外部另外来加EEPROM了。下面是STM32F103中文手册关于FLASH的截图;由于我用的是STM32C8T6做的实验;手册中没有给STM32C8T6的FLASH的地址信息,容量是64K,可以算出第63页地址是0X800FC00-0X800FFFF。


               



                          

                        


由于太晚了直接上代码:


头文件:


#ifndef  __ST_FLASH_H

#define  __ST_FLASH_H

/**@file StFlash.h

  *@brief stm32 flash的读写操作

  *    使用:

  *        * 此文件主要是针对STM32F103系列的芯片,注意不同容量大小的芯片的地址范围不一样

  *        * 使用Read和Write函数进行读写,具体参数和返回值见函数说明  

  *        * 可以利用flash模拟EEPROM使用

  * 

  *@author  DHS(746769845@qq.com)

  *

  */

 

 

#include "stm32f10x.h"

#include "stm32f10x_flash.h"

//////////////////////////////////////////////////////////////////////////////////////////////////////

//用户根据自己的需要设置

#define STM32_FLASH_SIZE  64 //所选STM32的FLASH容量大小(单位为K)

#define STM32_FLASH_WREN 1              //使能FLASH写入(0,不是能;1,使能)

//////////////////////////////////////////////////////////////////////////////////////////////////////

#if STM32_FLASH_SIZE<256

#define STM_SECTOR_SIZE 1024 //字节

#else 

#define STM_SECTOR_SIZE 2048

#endif  

//FLASH起始地址

#define STM32_FLASH_BASE 0x08000000 //STM32 FLASH的起始地址

//FLASH解锁键值

 

class STFLASH

{

private:

bool mUseHalfWord;//

uint32_t mStartAddress;//

public:

STFLASH(uint32_t startAddress=(0x08000000+1000),bool useHalfWord=true);

//读取指定地址的半字(16位数据)

//faddr:读地址(此地址必须为2的倍数!!)

//返回值:对应数据.

u16 ReadHalfWord(u32 faddr);

//WriteAddr:起始地址

//pBuffer:数据指针

//NumToWrite:半字(16位)数   

void Write_NoCheck(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite) ;

//从指定地址开始写入指定长度的数据

//WriteAddr:起始地址(此地址必须为2的倍数!!)

//pBuffer:数据指针

//NumToWrite:半字(16位)数(就是要写入的16位数据的个数.)

void Write(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite);

 

 

//从指定地址开始读出指定长度的数据

//ReadAddr:起始地址

//pBuffer:数据指针

//NumToWrite:半字(16位)数

void Read(u32 ReadAddr,u16 *pBuffer,u16 NumToRead) ;

 

 

};

 

 

#endif


程序文件:


#include "StFlash.h"

/**@file StFlash.h

  *@brief stm32 flash的读写操作

  *    使用:

  *        * 此文件主要是针对STM32F103系列的芯片,注意不同容量大小的芯片的地址范围不一样

  *        * 使用Read和Write函数进行读写,具体参数和返回值见函数说明  

  *        * 可以利用flash模拟EEPROM使用

  * 

  *@author  DHS(746769845@qq.com)

  *

  */

 

 

u16 STMFLASH_BUF[STM_SECTOR_SIZE/2];//最多是2K字节

STFLASH::STFLASH(uint32_t startAddress,bool useHalfWord)

{

if(startAddress%STM_SECTOR_SIZE!=0)//不是页的开始,将开始处设置为下一个页开始的地方

startAddress+=(STM_SECTOR_SIZE-(startAddress%STM_SECTOR_SIZE));

mStartAddress=startAddress;

mUseHalfWord=useHalfWord;

}

 

//读取指定地址的半字(16位数据)

//faddr:读地址(此地址必须为2的倍数!!)

//返回值:对应数据.

 

u16  STFLASH:: ReadHalfWord(u32 faddr)

{

return *(vu16*)faddr; 

}

//WriteAddr:起始地址

//pBuffer:数据指针

//NumToWrite:半字(16位)数   

void STFLASH::Write_NoCheck(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite)

{


u16 i;

for(i=0;i

{

FLASH_ProgramHalfWord(WriteAddr,pBuffer[i]);

    WriteAddr+=2;//地址增加2.

}  

}

//从指定地址开始写入指定长度的数据

//WriteAddr:起始地址(此地址必须为2的倍数!!)

//pBuffer:数据指针

//NumToWrite:半字(16位)数(就是要写入的16位数据的个数.)

void STFLASH::Write(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite)

{

u32 secpos;    //扇区地址

u16 secoff;    //扇区内偏移地址(16位字计算)

u16 secremain; //扇区内剩余地址(16位字计算)    

  u16 i;    

u32 offaddr;   //去掉0X08000000后的地址

if(WriteAddr

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) 

{

Read(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE,STMFLASH_BUF,STM_SECTOR_SIZE/2);//读出整个扇区的内容

for(i=0;i

{

if(STMFLASH_BUF[secoff+i]!=0XFFFF)break;//需要擦除    

}

if(i

{

FLASH_ErasePage(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE);//擦除这个扇区

for(i=0;i

{

STMFLASH_BUF[i+secoff]=pBuffer[i];   

}

Write_NoCheck(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE,STMFLASH_BUF,STM_SECTOR_SIZE/2);//写入整个扇区  

}else 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();//上锁

}

 

//从指定地址开始读出指定长度的数据

//ReadAddr:起始地址

//pBuffer:数据指针

//NumToWrite:半字(16位)数

void STFLASH::Read(u32 ReadAddr,u16 *pBuffer,u16 NumToRead) 

{

u16 i;

for(i=0;i

{

pBuffer[i]=ReadHalfWord(ReadAddr);//读取2个字节.

ReadAddr+=2;//偏移2个字节.

}

}

main文件:


#include "stm32f10x.h"

#include "StFlash.h"/要写入到STM32 FLASH的字符串数组

const u8 TEXT_Buffer[]={"Flash_test"};

#define SIZE sizeof(TEXT_Buffer) //数组长度

#define FLASH_SAVE_ADDR  0X0800FC00 //设置FLASH 保存地址(必须为偶数,且其值要大于本代码所占用FLASH的大小+0X08000000)

u8 datatemp[SIZE];

 

 

STFLASH flash1;//

int main()

{

SysTick_Config(72000);                                                    

flash1.Write(FLASH_SAVE_ADDR,(u16*)TEXT_Buffer,SIZE);//写数据,第一次下载程序到32,第二次注释掉此行,断电重新编译下载 //keil watch查看datatemp数组的数据正是之前写进去的数据

flash1.Read(FLASH_SAVE_ADDR,(u16*)datatemp,SIZE);//读数据


 while(1) {  

 

      }

}

推荐阅读

史海拾趣

ETL [E-Tech Electronics LTD]公司的发展小趣事

ETL始终将品质管理和客户服务放在首位。公司建立了完善的质量管理体系,从原材料采购到生产、检测、包装等各个环节都进行严格的质量控制。同时,ETL还注重提升客户服务水平,为客户提供全方位、个性化的服务。这些措施使得ETL的产品质量得到了客户的高度认可,也为公司赢得了良好的口碑。

BILIN公司的发展小趣事

E-Tech Electronics LTD(简称ETL)在创立之初就确立了其目标——为电子市场提供高质量、高性能的电子产品。公司凭借其创始人的远见卓识和团队的专业技术,成功开发了一系列电子产品,逐渐在市场上建立了良好的声誉。初期,ETL主要关注于特定领域的电子产品研发,通过不断优化产品设计,提升产品质量,逐渐赢得了客户的信任。

AZM [Arizona Microtek, Inc]公司的发展小趣事

随着电子行业的快速发展,AZM公司意识到只有不断创新才能在激烈的市场竞争中立于不败之地。因此,公司加大了对研发的投入,积极引进高端人才,建立了完善的研发体系。通过持续的技术创新,AZM公司成功推出了一系列具有领先水平的微电子产品,不仅提升了公司的市场竞争力,也为整个电子行业的发展做出了贡献。

Crowd Supply公司的发展小趣事

随着Crowd Supply在美国的成功运营,公司开始考虑全球扩张。他们首先在欧洲和亚洲设立了办事处和仓库,以便更好地服务这些地区的项目和支持者。同时,Crowd Supply也积极寻求与当地的合作伙伴建立关系,共同推广硬件创新。这些合作不仅为平台带来了更多的项目资源,也提升了其在全球范围内的影响力。

汇顶科技(GOODiX)公司的发展小趣事

随着Crowd Supply在美国的成功运营,公司开始考虑全球扩张。他们首先在欧洲和亚洲设立了办事处和仓库,以便更好地服务这些地区的项目和支持者。同时,Crowd Supply也积极寻求与当地的合作伙伴建立关系,共同推广硬件创新。这些合作不仅为平台带来了更多的项目资源,也提升了其在全球范围内的影响力。

AIC [Analog Intergrations Corporation]公司的发展小趣事

Crowd Supply的创立源于几位麻省理工大学的毕业生对于硬件创新的热情与追求。他们意识到,许多优秀的硬件项目因缺乏资金和市场渠道而无法实现商业化。于是,他们决定创建一个平台,专门服务于这些创新项目,帮助它们从原型设计走向市场。这就是Crowd Supply的初心,也是其使命所在——将原创、有用、受人尊敬的硬件带入生活。

问答坊 | AI 解惑

论坛资料重复太多了,有办法解决吗?

本人在论坛下载下来的时候发现,竟然有很多资料内容都是一样的,只改头换面而已,既浪费芯币又浪费时间,可怜我辛苦攒来的芯币呀!晕…希望管理员重视。…

查看全部问答>

源程序--我用逻辑分析仪测试时隙,调试出的18b20

我用逻辑分析仪测试出的1820时隙,源代码 …

查看全部问答>

WWDG进不了中断

我用一个灯监视WWG中断,正常的话每进20次中断改一次灯的状态,(主要是因为看门狗58.25MS喂一次狗,想让LED大约1S闪一次),但是不知哪里出现问题,灯从没闪烁过,说明WWDG中断没有进入,我将断点设在WWDG中断程序中,结果也没有跑到中断程序 ...…

查看全部问答>

请教大家下面IC的型号和厂商?

请各位大侠和兄弟姐妹帮忙,先在此谢过了。…

查看全部问答>

Stm32之寄存器汇总

很全的stm32寄存器表格,借以了解分析库函数。。。。。。 [ 本帖最后由 xinjitmzy 于 2012-4-17 21:26 编辑 ]…

查看全部问答>

低版本IAR简易开发LaunchPad的歪道

    (写得很认真,先留着,等板子来了就可以耍了!感谢作者)    故事的起因是这样滴。。。LaunchPad包装盒中并没有附带资料光盘(至少我收到的是这样的),只有一张纸的简单介绍,即TI网站上的文档MSP-EXP430G2 LaunchPa ...…

查看全部问答>

电源专用高压固态电容22UF/160V

6.8uf/160v 1、额定电压=160V; 2、浪涌电压=172.5V;3、容量=6.8UA;4、漏电流=217UA; 5、损耗=12%;6、ESR≤150毫欧 ;  7、纹波电流=420MA ;8、外形尺寸=¢8*12 12UF/160V      1、额定电压=160V; 2 ...…

查看全部问答>

为什么我的 INA CMRR 不随增益变化?

转自:deyisupport 前面有两篇关于仪表放大器 (INA) 电源及共模抑制比 (PSRR & CMRR) 的极好博客文章。(参见“处理抑制问题:仪表放大器 PSRR 与 CMRR”第 I 部分 和 第 II 部分)。 准确指出了大多数 INA 器件的 CMRR 与 PSRR 性能会随增益变化 ...…

查看全部问答>

如何设计基于DS18B20温度计

要求基于DS18B20的温度计,按键切换显示华氏和摄氏度。…

查看全部问答>

模数转换器中的混叠:并不是所有的信号都像其看上去那样

转自deyisupport 你看没看到过汽车向前行驶,而车的轮子实际上是向后转呢?如果不是在表演高难度特技的话,我打赌你一定在汽车广告中看到过。你想没想过这是为什么呢?真实的生活如流水般不可中断,而视频摄像头每秒钟只记录了有限数量的画面。每 ...…

查看全部问答>