我是靠谱客的博主 温暖蜜粉,最近开发中收集的这篇文章主要介绍STM32CubeMX | STM32F1系列HAL库读写内部FLASHSTM32F1系列HAL库读写内部FLASH,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

STM32F1系列HAL库读写内部FLASH


扫描以下二维码,关注公众号雍正不秃头获取更多STM32资源及干货!
在这里插入图片描述


测试环境:

  • STM32F103RB
  • 20KBytes RAM
  • 128KBytes FLASH

注:本章节代码只适合STM32F1系列!


在这里插入图片描述


头文件


/**
 * @brief Create by AnKun on 2019/10/10
 */

#ifndef __FLASH_H
#define __FLASH_H

#include "main.h"

 移植修改区 ///

/* FLASH大小:128K */
#define STM32FLASH_SIZE  0x00020000UL

/* FLASH起始地址 */
#define STM32FLASH_BASE  FLASH_BASE

/* FLASH结束地址 */
#define STM32FLASH_END   (STM32FLASH_BASE | STM32FLASH_SIZE)

/* FLASH页大小:1K */
#define STM32FLASH_PAGE_SIZE FLASH_PAGE_SIZE

/* FLASH总页数 */
#define STM32FLASH_PAGE_NUM  (STM32FLASH_SIZE / STM32FLASH_PAGE_SIZE)

/// 导出函数声明 
void FLASH_Init(void);
uint32_t FLASH_Read(uint32_t Address, void *Buffer, uint32_t Size);
uint32_t FLASH_Write(uint32_t Address, const uint16_t *Buffer, uint32_t NumToWrite);
int FLASH_ErasePage(uint32_t PageAddress, uint32_t NbPages);
uint32_t FLASH_WriteNotCheck(uint32_t Address, const uint16_t *Buffer, uint32_t NumToWrite);

#endif // !__FLASH_H

 end of file 


源文件


/**
 * @file  flash.c
 *
 * @brief Create by AnKun on 2019/10/10
 *
 */

#include "flash.h"
#include <string.h>

static uint16_t FlashBuffer[STM32FLASH_PAGE_SIZE >> 1];

/// 初始化FLASH
void FLASH_Init(void)
{
    HAL_FLASH_Unlock();
    __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPERR);
    HAL_FLASH_Lock();
}

/**
 * 读FLASH
 * @param  Address 地址
 * @param  Buffer  存放读取的数据
 * @param  Size    要读取的数据大小,单位字节
 * @return         读出成功的字节数
 */
uint32_t FLASH_Read(uint32_t Address, void *Buffer, uint32_t Size)
{
    uint32_t nread = Size;
    uint8_t* d = (uint8_t *)Buffer;
    const uint8_t* s = (const uint8_t *)Address;

    if (!Buffer || Address < STM32FLASH_BASE || Address >= STM32FLASH_END)
        return 0;

    while (nread >= sizeof(uint32_t) && (((uint32_t)s) <= (STM32FLASH_END - 4)))
    {
        *(uint32_t *)d = *(uint32_t *)s;
        d += sizeof(uint32_t);
        s += sizeof(uint32_t);
        nread -= sizeof(uint32_t);
    }

    while (nread && (((uint32_t)s) < STM32FLASH_END))
    {
        *d++ = *s++;
        nread--;
    }

    return Size - nread;
}

/**
 * 写FLASH
 * @param  Address    写入起始地址,!!!要求2字节对齐!!!
 * @param  Buffer     待写入的数据,!!!要求2字节对齐!!!
 * @param  NumToWrite 要写入的数据量,单位:半字,!!!要求2字节对齐!!!
 * @return            实际写入的数据量,单位:字节
 */
uint32_t FLASH_Write(uint32_t Address, const uint16_t *Buffer, uint32_t NumToWrite)
{
    uint32_t i = 0;
    uint32_t pagepos = 0;         // 页位置
    uint32_t pageoff = 0;         // 页内偏移地址
    uint32_t pagefre = 0;         // 页内空余空间
    uint32_t offset = 0;          // Address在FLASH中的偏移
    uint32_t nwrite = NumToWrite; // 记录剩余要写入的数据量
    const uint16_t *pBuffer = (const uint16_t *)Buffer;

    /* 非法地址 */
    if (Address < STM32FLASH_BASE || Address > (STM32FLASH_END - 2) || NumToWrite == 0 || pBuffer == NULL)
        return 0;

    /* 解锁FLASH */
    HAL_FLASH_Unlock();

    /* 计算偏移地址 */
    offset = Address - STM32FLASH_BASE;

    /* 计算当前页位置 */
    pagepos = offset / STM32FLASH_PAGE_SIZE;

    /* 计算要写数据的起始地址在当前页内的偏移地址 */
    pageoff = ((offset % STM32FLASH_PAGE_SIZE) >> 1);

    /* 计算当前页内空余空间 */
    pagefre = ((STM32FLASH_PAGE_SIZE >> 1) - pageoff);

    /* 要写入的数据量低于当前页空余量 */
    if (nwrite <= pagefre)
        pagefre = nwrite;

    while (nwrite != 0)
    {
        /* 检查是否超页 */
        if (pagepos >= STM32FLASH_PAGE_NUM)
            break;

        /* 读取一页 */
        FLASH_Read(STM32FLASH_BASE + pagepos * STM32FLASH_PAGE_SIZE, FlashBuffer, STM32FLASH_PAGE_SIZE);

        /* 检查是否需要擦除 */
        for (i = 0; i < pagefre; i++)
        {
            if (*(FlashBuffer + pageoff + i) != 0xFFFF) /* FLASH擦出后默认内容全为0xFF */
                break;
        }

        if (i < pagefre)
        {
            uint32_t count = 0;
            uint32_t index = 0;
            uint32_t PageError = 0;
            FLASH_EraseInitTypeDef pEraseInit;

            /* 擦除一页 */
            pEraseInit.TypeErase = FLASH_TYPEERASE_PAGES;
            pEraseInit.PageAddress = STM32FLASH_BASE + pagepos * STM32FLASH_PAGE_SIZE;
            pEraseInit.Banks = FLASH_BANK_1;
            pEraseInit.NbPages = 1;
            if (HAL_FLASHEx_Erase(&pEraseInit, &PageError) != HAL_OK)
                break;

            /* 复制到缓存 */
            for (index = 0; index < pagefre; index++)
            {
                *(FlashBuffer + pageoff + index) = *(pBuffer + index);
            }

            /* 写回FLASH */
            count = FLASH_WriteNotCheck(STM32FLASH_BASE + pagepos * STM32FLASH_PAGE_SIZE, FlashBuffer, STM32FLASH_PAGE_SIZE >> 1);
            if (count != (STM32FLASH_PAGE_SIZE >> 1))
            {
                nwrite -= count;
                break;
            }
        }
        else
        {
            /* 无需擦除,直接写 */
            uint32_t count = FLASH_WriteNotCheck(Address, pBuffer, pagefre);
            if (count != pagefre)
            {
                nwrite -= count;
                break;
            }
        }

        pBuffer += pagefre;         /* 读取地址递增         */
        Address += (pagefre << 1);  /* 写入地址递增         */
        nwrite -= pagefre;          /* 更新剩余未写入数据量 */

        pagepos++;     /* 下一页           */
        pageoff = 0;   /* 页内偏移地址置零  */

        /* 根据剩余量计算下次写入数据量 */
        pagefre = nwrite >= (STM32FLASH_PAGE_SIZE >> 1) ? (STM32FLASH_PAGE_SIZE >> 1) : nwrite;
    }

    /* 加锁FLASH */
    HAL_FLASH_Lock();

    return ((NumToWrite - nwrite) << 1);
}

uint32_t FLASH_WriteNotCheck(uint32_t Address, const uint16_t *Buffer, uint32_t NumToWrite)
{
    uint32_t nwrite = NumToWrite;
    uint32_t addrmax = STM32FLASH_END - 2;

    while (nwrite)
    {
        if (Address > addrmax)
            break;

        HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, Address, *Buffer);
        if ((*(__IO uint16_t*) Address) != *Buffer)
            break;

        nwrite--;
        Buffer++;
        Address += 2;
    }
    return (NumToWrite - nwrite);
}

int FLASH_ErasePage(uint32_t PageAddress, uint32_t NbPages)
{
	uint32_t PageError = 0;
	FLASH_EraseInitTypeDef pEraseInit;
	pEraseInit.TypeErase = FLASH_TYPEERASE_PAGES;
	pEraseInit.PageAddress = PageAddress;
	pEraseInit.Banks = FLASH_BANK_1;
	pEraseInit.NbPages = 1;
	if(HAL_FLASHEx_Erase(&pEraseInit, &PageError) != HAL_OK)
	{
		return -1;
	}
	return 0;
}

 end of file 


最后

以上就是温暖蜜粉为你收集整理的STM32CubeMX | STM32F1系列HAL库读写内部FLASHSTM32F1系列HAL库读写内部FLASH的全部内容,希望文章能够帮你解决STM32CubeMX | STM32F1系列HAL库读写内部FLASHSTM32F1系列HAL库读写内部FLASH所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(83)

评论列表共有 0 条评论

立即
投稿
返回
顶部