STM32单片机Flash模拟EEPROM

摘要

STM32单片机都带有ROM和RAM,其中STM32根据自身的ROM(Flash)可以分为小容量产品、中容量产品、大容量产品

根据FLASH容量可以分为:

  • 小容量:0-32K
  • 中容量:64-128K
  • 大容量:256K以上(包含256K)

按照不同容量,存储器组织成32个1K字节/页(小容量)、128个1K字节/页(中容量)、256个2K字 节/页(大容量)的主存储器块和一个信息块,各容量的页大小如下图所示
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在执行闪存写操作时,任何对闪存的读操作都会锁住总线,在写操作完成后读操作才能正确地
进行;既在进行写或擦除操作时,不能进行代码或数据的读取操作。
信息块分为两个部分:

  • 系统存储器是用于存放在系统存储器自举模式下的启动程序,这个区域只保留给ST使用,启动程序使用USART1串行接口实现对闪存存储器的编程;ST在生产线上对这个区域编程并锁定以防止用户擦写。关于使用这个启动程序的详细信息,请参阅AN2606。
  • 选择字节

对主存储器和信息块的写入由内嵌的闪存编程/擦除控制器(FPEC)管理;编程与擦除的高电压由内部产生。
闪存存储器有两种保护方式防止非法的访问(读、写、擦除):

  • 页写入保护
  • 读出保护

正文

说了这么多的官方语言,无非就是将STM32单片机是用不到的ROM部分当做存储盘来用而已,保存一些读写频率比较低的数据而已
说道保存数据,无非就是 读 写 擦除 保护等等

前言

现在 STM32 的 FLASH 寿命是 10000 次,如果不是频繁的擦除和写入,使用FLAHS模拟EEPROM是没有毛病的,但是要注意的是,存取数据的位置尽量靠后,要给代码留下足够的空间,不然就尴尬了
stm32是32bit处理器,所以它的字是32bit的(一次处理4字节长度的数据)。半字自然就是16bit(2字节);字节是8bit
FLASH的读写都是以半字为单位的

读的话就相对更简单了,有了对应的地址,直接去地址中的内容就可以了

  • 举例
    要读取 地址0x08030000出的内容*((vu16*)0x08030000); 就可以将该位置的内容读取出来了
    要想读取多个字节
void STMFLASH_Read(u32 ReadAddr,u16 *pBuffer,u16 NumToRead)   	
{
	u16 i;
	for(i=0;i<NumToRead;i++)
	{
		pBuffer[i]=*((u16*)(ReadAddr));//读取两个字节.
		ReadAddr+=2;//地址向后偏移2个字节.	
	}
}

对于大容量产品,从第0页至第61页,写保护是以每2页为单位实现的,剩下的存储器块(第62页至第255页)则是同时提供保护。对于小容量和中容量的产品,写保护是以每4页为单位实现的。
如果试图在一个受保护的页面进行编程或擦除操作,在闪存状态寄存器(FLASH_SR)中会返回一个保护错误标志。
在写入之前需要解除闪存锁

  • RDPRT键 = 0x000000A5
  • KEY1 = 0x45670123
  • KEY2 = 0xCDEF89AB
    复位后,FPEC模块是被保护的,不能写入FLASH_CR寄存器;通过写入特定的序列到FLASH_KEYR寄存器可以打开FPEC模块,这个特定的序列是在FLASH_KEYR写入两个键值(KEY1和KEY2,见2.3.1节);错误的操作序列都会在下次复位前锁死FPEC模块和FLASH_CR寄存器。
    写入错误的键序列还会产生总线错误;总线错误发生在第一次写入的不是KEY1,或第一次写入的是KEY1但第二次写入的不是KEY2时;FPEC模块和FLASH_CR寄存器可以由程序设置FLASH_CR寄存器中的LOCK位锁住,这时可以通过在FLASH_KEYR中写入正确的键值对FPEC解锁。
解锁
void FLASH_Unlock(void)
{
  /* Authorize the FPEC of Bank1 Access */
  FLASH->KEYR = FLASH_KEY1;
  FLASH->KEYR = FLASH_KEY2;
}

有解锁就有上锁

上锁
void FLASH_Lock(void)
{
  /* Set the Lock Bit to lock the FPEC and the CR of  Bank1 */
  FLASH->CR |= CR_LOCK_Set;//CR_LOCK_Set是((uint32_t)0x00000080)
}

为什么是CR_LOCK_Set是((uint32_t)0x00000080)
请看FLASH—CR寄存器的第七位
在这里插入图片描述

擦除

闪存可以按页擦除,也可以整片擦除。

页擦除

闪存的任何一页都可以通过FPEC的页擦除功能擦除;擦除一页应遵守下述过程:

  • 检查FLASH_SR寄存器的BSY位,以确认没有其他正在进行的闪存操作
  • 设置FLASH_CR寄存器的PER位为’1’
  • 用FLASH_AR寄存器选择要擦除的页
  • 设置FLASH_CR寄存器的STRT位为’1’
  • 等待BSY位变为’0’
  • 读出被擦除的页并做验证
FLASH_Status FLASH_ErasePage(uint32_t Page_Address)
{
  FLASH_Status status = FLASH_COMPLETE;
  /* Check the parameters */
  assert_param(IS_FLASH_ADDRESS(Page_Address));
  /* Wait for last operation to be completed */
  status = FLASH_WaitForLastOperation(EraseTimeout);
  
  if(status == FLASH_COMPLETE)
  { 
    /* if the previous operation is completed, proceed to erase the page */
    FLASH->CR|= CR_PER_Set;
    FLASH->AR = Page_Address; 
    FLASH->CR|= CR_STRT_Set;
    
    /* Wait for last operation to be completed */
    status = FLASH_WaitForLastOperation(EraseTimeout);
    
    /* Disable the PER Bit */
    FLASH->CR &= CR_PER_Reset;
  }
  /* Return the Erase Status */
  return status;
}
整片擦除

可以用整片擦除功能擦除所有用户区的闪存,信息块不受此操作影响。建议使用下述过程:

  • 检查FLASH_SR寄存器的BSY位,以确认没有其他正在进行的闪存操作
  • 设置FLASH_CR寄存器的MER位为’1’
  • 设置FLASH_CR寄存器的STRT位为’1’
  • 等待BSY位变为’0’
  • 读出所有页并做验证
FLASH_Status FLASH_EraseAllPages(void)
{
  FLASH_Status status = FLASH_COMPLETE;
  /* Wait for last operation to be completed */
  status = FLASH_WaitForLastOperation(EraseTimeout);
  if(status == FLASH_COMPLETE)
  {
    /* if the previous operation is completed, proceed to erase all pages */
     FLASH->CR |= CR_MER_Set;
     FLASH->CR |= CR_STRT_Set;
    
    /* Wait for last operation to be completed */
    status = FLASH_WaitForLastOperation(EraseTimeout);

    /* Disable the MER Bit */
    FLASH->CR &= CR_MER_Reset;
  }
  /* Return the Erase Status */
  return status;
}
  • 1
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值