STM32CubeMX | STM32F1系列HAL库读写内部FLASH

STM32F1系列HAL库读写内部FLASH


测试环境:

  • STM32F103RB
  • 20KBytes RAM
  • 128KBytes FLASH

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


在这里插入图片描述


头文件


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

#ifndef __FLASH_H
#define __FLASH_H

#include "main.h"

///
///
/// 移植修改区 
///
///

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

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



///
///
/// 导出函数声明 
///
///

void FLASH_Init(void);
void FLASH_Read(uint32_t Address, uint16_t* Buffer, uint32_t NumToRead);
void FLASH_Write(uint32_t Address, const uint16_t *Buffer, uint32_t NumToWrite);
int FLASH_ErasePage(uint32_t PageAddress, uint32_t NbPages);
void FLASH_WriteNotCheck(uint32_t Address, const uint16_t *Buffer, uint32_t NumToWrite);

void FLASH_SetReadProtectionState(int state);

#endif // !__FLASH_H


源文件


/**
 * @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   读取地址,!!!要求2字节对齐!!!
 * @param  Buffer    存放读取的数据
 * @param  NumToRead 要读取的数据量,单位:半字
 */
void FLASH_Read(uint32_t Address, uint16_t* Buffer, uint32_t NumToRead)
{
	while(NumToRead != 0)
	{
		*Buffer = (*(volatile uint16_t *)Address);
		Buffer++;
		NumToRead--;
		Address += 2;
	}
}

/**
 * 写FLASH
 * @param  Address    写入起始地址,!!!要求2字节对齐!!!
 * @param  Buffer     待写入的数据,!!!要求2字节对齐!!!
 * @param  NumToWrite 要写入的数据量,单位:半字
 */
void 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;

    /* 解锁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)
    {
        /* 读取一页 */
        FLASH_Read(STM32FLASH_BASE + pagepos * STM32FLASH_PAGE_SIZE, FlashBuffer, STM32FLASH_PAGE_SIZE >> 1);

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

        if (i < pagefre)
        {
            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 */
            FLASH_WriteNotCheck(STM32FLASH_BASE + pagepos * STM32FLASH_PAGE_SIZE, FlashBuffer, STM32FLASH_PAGE_SIZE >> 1);
        }
        else
        {
            /* 无需擦除,直接写 */
			FLASH_WriteNotCheck(Address, Buffer, pagefre);
        }
        
        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();
}

void FLASH_WriteNotCheck(uint32_t Address, const uint16_t *Buffer, uint32_t NumToWrite)
{
    while (NumToWrite != 0)
    {
        if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, Address, *Buffer) != HAL_OK)
			break;
		NumToWrite--;
		Buffer++;
        Address += 2;
    }
}

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;
}

void FLASH_SetReadProtectionState(int state)
{
    FLASH_OBProgramInitTypeDef OptionsBytesStruct;
    HAL_FLASHEx_OBGetConfig(&OptionsBytesStruct);

    HAL_FLASH_Unlock();
    HAL_FLASH_OB_Unlock();

    if(state)
    {
        if(OptionsBytesStruct.RDPLevel == OB_RDP_LEVEL0)
        {
            OptionsBytesStruct.OptionType = OPTIONBYTE_RDP;
            OptionsBytesStruct.RDPLevel   = OB_RDP_LEVEL1;
			HAL_FLASHEx_OBProgram(&OptionsBytesStruct);
        }
    }
    else
    {
        if(OptionsBytesStruct.RDPLevel == OB_RDP_LEVEL1)
        {
            OptionsBytesStruct.OptionType = OPTIONBYTE_RDP;
            OptionsBytesStruct.RDPLevel   = OB_RDP_LEVEL0;
			HAL_FLASHEx_OBProgram(&OptionsBytesStruct);
        }
    }
	
    HAL_FLASH_OB_Lock();
    HAL_FLASH_Lock();
}


  • 18
    点赞
  • 95
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
STM32CubeMX是由STMicroelectronics开发的一款集成开发环境(IDE),用于快速生成STM32微控制器相关的初始化代码。它提供了用户友好的图形界面,支持中文语言,使得开发人员可以轻松地配置和初始化STM32微控制器的各种外设,例如GPIO、USART、I2C等。STM32CubeMX还能够生成初始化代码模板,并支持导出至主流的IDE平台,如Keil、IAR等。 相对于STM32CubeMXSTM32F1的HAL(Hardware Abstraction Layer)是一种更底层的API层,用于抽象硬件细节,为开发人员提供更直接、更灵活的访问STM32F1系列微控制器的各种外设。HAL提供了一系列函数接口,方便用户进行底层硬件编程,例如GPIO的操作、USART的发送接收等。 STM32CubeMXSTM32F1的HAL在开发过程中都有各自的优点。STM32CubeMX提供了一个易于使用的图形化界面,使得微控制器初学者能够更加快速地进行外设配置,生成初始化代码,并支持中文,方便使用中国开发者。而HAL提供了更灵活、更底层的硬件接口,允许开发者直接调用底层寄存器操作,满足对微控制器性能和资源要求更高的应用场景。 总之,STM32CubeMXSTM32F1的HALSTM32微控制器开发的两个重要工具。对于初学者来说,可以先通过STM32CubeMX进行外设配置和生成初始化代码,然后使用HAL进行更高级的编程。而对于有一定经验的开发者来说,可以直接使用HAL进行底层硬件操作。无论是哪种方式,都能够帮助开发者更加快速、高效地进行STM32F1系列微控制器的开发工作。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

觉皇嵌入式

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值