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. SWT: 发起事件 post event

    有很多学习SWT的同志遇到过一类需求,为某些控件添加了诸如MouseListener.KeyListener之类的监听,然后呢,希望使用代码模拟鼠标.键盘来执行点击.按键等操作. 首先说明一点,这是可 ...

  2. 【腾讯Bugly干货分享】React移动web极致优化

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/579083d1c9da73584b02587d 最近一个季度,我们都在为手Q家校 ...

  3. java 多线程(threadlocal)

    package com.example; import java.util.Random; public class App { public static class MyRunnable1 imp ...

  4. Java多线程10:ThreadLocal的作用及使用

    ThreadLocal的作用 从上一篇对于ThreadLocal的分析来看,可以得出结论:ThreadLocal不是用来解决共享对象的多线程访问问题的,通过ThreadLocal的set()方法设置到 ...

  5. 设计模式之美:Null Object(空对象)

    索引 意图 结构 参与者 适用性 效果 相关模式 实现 实现方式(一):Null Object 的示例实现. 意图 通过对缺失对象的封装,以提供默认无任何行为的对象替代品. Encapsulate t ...

  6. Java Spring-Spring与Quartz整合

    关于spring mvc.mybatis.maven的整合,请看上一篇文章 Quartz是一个强大的可以在web端执行定时任务的jar包. 本篇文章分为两大不同配置,第一位xml配置,第二位注解配置 ...

  7. 将不确定变为确定~transactionscope何时提升为分布式事务?(sql2005数据库解决提升到MSDTC的办法)

    回到目录 对于transactionscope不了解的同学,可以看我的相关文章 第二十六回   将不确定变为确定~transactionscope何时提升为分布式事务? 第二十七回   将不确定变为确 ...

  8. atitit  opencv apiattilax总结 约500个函数 .xlsx

    atitit  opencv apiattilax总结 约500个函数 .xlsx 1.1. CxCore中文参考手册 1 1.2. 机器学习中文参考手册  knn  svm  1 1.3. CvAu ...

  9. Atitit  代理与分销系统(1)  子代理 充值总额功能设计概览 sum() groubpy subagt

    Atitit  代理与分销系统(1)  子代理 充值总额功能设计概览 sum() groubpy subagt Keyword 分组与聚合操作. 一个for做分组...里面的做聚合... 数据g操作查 ...

  10. Atitit截屏功能的设计解决方案

    Atitit截屏功能的设计解决方案 自己实现.... 使用快捷键.. 弹出自己的win,,背景是屏幕快照 点击鼠标光标变成十字状态 出现截屏窗口调整截屏窗口位置与大小 释放鼠标,三个btn,,  复制 ...