STM32系列(HAL库)——内部FLASH读写实验_简约版

         在此篇文章前,写过另外一篇关于STM32内部FLash读写的文章——点击跳转。之前那篇文章的代码是移植于正点原子的,比较复杂,因为它考虑了写入字节大于1K或2K时需要换页写入的问题。但是在实际使用过程中,我们需要写入的数据常常远小于1K,因此本篇文章的代码适用于写入小量数据使用(即小于1K或2K——取决于单片机最小写入页)。

本次代码是借鉴了CubeMX固件库官方例程的代码,经过和上一篇代码结合整理,比较简约易懂。

1.关于CubeMX的配置

本次实验的选择的是STM32F103C8T6

CubeMX选择配置一下时钟树,开启串口1即可

2.具体代码如下

 (1)Flash.h

        本次例程选择写入的页是第62页到第64页,可自定义修改

#ifndef _FLASH_H_
#define _FLASH_H_
#include "main.h"
#include "stm32f1xx_hal_flash_ex.h" 
#define u8 uint8_t
#define u16 uint16_t
#define u32 uint32_t


#define STM32_FLASH_SIZE 	64 	 	//所选STM32的FLASH容量大小(单位为K)
    #if     STM32_FLASH_SIZE < 256      //设置扇区大小
    #define STM_SECTOR_SIZE     1024    //1K字节
    #else 
    #define STM_SECTOR_SIZE	    2048    //2K字节
#endif

#define STM32_FLASH_BASE            0x08000000 		//STM32 FLASH的起始地址
#define FLASH_USER_START_ADDR   ( STM32_FLASH_BASE + STM_SECTOR_SIZE * 62 ) //写Flash的地址,这里从第62页开始
#define FLASH_USER_END_ADDR     ( STM32_FLASH_BASE + STM_SECTOR_SIZE * 64 ) //写Flash的地址,这里以第64页结束


void Flash_Erase(void); 
void Flash_Write(u32 *pBuffer,u32 NumToWrite);
void Flash_Read(u32 *pBuffer,u32 NumToRead);


#endif

(2)Flash.c 

#include "Flash.h"
#include <stdio.h>

static FLASH_EraseInitTypeDef EraseInitStruct;
u32 PAGEError = 0;
 /**********************************************************************************
  * 函数功能: 页擦除
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明:无 
  */
void Flash_Erase(void)
{  	
    EraseInitStruct.TypeErase   = FLASH_TYPEERASE_PAGES;
    EraseInitStruct.PageAddress = FLASH_USER_START_ADDR;
    EraseInitStruct.NbPages     = (FLASH_USER_END_ADDR - FLASH_USER_START_ADDR) / STM_SECTOR_SIZE;
    
     if (HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError) != HAL_OK)  
	 {
		 HAL_FLASH_Lock();  
		 printf(" Error...1\r\n");
         Error_Handler( );
	 }
}
 /**********************************************************************************
  * 函数功能: 数据写入
  * 输入参数: 写入数据缓存数组指针、写入数据数
  * 返 回 值: 无
  * 说    明:无 
  */    
void Flash_Write(u32 *pBuffer,u32  NumToWrite)
{

    u16  i=0;
    u32 Address = FLASH_USER_START_ADDR;
    HAL_FLASH_Unlock();	    //解锁
    Flash_Erase( );         //先擦除
                            //再写入
       printf(" 擦除完成,准备写入......\r\n");
     while ( (Address < FLASH_USER_END_ADDR) && (i<NumToWrite)  )    
    {
        if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, Address, pBuffer[i]) == HAL_OK)
        {
            Address = Address + 4;  //地址后移4个字节
            i++;
        }
        else
		{  
			printf(" Error...2\r\n"); 
            Error_Handler( );            
		}
    }
  
    HAL_FLASH_Lock();   //上锁


}

 /**********************************************************************************
  * 函数功能: 数据读取
  * 输入参数: 读取数据缓存数组指针、读出数据数
  * 返 回 值: 无
  * 说    明:无
  */
void Flash_Read(u32  *pBuffer,u32  NumToRead)
{
    u16  i=0;
    u32 Address = FLASH_USER_START_ADDR;
    
    while ( (Address < FLASH_USER_END_ADDR) && (i<NumToRead)  )
  {
    pBuffer[i++]= *(__IO u32 *)Address;  
    Address = Address + 4;   //地址后移4个字节
  }
  
}

(3)main.c

①添加头文件、变量声明

#include "Flash.h"
#include <stdio.h>

u8 TEXT_Buffer[]={"STM32_HAL_FLASH_TEST_"};//要写入到STM32 FLASH的字符串数组
#define SIZE sizeof(TEXT_Buffer)	 	//数组长度
u8 datatemp[SIZE];  //Flash读取缓存数组
u8 *p=datatemp;	    //数组指针

②main函数

测试时添加在while循环前即可,此段代码不需要重复运行。实现的操作为运行一次写入函数后,运行一次读取函数。

    printf(" 串口OK!......\r\n");
    HAL_Delay(2000);  

    Flash_Write((u32*)TEXT_Buffer,(SIZE+3)/4);  //强制转换后写入数组长度向上取整(SIZE+3)/4
    printf(" 写入成功,准备读取......\r\n");
    Flash_Read((u32*)datatemp,(SIZE+3)/4);
    printf(" 读取成功......写入内容为:\r\n");
    printf(" %s\r\n",p);

3.实现效果

### STM32 HAL 内部 Flash 读写示例 对于STM32系列微控制器而言,在使用HAL进行内部Flash操作时,通常会涉及到初始化、擦除页、编程以及验证数据等功能。下面提供一段基于STM32 HAL实现内部Flash读写的C语言代码示例。 #### 初始化Flash接口 在执行任何Flash操作之前,需要先调用`HAL_FLASH_Unlock()`解锁Flash访问权限;完成所有操作后再通过`HAL_FLASH_Lock()`锁定以保护存储区域不受意外更改的影响[^1]。 ```c // 解锁闪存程序/擦除控制寄存器 if (HAL_FLASH_Unlock() != HAL_OK) { // 错误处理... } ``` #### 擦除指定页面 由于Flash是以页为单位管理的,所以在写入新数据前可能需要先清除目标位置所在的整个页面。这一步骤由函数`HAL_FLASHEx_Erase()`负责完成,并接受指向结构体FLASH_EraseInitTypeDef实例的指针作为参数之一,该结构包含了要擦除的具体配置信息如起始地址和结束地址等。 ```c FLASH_EraseInitTypeDef eraseInitStruct; uint32_t pageError; eraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES; eraseInitStruct.PageAddress = ADDR_FLASH_PAGE_127; // 假设我们要擦除第127页 eraseInitStruct.NbPages = 1; if (HAL_FLASHEx_Erase(&eraseInitStruct, &pageError) != HAL_OK) { // 处理错误情况... } // 如果有多个连续页面,则增加NbPages的数量即可一次性全部清空。 ``` #### 编程(即写入) 当准备就绪后就可以向已擦除过的空间内写入新的字节序列了。注意每次只能按半字(word)或双字(double word)的形式传递给`HAL_FLASH_Program()`方法,因此如果打算保存字符串或其他形式的数据则需提前做好转换工作。 ```c uint32_t address = ADDR_FLASH_PAGE_127 + OFFSET_INTO_PAGE; uint64_t dataToWrite = 0xAABBCCDDEEFF1122ULL; for(int i=0;i<sizeof(dataToWrite)/sizeof(uint64_t);i++){ if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD,address,dataToWrite)!=HAL_OK){ // 再次尝试或者报告失败... } address += sizeof(uint64_t); } ``` #### 验证写入结果 最后建议再次从相同的位置读取回刚刚写进去的内容并与预期值对比确认无误。这部分可以通过简单的循环语句配合标准I/O指令轻松达成目的。 ```c volatile uint64_t readBackData; address = ADDR_FLASH_PAGE_127 + OFFSET_INTO_PAGE; readBackData = *(__IO uint64_t*)address; if(readBackData!=dataToWrite){ // 数据校验未通过... }else{ // 成功匹配! } ```
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

嵌入式创客工坊

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

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

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

打赏作者

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

抵扣说明:

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

余额充值