STM32L系列单片机内部提供了EEPROM存储区域,但实质上,其FLASH也是EEPROM类型,只不过有一块区域被开放出来专门用作EEPROM操作而已。STM32L的EEPROM使用寿命设计为100000次擦写以上,容量为2K-4K,这对于一般设备的参数存储来说是非常理想的。但从EEPROM使用方式看,其不适用于被反复修改的数据存储使用,一般作为配置参数,其修改次数往往是比较少量的。

STM32L的EEPROM和FLASH是统一编址,操作共用同一个读写电路,所以在EEPROM读写的时候STM32L核对于FLASH的一切访问和操作都将暂停,只有当EEPROM的操作完成后,才继续执行后续代码,在这期间只有EEPROM的读写电路工作,CPU处于挂起状态。

读操作,和FLASH以及内存一样,EEPROM的数据读取直接用总线读周期读出即可,不需要进行额外操作和设置。

  1. #define EEPROM_BASE_ADDR    0x08080000
  2. #define EEPROM_BYTE_SIZE    0x0FFF
#define EEPROM_BASE_ADDR	0x08080000
#define EEPROM_BYTE_SIZE 0x0FFF

以上定义EEPROM区的起始位置和大小,给定偏移量之后,可以按字节/半字/字/双字方式读出,但要注意的是最好偏移地址都按四字节对齐,以免产生总线访问错误或是取不正确:

  1. /*------------------------------------------------------------
  2. Func: EEPROM数据按字节读出
  3. Note:
  4. -------------------------------------------------------------*/
  5. void EEPROM_ReadBytes(uint16 Addr,uint8 *Buffer,uint16 Length)
  6. {
  7. uint8 *wAddr;
  8. wAddr=(uint8 *)(EEPROM_BASE_ADDR+Addr);
  9. while(Length--){
  10. *Buffer++=*wAddr++;
  11. }
  12. }
/*------------------------------------------------------------
Func: EEPROM数据按字节读出
Note:
-------------------------------------------------------------*/
void EEPROM_ReadBytes(uint16 Addr,uint8 *Buffer,uint16 Length)
{
uint8 *wAddr;
wAddr=(uint8 *)(EEPROM_BASE_ADDR+Addr);
while(Length--){
*Buffer++=*wAddr++;
}
}
  1. /*------------------------------------------------------------
  2. Func: EEPROM数据读出
  3. Note:
  4. -------------------------------------------------------------*/
  5. void EEPROM_ReadWords(uint16 Addr,uint16 *Buffer,uint16 Length)
  6. {
  7. uint32 *wAddr;
  8. wAddr=(uint32 *)(EEPROM_BASE_ADDR+Addr);
  9. while(Length--){
  10. *Buffer++=*wAddr++;
  11. }
  12. }
/*------------------------------------------------------------
Func: EEPROM数据读出
Note:
-------------------------------------------------------------*/
void EEPROM_ReadWords(uint16 Addr,uint16 *Buffer,uint16 Length)
{
uint32 *wAddr;
wAddr=(uint32 *)(EEPROM_BASE_ADDR+Addr);
while(Length--){
*Buffer++=*wAddr++;
}
}

以上方法使用字节和字方式读出,在后面方法中,在一个字的存储空间内只使用了16个位,另16位不用,这样以避免产生对齐问题。

EEPROM的编程比读操作要复杂的多,本质上来说,擦除操作和写入操作是一样的,擦除只是在相应的地方写入0x00000000,但在STM32L的实现上,根据其手册说明貌似把这种擦除和写入区分开了,当写入0x00或0x0000或0x00000000时,自动执行一次擦除操作,在值为非0时,才执行一次所谓的写入操作。数据的写入过程先要对EEPROM进行解锁,这通过对特殊寄存器写入特殊序列实现,然后在写入之前进行擦除操作,其擦除是按字/ 双字/页进行的,推荐使用页擦除方式进行,先把参数读到内存,并修改,再进行页擦除,最后将参数写回,这种方式比较通用,否则很容易出现地址对齐或长度问题。在数据擦除完成之后,即可进行写入,每写一字节/半字/双字,都需要判断其是否写入完成,这和内部高压擦写电路有关,只有在上次操作完成之后再进行其它操作才有意义。最后,对EEPROM进行加锁,以保护数据。

下是手册给出的解锁命令码:

  1. #define PEKEY1  0x89ABCDEF      //FLASH_PEKEYR
  2. #define PEKEY2  0x02030405      //FLASH_PEKEYR
#define PEKEY1	0x89ABCDEF		//FLASH_PEKEYR
#define PEKEY2 0x02030405 //FLASH_PEKEYR

以下分别实现按字节和字方式写入:

  1. /*------------------------------------------------------------
  2. Func: EEPROM数据按字节写入
  3. Note:
  4. -------------------------------------------------------------*/
  5. void EEPROM_WriteBytes(uint16 Addr,uint8 *Buffer,uint16 Length)
  6. {
  7. uint8 *wAddr;
  8. wAddr=(uint8 *)(EEPROM_BASE_ADDR+Addr);
  9. DIS_INT
  10. FLASH->PEKEYR=PEKEY1;                //unlock
  11. FLASH->PEKEYR=PEKEY2;
  12. while(FLASH->PECR&FLASH_PECR_PELOCK);
  13. FLASH->PECR|=FLASH_PECR_FTDW;        //not fast write
  14. while(Length--){
  15. *wAddr++=*Buffer++;
  16. while(FLASH->SR&FLASH_SR_BSY);
  17. }
  18. FLASH->PECR|=FLASH_PECR_PELOCK;
  19. EN_INT
  20. }
/*------------------------------------------------------------
Func: EEPROM数据按字节写入
Note:
-------------------------------------------------------------*/
void EEPROM_WriteBytes(uint16 Addr,uint8 *Buffer,uint16 Length)
{
uint8 *wAddr;
wAddr=(uint8 *)(EEPROM_BASE_ADDR+Addr);
DIS_INT
FLASH->PEKEYR=PEKEY1; //unlock
FLASH->PEKEYR=PEKEY2;
while(FLASH->PECR&FLASH_PECR_PELOCK);
FLASH->PECR|=FLASH_PECR_FTDW; //not fast write
while(Length--){
*wAddr++=*Buffer++;
while(FLASH->SR&FLASH_SR_BSY);
}
FLASH->PECR|=FLASH_PECR_PELOCK;
EN_INT
}
  1. /*------------------------------------------------------------
  2. Func: EEPROM数据按字写入
  3. Note: 字当半字用
  4. -------------------------------------------------------------*/
  5. void EEPROM_WriteWords(uint16 Addr,uint16 *Buffer,uint16 Length)
  6. {
  7. uint32 *wAddr;
  8. wAddr=(uint32 *)(EEPROM_BASE_ADDR+Addr);
  9. DIS_INT
  10. FLASH->PEKEYR=PEKEY1;                //unlock
  11. FLASH->PEKEYR=PEKEY2;
  12. while(FLASH->PECR&FLASH_PECR_PELOCK);
  13. FLASH->PECR|=FLASH_PECR_FTDW;        //not fast write
  14. while(Length--){
  15. *wAddr++=*Buffer++;
  16. while(FLASH->SR&FLASH_SR_BSY);
  17. }
  18. FLASH->PECR|=FLASH_PECR_PELOCK;
  19. EN_INT
  20. }
/*------------------------------------------------------------
Func: EEPROM数据按字写入
Note: 字当半字用
-------------------------------------------------------------*/
void EEPROM_WriteWords(uint16 Addr,uint16 *Buffer,uint16 Length)
{
uint32 *wAddr;
wAddr=(uint32 *)(EEPROM_BASE_ADDR+Addr);
DIS_INT
FLASH->PEKEYR=PEKEY1; //unlock
FLASH->PEKEYR=PEKEY2;
while(FLASH->PECR&FLASH_PECR_PELOCK);
FLASH->PECR|=FLASH_PECR_FTDW; //not fast write
while(Length--){
*wAddr++=*Buffer++;
while(FLASH->SR&FLASH_SR_BSY);
}
FLASH->PECR|=FLASH_PECR_PELOCK;
EN_INT
}

以上代码中,在写入数据之前先关闭系统中断DIS_INT,写入完成之后打开系统中断EN_INT,这样避免在执行写操作的过程中被中断过程所打断,引起CPU异常或锁死,在在使用中一定要注意。在MDK环境中,两个可以这样定义:

  1. #define EN_INT          __enable_irq();     //系统开全局中断
  2. #define DIS_INT         __disable_irq();    //系统关全局中断

声明:本文是我转载别人的日志,http://blog.csdn.net/wangsanhuai2010/article/details/7932867原创作者

STM32L系列单片机内部EEPROM的读写的更多相关文章

  1. 单片机成长之路(51基础篇) - 021 STC89C51系列单片机 内部EEPROM 驱动

    最近又看了一下关于stc单片机的知识,感觉在使用中EEPROM是个经常用到的东西,特地学习了一下,给大家分享一下心得,如有不足,多多包涵,废话不多说,一图解千言,先上图: /*------------ ...

  2. STC89C52单片机内部EEPROM驱动

    STC89C52单片机自身带有4K的存储空间,分为8个扇区,每个扇区512字节,第一扇区起始地址为:0x2000, 结束地址为:21FF, 第八扇区起始地址为0x2E00,结束地址是2FFF #inc ...

  3. STC单片机 IAP(EEPROM)的使用

    STC89C51.52内部都自带有2K字节的EEPROM,54.55和58都自带有16K字节的EEPROM,STC单片机是利用IAP技术实现的EEPROM,内部Flash擦写次数可达100,000 次 ...

  4. 调试单片机内部扩展RAM

    51单片机内部只有128字节的RAM(8051),而8052有256字节的RAM,低128字节RAM直接或间接寻址都可以,高128字节RAM与SRF特殊功能寄存器共用地址,SFR只能直接寻址,高128 ...

  5. AT89C 系列单片机解密原理

    单片机解密简单就是擦除单片机片内的加密锁定位.由于AT89C系列单片机擦除操作时序设计上的不合理.使在擦除片内程序之前首先擦除加密锁定位成为可能.AT89C系列单片机擦除操作的时序为:擦除开始---- ...

  6. 8、16、32-BIT系列单片机区别与特点

    一.8位单片机 8031/8051/8751是Intel公司早期的产品 1.8031的特点 8031片内不带程序存储器ROM,使用时用户需外接程序存储器和一片逻辑电路373,外接的程序存储器多为EPR ...

  7. MSP430FR2系列单片机破解芯片解密多少钱?

    MSP430FR2系列单片机破解芯片解密 MSP430FR2xx系列单片机芯片解密型号: MSP430FR2533.MSP430FR2110.MSP430FR2310.MSP430FR2311.MSP ...

  8. MCS-51系列和80C51系列单片机是否相同

    MCS是Intel公司单片机的系列符号.Intel推出有MCS-48.MCS-51.MCS-96系列单片机. MCS-51系列单既包括三个基本型80C31.8051.8751,以及对应的低功耗型号80 ...

  9. MSP430系列单片机特性及应用领域

    概述 MSP430系列单片机是德州仪器1996年开始推向市场的一种16位超低功耗的混合信号处理器,给人们留下的最大的亮点是低功耗而且速度快,汇编语言用起来很灵活,寻址方式很多,指令很少,容易上手.主要 ...

随机推荐

  1. Linux Shell变量

    200 ? "200px" : this.width)!important;} --> 介绍 变量是shell脚本中必不可少的组成部分,在脚本中使用变量不需要提前声明.在ba ...

  2. 赴美工作常识(Part 3 - 英语)

    在<Part 2 - 申请>的评论中有人问英语要达到何种水平,以及如何提高.其实英语也不是我的强项,只是刚刚好做到能够沟通而已.由于我在知乎上回到过一个类似问题,我就基于那个答案简单说一下 ...

  3. UStore-添加自定义工作流(JDF)到产品

    这里使用的是8.2版本.所有的帮助文档可以在可以看到: http://www.xmpie.com/uStore%20Help/uStore_Help_Page.htm 1.登录 首先,登录到ustor ...

  4. underscore源码阅读记录

    这几天有大神推荐读underscore源码,趁着项目测试的空白时间,看了一下. 整个underscore包括了常用的工具函数,下面以1.3.3源码为例分析一下. _.size = function(o ...

  5. 知方可补不足~SQL2008中的发布与订阅模式~续

    回到目录 上一回介绍了如何在sql2008中建立一个数据库的发布者,今天来说一下如何建立一个订阅者,其实订阅者也是一个数据库,而这个数据库是和发布者的数据结构相同的库,它们之间通过SQL代理进行数据上 ...

  6. EF架构~为BulkInsert引入SET IDENTITY_INSERT ON功能

    回到目录 在设计表结构时,我们通常将不是很在乎表现的主键设计成自增长的,大数据量用bigint,一般地用int就可以了,int就是C#里的Int32,它最大可以存储到2147483647,21亿,基本 ...

  7. [Spring框架]Spring IOC的原理及详解。

    这里感谢 CSDN 的原博客:http://blog.csdn.net/m13666368773/article/details/7802126 看后  受益匪浅,这里再重温一遍Spring IOC ...

  8. 敏捷数据科学:用Hadoop创建数据分析应用

    敏捷数据科学:用Hadoop创建数据分析应用(数据分析最佳实践入门敏捷大数据首作分步骤|全流程演示思路.工具与方法) [美]Russell Jurney(拉塞尔·朱尔尼) 著   冯文中 朱洪波 译 ...

  9. iOS-------应用性能调优的25个建议和技巧

    性能对 iOS 应用的开发尤其重要,如果你的应用失去反应或者很慢,失望的用户会把他们的失望写满App Store的评论.然而由于iOS设备的限制,有时搞好性能是一件难事.开发过程中你会有很多需要注意的 ...

  10. jQuery 滚动条 滚动到底部(下拉到底部) 加载数据(触发事件、处理逻辑)、分页加载数据

    1.针对浏览器整个窗口滚动 主要代码: <script type="text/javascript"> ; function GetProductListPageFun ...