找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3110|回复: 4
收起左侧

STM32怎么用自身程序保存永久数据

[复制链接]
ID:703220 发表于 2020-11-19 11:39 | 显示全部楼层 |阅读模式


我现在是想做一个功能,这个程序在运行到某一位置后,会保存一个状态参数,但是我只会用变量实现,但是用变量实现会面临一个弊端,那就是如果系统断电,那么这个变量在重新上电后会重新初始化,也就是不再是断电前保存的状态参数了。   

我看网上说可以对STM32自己的flash写永久保存的数据,请问,具体怎么操作,求指点一下。



回复

使用道具 举报

ID:827243 发表于 2020-11-19 13:02 | 显示全部楼层
自用的,你试试。STM32Flash.h
  1. #ifndef __STM32FLASH_H__
  2. #define __STM32FLASH_H__

  3. #define FLASHSTART_ADDR         0x08000000                                //128K 最后一页 1KB每页 可存512个16位数  仅用于小于512K产品
  4. #define FLASH_BLOCK_USE                1                                                                        //使用倒数1个block
  5. #define STM32_FLASH_SIZE        128                                                                //128K Flash

  6. #if STM32_FLASH_SIZE<256
  7. #define STM_SECTOR_SIZE 1024
  8. #else
  9. #define STM_SECTOR_SIZE        2048
  10. #endif       

  11. #define USER_ADDR (FLASHSTART_ADDR+STM32_FLASH_SIZE*1024-FLASH_BLOCK_USE*STM_SECTOR_SIZE)

  12. #include "GloablVar.h"

  13. void STMFlash_Init(void);
  14. u8 STMFLASH_Write(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite);
  15. void STMFLASH_Read(u32 ReadAddr,u16 *pBuffer,u16 NumToRead);


  16. #endif        //for __STM32FLASH_H__
复制代码

STM32Flash.c
  1. #include "main.h"
  2. #include "STM32Flash.h"

  3. u8 FLASH_Unlock(void) {
  4.   if(READ_BIT(FLASH->CR, FLASH_CR_LOCK) != RESET)
  5.   {
  6.     /* Authorize the FLASH Registers access */
  7.     WRITE_REG(FLASH->KEYR, FLASH_KEY1);
  8.     WRITE_REG(FLASH->KEYR, FLASH_KEY2);

  9.     /* Verify Flash is unlocked */
  10.     if(READ_BIT(FLASH->CR, FLASH_CR_LOCK) != RESET)
  11.     {
  12.       return 1;
  13.     }
  14.   }
  15.        
  16.         return 0;
  17. }

  18. void FLASH_Lock(void) {
  19. SET_BIT(FLASH->CR, FLASH_CR_LOCK);
  20. }

  21. void FLASH_Program_HalfWord(uint32_t Address, uint16_t Data)
  22. {
  23.     /* Proceed to program the new data */
  24.     SET_BIT(FLASH->CR, FLASH_CR_PG);

  25.                 /* Write data in the address */
  26.                 *(__IO uint16_t*)Address = Data;
  27.        
  28.                 while (READ_BIT(FLASH->SR, FLASH_SR_BSY));
  29.                 CLEAR_BIT(FLASH->CR, FLASH_CR_PG);
  30.                 SET_BIT(FLASH->SR, FLASH_SR_EOP);
  31. }

  32. void STMFlash_Init(void) {
  33. //        FLASH->ACR=0;                                                        //CPU= 0M-24M
  34. //        FLASH->ACR=1;                                                        //CPU= 24M-48M
  35.         FLASH->ACR=2;                                                        //CPU= 48M-72M
  36. }

  37.        
  38. void STMFLASH_Write_NoCheck(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite)   
  39. {                                           
  40.         u16 i;
  41.         for(i=0;i<NumToWrite;i++)
  42.         {
  43.                 FLASH_Program_HalfWord(WriteAddr+i*2,pBuffer[i]);
  44.         }  
  45. }

  46. void STMFLASH_PageErase(uint32_t EraseAddress)
  47. {
  48.                 /* Proceed to erase the page */
  49.     SET_BIT(FLASH->SR, FLASH_SR_EOP);
  50.     SET_BIT(FLASH->CR, FLASH_CR_PER);
  51.     WRITE_REG(FLASH->AR, EraseAddress);
  52.     SET_BIT(FLASH->CR, FLASH_CR_STRT);
  53.                 while (READ_BIT(FLASH->SR, FLASH_SR_EOP)==0);
  54.                 SET_BIT(FLASH->SR, FLASH_SR_EOP);
  55.     CLEAR_BIT(FLASH->CR, FLASH_CR_PER);
  56. }

  57. u16 STMFLASH_ReadHalfWord(u32 faddr)
  58. {
  59.         return *(vu16*)faddr;
  60. }

  61. u16 STMFLASH_BUF[STM_SECTOR_SIZE/2];

  62. void STMFLASH_Read(u32 ReadAddr,u16 *pBuffer,u16 NumToRead)          
  63. {
  64.         u16 i;
  65.         for(i=0;i<NumToRead;i++)
  66.         {
  67.                 pBuffer[i]=STMFLASH_ReadHalfWord(USER_ADDR+ReadAddr+i*2);
  68.         }
  69.        
  70. }


  71. u8 STMFLASH_Write(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite)       
  72. {
  73.         u32 secpos;          
  74.         u16 secoff;
  75.         u16 rdLen;          
  76.         u16 i;
  77.         u16 wrEnd;
  78.        
  79.         if(WriteAddr+NumToWrite*2>FLASH_BLOCK_USE*STM_SECTOR_SIZE)         return 1;                                        //写入地址超限
  80.         FLASH_Unlock();
  81.         secpos = WriteAddr / STM_SECTOR_SIZE;
  82.         secoff = WriteAddr % STM_SECTOR_SIZE;
  83.   wrEnd=0;
  84.         while (wrEnd<NumToWrite) {
  85.                 rdLen=(secoff+(NumToWrite-wrEnd)*2<=STM_SECTOR_SIZE)?NumToWrite-wrEnd:(STM_SECTOR_SIZE-secoff)/2;
  86.                 STMFLASH_Read(secpos*STM_SECTOR_SIZE,STMFLASH_BUF,STM_SECTOR_SIZE/2);
  87.                 for(i=0;i<rdLen;i++) {
  88.                         if(STMFLASH_BUF[secoff/2+i]!=0XFFFF) break;            
  89.                 }
  90.                 if (i<rdLen) {
  91.                         STMFLASH_PageErase(secpos*STM_SECTOR_SIZE+USER_ADDR);
  92.                         for(i=0;i<rdLen;i++)
  93.                         {
  94.                                 STMFLASH_BUF[i+secoff/2]=pBuffer[i+wrEnd];          
  95.                         }
  96.                         STMFLASH_Write_NoCheck(USER_ADDR+secpos*STM_SECTOR_SIZE,STMFLASH_BUF,STM_SECTOR_SIZE/2);
  97.                 }
  98.                 else
  99.                         STMFLASH_Write_NoCheck(USER_ADDR+secpos*STM_SECTOR_SIZE+secoff,pBuffer+wrEnd,rdLen);
  100.                
  101.                 secoff = 0;
  102.                 secpos++;
  103.                 wrEnd+=rdLen;
  104.         }
  105.         FLASH_Lock();
  106.         return 0;
  107. }
复制代码



评分

参与人数 1黑币 +40 收起 理由
admin + 40 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:845928 发表于 2020-11-19 16:35 | 显示全部楼层
如果只是保存少量一两个数据,使用RTC备份寄存器更方便啦,写FLASH太耗时间了(毫秒级)
回复

使用道具 举报

ID:703220 发表于 2020-11-19 19:52 | 显示全部楼层
daemondong 发表于 2020-11-19 13:02
自用的,你试试。STM32Flash.h

STM32Flash.c

多谢多谢
回复

使用道具 举报

ID:703220 发表于 2020-11-19 20:01 | 显示全部楼层
24335882qq 发表于 2020-11-19 16:35
如果只是保存少量一两个数据,使用RTC备份寄存器更方便啦,写FLASH太耗时间了(毫秒级)

好的,我试试
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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