OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 1224|回复: 10

stm32f103ret6读写flash数据丢失

[复制链接]

66

主题

250

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1146
金钱
1146
注册时间
2015-11-29
在线时间
150 小时
发表于 2025-12-31 14:16:13 | 显示全部楼层 |阅读模式
10金钱
#include "stm32f10x_it.h"
#include "stm32f10x.h"
#include "globle.h"
#include "stm32f10x_conf.h"
//#include "usart.h"
#include "adc.h"
#include "Driver.h"
#include "Ex_Control.h"
#include "Flashdata.h"

uint16_t writedata[200]={0};
uint16_t readdata[200]={0};
//Threshold Laser_Threshold;
Adapatpara Laser_Adapatpara;
Adapatpara1 Laser_Adapatpara1;
biaoding_value biaoding_current;
void writeflash(uint32_t data1,uint32_t data2)
{
//        uint32_t EraseCounter = 0x00;         //记录要擦除多少页
        uint32_t Address = 0x00;                                //记录写入的地址
        uint16_t Data = 0;                        //记录写入的数据
//        uint32_t NbrOfPage = 0x00;                        //记录写入多少页
        uint8_t i=0;
       
        if((data1==WRITE_START_ADDR)&&(data2==WRITE_END_ADDR))
        {
                        FLASH_Status FLASHStatus = FLASH_COMPLETE; //记录每次擦除的结果       
                         /* 解锁 */
                        FLASH_Unlock();

                        /* 清空所有标志位 */
                        FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);       

                        /* 按页擦除*/
                        FLASHStatus=FLASH_ErasePage(WRITE_START_ADDR);  //擦除1页
//                 for(EraseCounter = 0; (EraseCounter < NbrOfPage) && (FLASHStatus == FLASH_COMPLETE); EraseCounter++)
//                        {
//                                FLASHStatus = FLASH_ErasePage(WRITE_START_ADDR + (FLASH_PAGE_SIZE * EraseCounter));
//                       
//                        }
                       
                        /* 向内部FLASH写入数据 */
                        if(FLASHStatus == FLASH_COMPLETE)  //擦除成功
                        {
                                Address = WRITE_START_ADDR;
                               
                                while((Address < WRITE_END_ADDR) && (FLASHStatus == FLASH_COMPLETE))
                                {
                                        Data=writedata[i];
                                        FLASHStatus = FLASH_ProgramHalfWord(Address, Data);
                                        Address = Address + 2;
                                        i++;
                                }
                        }
                FLASH_Lock();
}
}

void readflash(void)
{
        uint32_t Address = 0;                                //读取的地址
        uint8_t i=0x00;
        Address = WRITE_START_ADDR;
        for(i=0;i<200;i++)
        {
                readdata[i]=*(__IO uint16_t*)Address;
                Address=Address+2;
        }
}
void Adapat_Para_Updata(void)
{
        uint8_t i=0;
        writedata[0]=0xA5A5;
   for(i=0;i<200;i++)
{
writedata[i]=i;
}

        writeflash(WRITE_START_ADDR,WRITE_END_ADDR);       
       
}
偶尔出现数据从readdata[85]到readdata[120]丢失。


最佳答案

查看完整内容[请看2#楼]

https://download.csdn.net/blog/column/12561144/135722340
回复

使用道具 举报

8

主题

593

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2999
金钱
2999
注册时间
2016-5-13
在线时间
189 小时
发表于 2025-12-31 14:16:14 | 显示全部楼层
虽然不明白你们在说什么,但感觉很厉害的样子。
回复

使用道具 举报

66

主题

250

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1146
金钱
1146
注册时间
2015-11-29
在线时间
150 小时
 楼主| 发表于 2025-12-31 14:18:56 | 显示全部楼层
#define WRITE_START_ADDR  ((uint32_t)0x800C000)   #define WRITE_END_ADDR    ((uint32_t)0x800C0fa)    //200 个双字
回复

使用道具 举报

8

主题

593

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2999
金钱
2999
注册时间
2016-5-13
在线时间
189 小时
发表于 2026-1-4 15:57:00 | 显示全部楼层

我怀疑是你操作的时候有中断进来。就是读到85的时候有中断打断你的读取函数了。可以考虑读取开始前关闭总中断,读取完毕再打开。

__disable_irq();

开始读取....
读取结束.

__enable_irq();
虽然不明白你们在说什么,但感觉很厉害的样子。
回复

使用道具 举报

66

主题

250

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1146
金钱
1146
注册时间
2015-11-29
在线时间
150 小时
 楼主| 发表于 2026-4-2 10:51:50 | 显示全部楼层
上电先延时1s读取数据后再延时1s后再开启中断
回复

使用道具 举报

66

主题

250

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1146
金钱
1146
注册时间
2015-11-29
在线时间
150 小时
 楼主| 发表于 2026-4-2 10:52:15 | 显示全部楼层
电脑小白 发表于 2026-1-4 15:57
我怀疑是你操作的时候有中断进来。就是读到85的时候有中断打断你的读取函数了。可以考虑读取开始前关闭总 ...

上电先延时1s读取数据后再延时1s后再开启中断
回复

使用道具 举报

66

主题

250

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1146
金钱
1146
注册时间
2015-11-29
在线时间
150 小时
 楼主| 发表于 2026-4-2 10:52:46 | 显示全部楼层
应该是没有中断运行的
回复

使用道具 举报

66

主题

250

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1146
金钱
1146
注册时间
2015-11-29
在线时间
150 小时
 楼主| 发表于 2026-4-2 10:59:26 | 显示全部楼层
电脑小白 发表于 2026-1-4 15:57
我怀疑是你操作的时候有中断进来。就是读到85的时候有中断打断你的读取函数了。可以考虑读取开始前关闭总 ...

以为解决了,实际还是出现了。
回复

使用道具 举报

8

主题

593

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2999
金钱
2999
注册时间
2016-5-13
在线时间
189 小时
发表于 2026-4-15 11:09:46 | 显示全部楼层
/**
* @brief       从指定地址开始读出指定长度的数据
* @param       raddr : 起始地址
* @param       pbuf  : 数据指针
* @param       length: 要读取的字(32)数,即4个字节的整数倍
* @retval      无
*/
void stmflash_read(uint32_t raddr, uint32_t *pbuf, uint32_t length)
{
    uint32_t i;

    for (i = 0; i < length; i++)
    {
        pbuf = stmflash_read_word(raddr);    /* 读取4个字节. */
        raddr += 4; /* 偏移4个字节. */
    }
}
虽然不明白你们在说什么,但感觉很厉害的样子。
回复

使用道具 举报

8

主题

593

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2999
金钱
2999
注册时间
2016-5-13
在线时间
189 小时
发表于 2026-4-15 11:10:31 | 显示全部楼层
/**
* @brief       在FLASH 指定位置, 写入指定长度的数据(自动擦除)
*   @note      因为STM32F4的扇区实在太大,没办法本地保存扇区数据,所以本函数写地址如果非0XFF
*              ,那么会先擦除整个扇区且不保存扇区数据.所以写非0XFF的地址,将导致整个扇区数据丢失.
*              建议写之前确保扇区里没有重要数据,最好是整个扇区先擦除了,然后慢慢往后写.
*              该函数对OTP区域也有效!可以用来写OTP区!
*              OTP区域地址范围:0X1FFF7800~0X1FFF7A0F(注意:最后16字节,用于OTP数据块锁定,别乱写!!)
* @param       waddr   : 起始地址 (此地址必须为4的倍数!!,否则写入出错!)
* @param       pbuf    : 数据指针
* @param       length  : 要写入的 字(32位)数(就是要写入的32位数据的个数)
* @retval      无
*/
void stmflash_write(uint32_t waddr, uint32_t *pbuf, uint32_t length)
{
    FLASH_EraseInitTypeDef flasheraseinit;
    HAL_StatusTypeDef FlashStatus=HAL_OK;

    uint32_t addrx = 0;
    uint32_t endaddr = 0;
    uint32_t sectorerror=0;
   
    if (waddr < STM32_FLASH_BASE || waddr % 4 ||        /* 写入地址小于 STM32_FLASH_BASE, 或不是4的整数倍, 非法. */
        waddr > (STM32_FLASH_BASE + STM32_FLASH_SIZE))  /* 写入地址大于 STM32_FLASH_BASE + STM32_FLASH_SIZE, 非法. */
    {
        return;
    }

    HAL_FLASH_Unlock();             /* 解锁 */
    FLASH->ACR &= ~(1 << 10);       /* FLASH擦除期间,必须禁止数据缓存!!! */

    addrx = waddr;                  /* 写入的起始地址 */
    endaddr = waddr + length * 4;   /* 写入的结束地址 */

    if (addrx < 0X1FFF0000)         /* 只有主存储区,才需要执行擦除操作!! */
    {
        while (addrx < endaddr)     /* 扫清一切障碍.(对非FFFFFFFF的地方,先擦除) */
        {
            if (stmflash_read_word(addrx) != 0XFFFFFFFF)    /* 有非0XFFFFFFFF的地方,要擦除这个扇区 */
            {
                flasheraseinit.TypeErase=FLASH_TYPEERASE_SECTORS;       /* 擦除类型,扇区擦除 */
                flasheraseinit.Sector=stmflash_get_flash_sector(addrx); /* 要擦除的扇区 */
                flasheraseinit.NbSectors=1;                             /* 一次只擦除一个扇区 */
                flasheraseinit.VoltageRange=FLASH_VOLTAGE_RANGE_3;      /* 电压范围,VCC=2.7~3.6V之间!! */

                if(HAL_FLASHEx_Erase(&flasheraseinit, &sectorerror) != HAL_OK)
                {
                    break;/* 发生错误了 */
                }

            }
            else
            {
                addrx += 4;
            }
            FLASH_WaitForLastOperation(FLASH_WAITETIME);                 /* 等待上次操作完成 */
        }
    }

    FlashStatus=FLASH_WaitForLastOperation(FLASH_WAITETIME);             /* 等待上次操作完成 */

    if (FlashStatus==HAL_OK)
    {
        while (waddr < endaddr)     /* 写数据 */
        {
            if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, waddr, *pbuf) != HAL_OK)  /* 写入数据 */
            {
                break;              /* 写入异常 */
            }

            waddr += 4;
            pbuf++;
        }
    }
   
    FLASH->ACR |= 1 << 10;          /* FLASH擦除结束,开启数据fetch */

    HAL_FLASH_Lock();               /* 上锁 */
}
虽然不明白你们在说什么,但感觉很厉害的样子。
回复

使用道具 举报

8

主题

593

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2999
金钱
2999
注册时间
2016-5-13
在线时间
189 小时
发表于 2026-4-15 11:11:23 | 显示全部楼层
/**
****************************************************************************************************
* @file        stmflash.c
* @Author      正点原子团队(ALIENTEK)
* @version     V1.0
* @date        2021-10-28
* @brief       STM32内部FLASH读写 驱动代码
* @license     Copyright (c) 2020-2032, 广州市星翼电子科技有限公司
****************************************************************************************************
* @attention
*
* 实验平台:正点原子 探索者 F407开发板
* 在线视频:www.yuanzige.com
* 技术论坛:www.openedv.com
* 公司网址:www.alientek.com
* 购买地址penedv.taobao.com
*
* 修改说明
* V1.0 20211028
* 第一次发布
*
****************************************************************************************************
*/

//#include "./SYSTEM/usart/usart.h"
//#include "./SYSTEM/delay/delay.h"
#include "main.h"
#include "stmflash.h"

//uint8_t g_text_buf[25] = {"0125,0500,0115200,0115200"};
uint8_t g_text_buf[12] = {"0125,0500,00"};
//uint8_t reboot_flg = 0;
uint8_t datatemp[SIZE];

/**
* @brief       从指定地址读取一个字 (32位数据)
* @param       faddr   : 读取地址 (此地址必须为4倍数!!)
* @retval      读取到的数据 (32位)
*/
uint32_t stmflash_read_word(uint32_t faddr)
{
    return *(volatile uint32_t *)faddr;
}

/**
* @brief       获取某个地址所在的flash扇区
* @param       addr    : lash地址
* @retval      0~11,即addr所在的扇区
*/
uint8_t  stmflash_get_flash_sector(uint32_t addr)
{
    if (addr < ADDR_FLASH_SECTOR_1) return FLASH_SECTOR_0;
    else if (addr < ADDR_FLASH_SECTOR_2) return FLASH_SECTOR_1;
    else if (addr < ADDR_FLASH_SECTOR_3) return FLASH_SECTOR_2;
    else if (addr < ADDR_FLASH_SECTOR_4) return FLASH_SECTOR_3;
    else if (addr < ADDR_FLASH_SECTOR_5) return FLASH_SECTOR_4;
    else if (addr < ADDR_FLASH_SECTOR_6) return FLASH_SECTOR_5;
    else if (addr < ADDR_FLASH_SECTOR_7) return FLASH_SECTOR_6;
    else if (addr < ADDR_FLASH_SECTOR_8) return FLASH_SECTOR_7;
    else if (addr < ADDR_FLASH_SECTOR_9) return FLASH_SECTOR_8;
    else if (addr < ADDR_FLASH_SECTOR_10) return FLASH_SECTOR_9;
    else if (addr < ADDR_FLASH_SECTOR_11) return FLASH_SECTOR_10;
    return FLASH_SECTOR_11;
}
虽然不明白你们在说什么,但感觉很厉害的样子。
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /1 下一条

正点原子公众号

如发现本坛存在违规或侵权内容, 请点击这里发送邮件举报 (或致电020-38271790)。请提供侵权说明和联系方式。我们将及时审核依法处理,感谢配合。

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2026-4-24 20:34

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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