当前位置:首页 > 单片机 > 单片机
[导读] STM32L系列单片机内部提供了EEPROM存储区域,但实质上,其FLASH也是EEPROM类型,只不过有一块区域被开放出来专门用作EEPROM操作而已。STM32L的EEPROM使用寿命设计为100000次擦写以上,容量为2K-4K,这对于一般设备

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

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

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

#defineEEPROM_BASE_ADDR0x08080000

#defineEEPROM_BYTE_SIZE0x0FFF

#defineEEPROM_BASE_ADDR0x08080000#defineEEPROM_BYTE_SIZE0x0FFF

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

/*------------------------------------------------------------

Func:EEPROM数据按字节读出

Note:

-------------------------------------------------------------*/

voidEEPROM_ReadBytes(uint16Addr,uint8*Buffer,uint16Length)

{

uint8*wAddr;

wAddr=(uint8*)(EEPROM_BASE_ADDR+Addr);

while(Length--){

*Buffer++=*wAddr++;

}

}

/*------------------------------------------------------------Func:EEPROM数据按字节读出Note:-------------------------------------------------------------*/voidEEPROM_ReadBytes(uint16Addr,uint8*Buffer,uint16Length){uint8*wAddr;wAddr=(uint8*)(EEPROM_BASE_ADDR+Addr);while(Length--){*Buffer++=*wAddr++;}}

/*------------------------------------------------------------

Func:EEPROM数据读出

Note:

-------------------------------------------------------------*/

voidEEPROM_ReadWords(uint16Addr,uint16*Buffer,uint16Length)

{

uint32*wAddr;

wAddr=(uint32*)(EEPROM_BASE_ADDR+Addr);

while(Length--){

*Buffer++=*wAddr++;

}

}

/*------------------------------------------------------------Func:EEPROM数据读出Note:-------------------------------------------------------------*/voidEEPROM_ReadWords(uint16Addr,uint16*Buffer,uint16Length){uint32*wAddr;wAddr=(uint32*)(EEPROM_BASE_ADDR+Addr);while(Length--){*Buffer++=*wAddr++;}}

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

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

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

#definePEKEY10x89ABCDEF//FLASH_PEKEYR

#definePEKEY20x02030405//FLASH_PEKEYR

#definePEKEY10x89ABCDEF//FLASH_PEKEYR#definePEKEY20x02030405//FLASH_PEKEYR

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

/*------------------------------------------------------------

Func:EEPROM数据按字节写入

Note:

-------------------------------------------------------------*/

voidEEPROM_WriteBytes(uint16Addr,uint8*Buffer,uint16Length)

{

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;//notfastwrite

while(Length--){

*wAddr++=*Buffer++;

while(FLASH->SR&FLASH_SR_BSY);

}

FLASH->PECR|=FLASH_PECR_PELOCK;

EN_INT

}

/*------------------------------------------------------------Func:EEPROM数据按字节写入Note:-------------------------------------------------------------*/voidEEPROM_WriteBytes(uint16Addr,uint8*Buffer,uint16Length){uint8*wAddr;wAddr=(uint8*)(EEPROM_BASE_ADDR+Addr);DIS_INTFLASH->PEKEYR=PEKEY1;//unlockFLASH->PEKEYR=PEKEY2;while(FLASH->PECR&FLASH_PECR_PELOCK);FLASH->PECR|=FLASH_PECR_FTDW;//notfastwritewhile(Length--){*wAddr++=*Buffer++;while(FLASH->SR&FLASH_SR_BSY);}FLASH->PECR|=FLASH_PECR_PELOCK;EN_INT}

/*------------------------------------------------------------

Func:EEPROM数据按字写入

Note:字当半字用

-------------------------------------------------------------*/

voidEEPROM_WriteWords(uint16Addr,uint16*Buffer,uint16Length)

{

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;//notfastwrite

while(Length--){

*wAddr++=*Buffer++;

while(FLASH->SR&FLASH_SR_BSY);

}

FLASH->PECR|=FLASH_PECR_PELOCK;

EN_INT

}

/*------------------------------------------------------------Func:EEPROM数据按字写入Note:字当半字用-------------------------------------------------------------*/voidEEPROM_WriteWords(uint16Addr,uint16*Buffer,uint16Length){uint32*wAddr;wAddr=(uint32*)(EEPROM_BASE_ADDR+Addr);DIS_INTFLASH->PEKEYR=PEKEY1;//unlockFLASH->PEKEYR=PEKEY2;while(FLASH->PECR&FLASH_PECR_PELOCK);FLASH->PECR|=FLASH_PECR_FTDW;//notfastwritewhile(Length--){*wAddr++=*Buffer++;while(FLASH->SR&FLASH_SR_BSY);}FLASH->PECR|=FLASH_PECR_PELOCK;EN_INT}

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

#defineEN_INT__enable_irq();//系统开全局中断

#define DIS_INT __disable_irq(); //系统关全局中断

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

8位单片机在嵌入式设计领域已经成为半个多世纪以来的主流选择。尽管嵌入式系统市场日益复杂,8位单片机依然不断发展,积极应对新的挑战和系统需求。如今,Microchip推出的8位PIC®和AVR®单片机系列,配备了先进的独立...

关键字: 单片机 嵌入式 CPU

在嵌入式系统开发中,程序烧录是连接软件设计与硬件实现的关键环节。当前主流的单片机烧录技术已形成ICP(在电路编程)、ISP(在系统编程)、IAP(在应用编程)三大技术体系,分别对应开发调试、量产烧录、远程升级等不同场景。...

关键字: 单片机 ISP ICP IAP 嵌入式系统开发

在嵌入式系统开发中,看门狗(Watchdog Timer, WDT)是保障系统可靠性的核心组件,其初始化时机的选择直接影响系统抗干扰能力和稳定性。本文从硬件架构、软件流程、安全规范三个维度,系统分析看门狗初始化的最佳实践...

关键字: 单片机 看门狗 嵌入式系统

本文中,小编将对单片机予以介绍,如果你想对它的详细情况有所认识,或者想要增进对它的了解程度,不妨请看以下内容哦。

关键字: 单片机 开发板 Keil

随着单片机系统越来越广泛地应用于消费类电子、医疗、工业自动化、智能化仪器仪表、航空航天等各领域,单片机系统面临着电磁干扰(EMI)日益严重的威胁。电磁兼容性(EMC)包含系统的发射和敏感度两方面的问题。

关键字: 单片机 电磁兼容

以下内容中,小编将对单片机的相关内容进行着重介绍和阐述,希望本文能帮您增进对单片机的了解,和小编一起来看看吧。

关键字: 单片机 复位电路

在这篇文章中,小编将为大家带来单片机的相关报道。如果你对本文即将要讲解的内容存在一定兴趣,不妨继续往下阅读哦。

关键字: 单片机 异常复位

今天,小编将在这篇文章中为大家带来单片机的有关报道,通过阅读这篇文章,大家可以对它具备清晰的认识,主要内容如下。

关键字: 单片机 仿真器

单片机将是下述内容的主要介绍对象,通过这篇文章,小编希望大家可以对它的相关情况以及信息有所认识和了解,详细内容如下。

关键字: 单片机 中断 boot

一直以来,单片机都是大家的关注焦点之一。因此针对大家的兴趣点所在,小编将为大家带来单片机的相关介绍,详细内容请看下文。

关键字: 单片机 数字信号 模拟信号
关闭