STM32L系列单片机内部EEPROM的读写
STM32L系列单片机内部提供了EEPROM存储区域,但实质上,其FLASH也是EEPROM类型,只不过有一块区域被开放出来专门用作EEPROM操作而已。STM32L的EEPROM使用寿命设计为100000次擦写以上,容量为2K-4K,这对于一般设备的参数存储来说是非常理想的。但从EEPROM使用方式看,其不适用于被反复修改的数据存储使用,一般作为配置参数,其修改次数往往是比较少量的。
STM32L的EEPROM和FLASH是统一编址,操作共用同一个读写电路,所以在EEPROM读写的时候STM32L核对于FLASH的一切访问和操作都将暂停,只有当EEPROM的操作完成后,才继续执行后续代码,在这期间只有EEPROM的读写电路工作,CPU处于挂起状态。
读操作,和FLASH以及内存一样,EEPROM的数据读取直接用总线读周期读出即可,不需要进行额外操作和设置。
- #define EEPROM_BASE_ADDR 0x08080000
- #define EEPROM_BYTE_SIZE 0x0FFF
#define EEPROM_BASE_ADDR 0x08080000
#define EEPROM_BYTE_SIZE 0x0FFF
以上定义EEPROM区的起始位置和大小,给定偏移量之后,可以按字节/半字/字/双字方式读出,但要注意的是最好偏移地址都按四字节对齐,以免产生总线访问错误或是取不正确:
- /*------------------------------------------------------------
- Func: EEPROM数据按字节读出
- Note:
- -------------------------------------------------------------*/
- void EEPROM_ReadBytes(uint16 Addr,uint8 *Buffer,uint16 Length)
- {
- uint8 *wAddr;
- wAddr=(uint8 *)(EEPROM_BASE_ADDR+Addr);
- while(Length--){
- *Buffer++=*wAddr++;
- }
- }
/*------------------------------------------------------------
Func: EEPROM数据按字节读出
Note:
-------------------------------------------------------------*/
void EEPROM_ReadBytes(uint16 Addr,uint8 *Buffer,uint16 Length)
{
uint8 *wAddr;
wAddr=(uint8 *)(EEPROM_BASE_ADDR+Addr);
while(Length--){
*Buffer++=*wAddr++;
}
}
- /*------------------------------------------------------------
- Func: EEPROM数据读出
- Note:
- -------------------------------------------------------------*/
- void EEPROM_ReadWords(uint16 Addr,uint16 *Buffer,uint16 Length)
- {
- uint32 *wAddr;
- wAddr=(uint32 *)(EEPROM_BASE_ADDR+Addr);
- while(Length--){
- *Buffer++=*wAddr++;
- }
- }
/*------------------------------------------------------------
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进行加锁,以保护数据。
下是手册给出的解锁命令码:
- #define PEKEY1 0x89ABCDEF //FLASH_PEKEYR
- #define PEKEY2 0x02030405 //FLASH_PEKEYR
#define PEKEY1 0x89ABCDEF //FLASH_PEKEYR
#define PEKEY2 0x02030405 //FLASH_PEKEYR
以下分别实现按字节和字方式写入:
- /*------------------------------------------------------------
- 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
- }
/*------------------------------------------------------------
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
}
- /*------------------------------------------------------------
- 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
- }
/*------------------------------------------------------------
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环境中,两个可以这样定义:
- #define EN_INT __enable_irq(); //系统开全局中断
- #define DIS_INT __disable_irq(); //系统关全局中断
声明:本文是我转载别人的日志,http://blog.csdn.net/wangsanhuai2010/article/details/7932867原创作者
STM32L系列单片机内部EEPROM的读写的更多相关文章
- 单片机成长之路(51基础篇) - 021 STC89C51系列单片机 内部EEPROM 驱动
最近又看了一下关于stc单片机的知识,感觉在使用中EEPROM是个经常用到的东西,特地学习了一下,给大家分享一下心得,如有不足,多多包涵,废话不多说,一图解千言,先上图: /*------------ ...
- STC89C52单片机内部EEPROM驱动
STC89C52单片机自身带有4K的存储空间,分为8个扇区,每个扇区512字节,第一扇区起始地址为:0x2000, 结束地址为:21FF, 第八扇区起始地址为0x2E00,结束地址是2FFF #inc ...
- STC单片机 IAP(EEPROM)的使用
STC89C51.52内部都自带有2K字节的EEPROM,54.55和58都自带有16K字节的EEPROM,STC单片机是利用IAP技术实现的EEPROM,内部Flash擦写次数可达100,000 次 ...
- 调试单片机内部扩展RAM
51单片机内部只有128字节的RAM(8051),而8052有256字节的RAM,低128字节RAM直接或间接寻址都可以,高128字节RAM与SRF特殊功能寄存器共用地址,SFR只能直接寻址,高128 ...
- AT89C 系列单片机解密原理
单片机解密简单就是擦除单片机片内的加密锁定位.由于AT89C系列单片机擦除操作时序设计上的不合理.使在擦除片内程序之前首先擦除加密锁定位成为可能.AT89C系列单片机擦除操作的时序为:擦除开始---- ...
- 8、16、32-BIT系列单片机区别与特点
一.8位单片机 8031/8051/8751是Intel公司早期的产品 1.8031的特点 8031片内不带程序存储器ROM,使用时用户需外接程序存储器和一片逻辑电路373,外接的程序存储器多为EPR ...
- MSP430FR2系列单片机破解芯片解密多少钱?
MSP430FR2系列单片机破解芯片解密 MSP430FR2xx系列单片机芯片解密型号: MSP430FR2533.MSP430FR2110.MSP430FR2310.MSP430FR2311.MSP ...
- MCS-51系列和80C51系列单片机是否相同
MCS是Intel公司单片机的系列符号.Intel推出有MCS-48.MCS-51.MCS-96系列单片机. MCS-51系列单既包括三个基本型80C31.8051.8751,以及对应的低功耗型号80 ...
- MSP430系列单片机特性及应用领域
概述 MSP430系列单片机是德州仪器1996年开始推向市场的一种16位超低功耗的混合信号处理器,给人们留下的最大的亮点是低功耗而且速度快,汇编语言用起来很灵活,寻址方式很多,指令很少,容易上手.主要 ...
随机推荐
- 人人都是 DBA(X)资源信息收集脚本汇编
什么?有个 SQL 执行了 8 秒! 哪里出了问题?臣妾不知道啊,得找 DBA 啊. DBA 人呢?离职了!!擦!!! 程序员在无处寻求帮助时,就得想办法自救,努力让自己变成 "伪 DBA& ...
- 解决在onCreate()过程中获取View的width和Height为0的4种方法
很经常当我们动态创建某些View时,需要通过获取他们的width和height来确定别的view的布局,但是在onCreate()获取view的width和height会得到0.view.getWid ...
- 渣渣小本求职复习之路每天一博客系列——Unix&Linux入门(5)
前情回顾:昨天简单地介绍了一下如何使用vi编辑器,例如命令模式和插入模式的切换,以及一些简单命令的讲解. —————————————————————————直接就开始吧———————————————— ...
- 浅析SQL Server实现分布式事务的两阶段提交协议2PC
不久之前团队有个新人问我一个很重要的web服务接口如何保证事务的问题.因为涉及到跨库事务,当时我只是回答目前我们的SOA框架都不支持跨库事务.然后就问到了数据库跨库事务是如何实现的,我只能凭印象含糊回 ...
- Senparc.Weixin.MP SDK 微信公众平台开发教程(十六):AccessToken自动管理机制
在<Senparc.Weixin.MP SDK 微信公众平台开发教程(八):通用接口说明>中,我介绍了获取AccessToken(通用接口)的方法. 在实际的开发过程中,所有的高级接口都需 ...
- 消息队列-rabbitMQ
消息队列两个用处:服务间解耦,缓解压力(削峰平谷),以前用过ZMQ.狼厂内部的NMQ,现在接触了java开源的kafka和RabbitMQ.目前先不求甚解,有个大概的认识. RabbitMQ的安装和入 ...
- 每天一个linux命令(59):rcp命令
rcp代表“remote file copy”(远程文件拷贝).该命令用于在计算机之间拷贝文件.rcp命令有两种格式.第一种格式用于文件到文件的拷贝:第二种格式用于把文件或目录拷贝到另一个目录中. 1 ...
- DDD~DDD从零起步架构说明
回到目录 看了传说中的弦哥对园子里.Net项目分层与文件夹结构大全(最佳架子奖,吐槽奖,阴沟翻船奖揭晓),我也来说说我的DDD架构吧,主要是看了微软NlayerApp之后,自己写的一个,以后将会应用到 ...
- 用PHP访问数据库
<?php //1造链接.面向对象 .方式对象方式 //把对象定个名字$db //MySQLi:数据扩展类.在MySQLi里做对象() //host:代表服务器地址也叫做本机[本机服务器loca ...
- python学习 数据类型之序列
一.序列(本文使用python3.5)############################################################# 列表.元组 字符窜都是序列#特点:#1 ...