找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2822|回復(fù): 2
收起左側(cè)

STM32 FLASH 模擬EEPROM程序

[復(fù)制鏈接]
ID:389674 發(fā)表于 2020-2-21 09:53 | 顯示全部樓層 |閱讀模式
單片機(jī)源程序如下:
  1. #include "stmflash.h"
  2. #include "delay.h"




  3. //讀取指定地址的半字(16位數(shù)據(jù))
  4. //faddr:讀地址(此地址必須為2的倍數(shù)!!)
  5. //返回值:對應(yīng)數(shù)據(jù).
  6. u16 STMFLASH_ReadHalfWord(u32 faddr)
  7. {
  8.         return *(vu16*)faddr;
  9. }
  10. #if STM32_FLASH_WREN        //如果使能了寫   
  11. //不檢查的寫入
  12. //WriteAddr:起始地址
  13. //pBuffer:數(shù)據(jù)指針
  14. //NumToWrite:半字(16位)數(shù)   
  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. //從指定地址開始寫入指定長度的數(shù)據(jù)
  25. //WriteAddr:起始地址(此地址必須為2的倍數(shù)!!)
  26. //pBuffer:數(shù)據(jù)指針
  27. //NumToWrite:半字(16位)數(shù)(就是要寫入的16位數(shù)據(jù)的個數(shù).)
  28. #if STM32_FLASH_SIZE<256
  29. #define STM_SECTOR_SIZE 1024 //字節(jié)
  30. #else
  31. #define STM_SECTOR_SIZE        2048
  32. #endif                 
  33. u16 STMFLASH_BUF[STM_SECTOR_SIZE/2];//最多是2K字節(jié)
  34. void STMFLASH_Write(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite)       
  35. {
  36.         u32 secpos;           //扇區(qū)地址
  37.         u16 secoff;           //扇區(qū)內(nèi)偏移地址(16位字計算)
  38.         u16 secremain; //扇區(qū)內(nèi)剩余地址(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;                        //扇區(qū)地址  0~127 for STM32F103RBT6
  45.         secoff=(offaddr%STM_SECTOR_SIZE)/2;                //在扇區(qū)內(nèi)的偏移(2個字節(jié)為基本單位.)
  46.         secremain=STM_SECTOR_SIZE/2-secoff;                //扇區(qū)剩余空間大小   
  47.         if(NumToWrite<=secremain)secremain=NumToWrite;//不大于該扇區(qū)范圍
  48.         while(1)
  49.         {       
  50.                 STMFLASH_Read(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE,STMFLASH_BUF,STM_SECTOR_SIZE/2);//讀出整個扇區(qū)的內(nèi)容
  51.                 for(i=0;i<secremain;i++)//校驗數(shù)據(jù)
  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);//擦除這個扇區(qū)
  58.                         for(i=0;i<secremain;i++)//復(fù)制
  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);//寫入整個扇區(qū)  
  63.                 }else STMFLASH_Write_NoCheck(WriteAddr,pBuffer,secremain);//寫已經(jīng)擦除了的,直接寫入扇區(qū)剩余區(qū)間.                                   
  64.                 if(NumToWrite==secremain)break;//寫入結(jié)束了
  65.                 else//寫入未結(jié)束
  66.                 {
  67.                         secpos++;                                //扇區(qū)地址增1
  68.                         secoff=0;                                //偏移位置為0          
  69.                            pBuffer+=secremain;          //指針偏移
  70.                         WriteAddr+=secremain;        //寫地址偏移          
  71.                            NumToWrite-=secremain;        //字節(jié)(16位)數(shù)遞減
  72.                         if(NumToWrite>(STM_SECTOR_SIZE/2))secremain=STM_SECTOR_SIZE/2;//下一個扇區(qū)還是寫不完
  73.                         else secremain=NumToWrite;//下一個扇區(qū)可以寫完了
  74.                 }         
  75.         };       
  76.         FLASH_Lock();//上鎖
  77. }
  78. #endif

  79. //從指定地址開始讀出指定長度的數(shù)據(jù)
  80. //ReadAddr:起始地址
  81. //pBuffer:數(shù)據(jù)指針
  82. //NumToWrite:半字(16位)數(shù)
  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個字節(jié).
  89.                 ReadAddr+=2;//偏移2個字節(jié).       
  90.         }
  91. }

  92. //////////////////////////////////////////////////////////////////////////////////////////////////////
  93. //WriteAddr:起始地址
  94. //WriteData:要寫入的數(shù)據(jù)
  95. void Test_Write(u32 WriteAddr,u16 WriteData)          
  96. {
  97.         STMFLASH_Write(WriteAddr,&WriteData,1);//寫入一個字
  98. }
復(fù)制代碼

全部資料51hei下載地址:
FLASH模擬EEPROM實驗.7z (180.62 KB, 下載次數(shù): 61)

評分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

回復(fù)

使用道具 舉報

ID:108573 發(fā)表于 2020-2-22 09:43 | 顯示全部樓層
原理是先讀出來flash中的數(shù)據(jù),然后再擦除flash,然后再更改要寫入的數(shù)據(jù),最后再寫入
回復(fù)

使用道具 舉報

ID:670155 發(fā)表于 2021-1-5 16:50 | 顯示全部樓層
這是正點原子的例程吧
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表