找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2803|回复: 2
收起左侧

STM32 FLASH 模拟EEPROM程序

[复制链接]
ID:389674 发表于 2020-2-21 09:53 | 显示全部楼层 |阅读模式
单片机源程序如下:
  1. #include "stmflash.h"
  2. #include "delay.h"




  3. //读取指定地址的半字(16位数据)
  4. //faddr:读地址(此地址必须为2的倍数!!)
  5. //返回值:对应数据.
  6. u16 STMFLASH_ReadHalfWord(u32 faddr)
  7. {
  8.         return *(vu16*)faddr;
  9. }
  10. #if STM32_FLASH_WREN        //如果使能了写   
  11. //不检查的写入
  12. //WriteAddr:起始地址
  13. //pBuffer:数据指针
  14. //NumToWrite:半字(16位)数   
  15. void STMFLASH_Write_NoCheck(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite)   
  16. {                                           
  17.         u16 i;
  18.         for(i=0;i<NumToWrite;i++)
  19.         {
  20.                 FLASH_ProgramHalfWord(WriteAddr,pBuffer[i]);
  21.             WriteAddr+=2;//地址增加2.
  22.         }  
  23. }
  24. //从指定地址开始写入指定长度的数据
  25. //WriteAddr:起始地址(此地址必须为2的倍数!!)
  26. //pBuffer:数据指针
  27. //NumToWrite:半字(16位)数(就是要写入的16位数据的个数.)
  28. #if STM32_FLASH_SIZE<256
  29. #define STM_SECTOR_SIZE 1024 //字节
  30. #else
  31. #define STM_SECTOR_SIZE        2048
  32. #endif                 
  33. u16 STMFLASH_BUF[STM_SECTOR_SIZE/2];//最多是2K字节
  34. void STMFLASH_Write(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite)       
  35. {
  36.         u32 secpos;           //扇区地址
  37.         u16 secoff;           //扇区内偏移地址(16位字计算)
  38.         u16 secremain; //扇区内剩余地址(16位字计算)          
  39.         u16 i;   
  40.         u32 offaddr;   //去掉0X08000000后的地址
  41.         if(WriteAddr<STM32_FLASH_BASE||(WriteAddr>=(STM32_FLASH_BASE+1024*STM32_FLASH_SIZE)))return;//非法地址
  42.         FLASH_Unlock();                                                //解锁
  43.         offaddr=WriteAddr-STM32_FLASH_BASE;                //实际偏移地址.
  44.         secpos=offaddr/STM_SECTOR_SIZE;                        //扇区地址  0~127 for STM32F103RBT6
  45.         secoff=(offaddr%STM_SECTOR_SIZE)/2;                //在扇区内的偏移(2个字节为基本单位.)
  46.         secremain=STM_SECTOR_SIZE/2-secoff;                //扇区剩余空间大小   
  47.         if(NumToWrite<=secremain)secremain=NumToWrite;//不大于该扇区范围
  48.         while(1)
  49.         {       
  50.                 STMFLASH_Read(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE,STMFLASH_BUF,STM_SECTOR_SIZE/2);//读出整个扇区的内容
  51.                 for(i=0;i<secremain;i++)//校验数据
  52.                 {
  53.                         if(STMFLASH_BUF[secoff+i]!=0XFFFF)break;//需要擦除            
  54.                 }
  55.                 if(i<secremain)//需要擦除
  56.                 {
  57.                         FLASH_ErasePage(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE);//擦除这个扇区
  58.                         for(i=0;i<secremain;i++)//复制
  59.                         {
  60.                                 STMFLASH_BUF[i+secoff]=pBuffer[i];          
  61.                         }
  62.                         STMFLASH_Write_NoCheck(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE,STMFLASH_BUF,STM_SECTOR_SIZE/2);//写入整个扇区  
  63.                 }else STMFLASH_Write_NoCheck(WriteAddr,pBuffer,secremain);//写已经擦除了的,直接写入扇区剩余区间.                                   
  64.                 if(NumToWrite==secremain)break;//写入结束了
  65.                 else//写入未结束
  66.                 {
  67.                         secpos++;                                //扇区地址增1
  68.                         secoff=0;                                //偏移位置为0          
  69.                            pBuffer+=secremain;          //指针偏移
  70.                         WriteAddr+=secremain;        //写地址偏移          
  71.                            NumToWrite-=secremain;        //字节(16位)数递减
  72.                         if(NumToWrite>(STM_SECTOR_SIZE/2))secremain=STM_SECTOR_SIZE/2;//下一个扇区还是写不完
  73.                         else secremain=NumToWrite;//下一个扇区可以写完了
  74.                 }         
  75.         };       
  76.         FLASH_Lock();//上锁
  77. }
  78. #endif

  79. //从指定地址开始读出指定长度的数据
  80. //ReadAddr:起始地址
  81. //pBuffer:数据指针
  82. //NumToWrite:半字(16位)数
  83. void STMFLASH_Read(u32 ReadAddr,u16 *pBuffer,u16 NumToRead)          
  84. {
  85.         u16 i;
  86.         for(i=0;i<NumToRead;i++)
  87.         {
  88.                 pBuffer[i]=STMFLASH_ReadHalfWord(ReadAddr);//读取2个字节.
  89.                 ReadAddr+=2;//偏移2个字节.       
  90.         }
  91. }

  92. //////////////////////////////////////////////////////////////////////////////////////////////////////
  93. //WriteAddr:起始地址
  94. //WriteData:要写入的数据
  95. void Test_Write(u32 WriteAddr,u16 WriteData)          
  96. {
  97.         STMFLASH_Write(WriteAddr,&WriteData,1);//写入一个字
  98. }
复制代码

全部资料51hei下载地址:
FLASH模拟EEPROM实验.7z (180.62 KB, 下载次数: 61)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:108573 发表于 2020-2-22 09:43 | 显示全部楼层
原理是先读出来flash中的数据,然后再擦除flash,然后再更改要写入的数据,最后再写入
回复

使用道具 举报

ID:670155 发表于 2021-1-5 16:50 | 显示全部楼层
这是正点原子的例程吧
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表