STM32开发笔记38: 单片机内部Flash的读写

2019-07-16来源: eefocus关键字:STM32  单片机  内部Flash  读写

单片机型号:STM32F070F6P6


本文介绍应用C语言进行单片机内部Flash的读写技巧,将从查看文档开始,到最终完成完整的程序。


单片机型号:STM32F070F6P6


步骤如下:


1、查看文档《STM32F030x4/x6/x8/xC and STM32F070x6/xB advanced ARM®-based 32-bit MCUs》确认其Flash的内部结构。



2、查看文档确认STM32F070F6P6内部存储器地址分配。从下表中得到的主要信息是Main Flash memory的起始地址是0x08000000,长度是32KB,到0x08017FFF结束(结束值可不关心)。



3、继续查看Main Flash memory的内部结构,如下表所示。从此表可以看出其内部Flash按1Kbyte进行分页,由于STM32F070F6P6为32KB,所以一共分成32页,分别为Page0-Page31。这个也与Keil的内部设置是相吻合的,见下图。


4、建立Flash地址列表,加入如下程序,这些程序参照文档自己手动完成,在使用时,尽量靠后使用,以免和自身程序所占用的Flash空间重叠。


#define ADDR_FLASH_PAGE_0     ((uint32_t)0x08000000) /* Base @ of Page 0, 1 Kbytes */

#define ADDR_FLASH_PAGE_1     ((uint32_t)0x08000400) /* Base @ of Page 1, 1 Kbytes */

#define ADDR_FLASH_PAGE_2     ((uint32_t)0x08000800) /* Base @ of Page 2, 1 Kbytes */

#define ADDR_FLASH_PAGE_3     ((uint32_t)0x08000C00) /* Base @ of Page 3, 1 Kbytes */

#define ADDR_FLASH_PAGE_4     ((uint32_t)0x08001000) /* Base @ of Page 4, 1 Kbytes */

#define ADDR_FLASH_PAGE_5     ((uint32_t)0x08001400) /* Base @ of Page 5, 1 Kbytes */

#define ADDR_FLASH_PAGE_6     ((uint32_t)0x08001800) /* Base @ of Page 6, 1 Kbytes */

#define ADDR_FLASH_PAGE_7     ((uint32_t)0x08001C00) /* Base @ of Page 7, 1 Kbytes */

#define ADDR_FLASH_PAGE_8     ((uint32_t)0x08002000) /* Base @ of Page 8, 1 Kbytes */

#define ADDR_FLASH_PAGE_9     ((uint32_t)0x08002400) /* Base @ of Page 9, 1 Kbytes */

#define ADDR_FLASH_PAGE_10    ((uint32_t)0x08002800) /* Base @ of Page 10, 1 Kbytes */

#define ADDR_FLASH_PAGE_11    ((uint32_t)0x08002C00) /* Base @ of Page 11, 1 Kbytes */

#define ADDR_FLASH_PAGE_12    ((uint32_t)0x08003000) /* Base @ of Page 12, 1 Kbytes */

#define ADDR_FLASH_PAGE_13    ((uint32_t)0x08003400) /* Base @ of Page 13, 1 Kbytes */

#define ADDR_FLASH_PAGE_14    ((uint32_t)0x08003800) /* Base @ of Page 14, 1 Kbytes */

#define ADDR_FLASH_PAGE_15    ((uint32_t)0x08003C00) /* Base @ of Page 15, 1 Kbytes */

#define ADDR_FLASH_PAGE_16    ((uint32_t)0x08004000) /* Base @ of Page 16, 1 Kbytes */

#define ADDR_FLASH_PAGE_17    ((uint32_t)0x08004400) /* Base @ of Page 17, 1 Kbytes */

#define ADDR_FLASH_PAGE_18    ((uint32_t)0x08004800) /* Base @ of Page 18, 1 Kbytes */

#define ADDR_FLASH_PAGE_19    ((uint32_t)0x08004C00) /* Base @ of Page 19, 1 Kbytes */

#define ADDR_FLASH_PAGE_20    ((uint32_t)0x08005000) /* Base @ of Page 20, 1 Kbytes */

#define ADDR_FLASH_PAGE_21    ((uint32_t)0x08005400) /* Base @ of Page 21, 1 Kbytes */

#define ADDR_FLASH_PAGE_22    ((uint32_t)0x08005800) /* Base @ of Page 22, 1 Kbytes */

#define ADDR_FLASH_PAGE_23    ((uint32_t)0x08005C00) /* Base @ of Page 23, 1 Kbytes */

#define ADDR_FLASH_PAGE_24    ((uint32_t)0x08006000) /* Base @ of Page 24, 1 Kbytes */

#define ADDR_FLASH_PAGE_25    ((uint32_t)0x08006400) /* Base @ of Page 25, 1 Kbytes */

#define ADDR_FLASH_PAGE_26    ((uint32_t)0x08006800) /* Base @ of Page 26, 1 Kbytes */

#define ADDR_FLASH_PAGE_27    ((uint32_t)0x08006C00) /* Base @ of Page 27, 1 Kbytes */

#define ADDR_FLASH_PAGE_28    ((uint32_t)0x08007000) /* Base @ of Page 28, 1 Kbytes */

#define ADDR_FLASH_PAGE_29    ((uint32_t)0x08007400) /* Base @ of Page 29, 1 Kbytes */

#define ADDR_FLASH_PAGE_30    ((uint32_t)0x08007800) /* Base @ of Page 30, 1 Kbytes */

#define ADDR_FLASH_PAGE_31    ((uint32_t)0x08007C00) /* Base @ of Page 31, 1 Kbytes */

6、建立CFlash类,代码如下:


class CFlash

{

public:

    void UnLockFalsh(void);

    void LockFlash(void);

    boolean ErasePage(uint32_t u32_Page);

    boolean WriteDataToFlash(uint32_t address, uint8_t data3, uint8_t data2, uint8_t data1, uint8_t data0);

    boolean WriteDataToFlash(uint32_t address, uint16_t data1, uint16_t data0);

    boolean WriteDataToFlash(uint32_t address, uint32_t data);

    void ReadDataFromFlash(uint32_t address, uint8_t *data3, uint8_t *data2, uint8_t *data1, uint8_t *data0);

    void ReadDataFromFlash(uint32_t address, uint16_t *data1, uint16_t *data0);

    void ReadDataFromFlash(uint32_t address, uint32_t *data);

};

7、以下是上述成员函数的具体实现,参考使用即可。


#include "include.h"

 

void CFlash::UnLockFalsh(void)

{

    HAL_FLASH_Unlock();

}

 

void CFlash::LockFlash(void)

{

    HAL_FLASH_Lock();

}

boolean CFlash::ErasePage(uint32_t u32_Page)

{

    FLASH_EraseInitTypeDef EraseInitStruct;

    uint32_t PageError = 0;

 

    EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;

    EraseInitStruct.PageAddress = u32_Page;

    EraseInitStruct.NbPages = 1;

    if (HAL_FLASHEx_Erase(&EraseInitStruct, &PageError) != HAL_OK)

    {

        return TRUE;

    }

    return FALSE;

}

 

boolean CFlash::WriteDataToFlash(uint32_t address, uint8_t data3, uint8_t data2, uint8_t data1, uint8_t data0)

{

    if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, address, (data3 << 24) | (data2 << 16) | (data1 << 8) | data0) != HAL_OK)

    {

        return FALSE;

    }

    return TRUE;

}

 

boolean CFlash::WriteDataToFlash(uint32_t address, uint16_t data1, uint16_t data0)

{

    if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, address, (data1 << 16) |  data0) != HAL_OK)

    {

        return FALSE;

    }

    return TRUE;

}

 

boolean CFlash::WriteDataToFlash(uint32_t address, uint32_t data)

{

    if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, address, data) != HAL_OK)

    {

        return FALSE;

    }

    return TRUE;

}

 

 

void CFlash::ReadDataFromFlash(uint32_t address, uint8_t *data3, uint8_t *data2, uint8_t *data1, uint8_t *data0)

{

    uint32_t u32_Data;

    u32_Data = *(__IO uint32_t *)(address);

    if (data3 != NULL)

    {

        *data3 = (u32_Data >> 24) & 0xff;

    }

    if (data2 != NULL)

    {

        *data2 = (u32_Data >> 16) & 0xff;

    }

    if (data1 != NULL)

    {

        *data1 = (u32_Data >> 8) & 0xff;

    }

    if (data0 != NULL)

    {

        *data0 = u32_Data & 0xff;

    }

}

 

void CFlash::ReadDataFromFlash(uint32_t address, uint16_t *data1, uint16_t *data0)

{

    uint32_t u32_Data;

    u32_Data = *(__IO uint32_t *)(address);

    *data1 = (u32_Data >> 16) & 0xffff;

    *data0 = u32_Data & 0xffff;

}

 

void CFlash::ReadDataFromFlash(uint32_t address, uint32_t *data)

{

    *data =  *(__IO uint32_t *)(address);

}

8、到此,就可以直接进行Flash读写操作了。


关键字:STM32  单片机  内部Flash  读写 编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/ic468058.html 本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:STM32开发笔记39: Keil打开时提示”Warning #440“警告的解决方法
下一篇:STM32开发笔记37: 485总线的收发切换时间

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

STM32流水灯(基于库函数)
,GPIO_Pin_5);/ /PE.5 输出高}该代码里面就包含了一个函数 void LED_Init(void),该函数的功能就是用来实现配置 PB5和 PE5 为推挽输出。 这里需要注意的是: 在配置 STM32 外设的时候,任何时候都要先使能该外设的时钟。 GPIO 是挂载在 APB2 总线上的外设, 在固件库中对挂载在 APB2 总线上的外设时钟使能是通过函数 RCC_APB2PeriphClockCmd()来实现的。LED.h程序代码书写#ifndef __LED_H#define __LED_H#include "sys.h"//LED 端口定义#define LED0 PBout
发表于 2019-10-21
stm32入门——跑马灯(基于stm32f103zet6)
的驱动都要使能相应的时钟,首先看stm32系统的时钟框图经查阅资料可知,GPIO的时钟在APB2的外设时钟使能寄存器上,相关函数的定义在stm32f10x_rcc.h中 void   RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)其源代码为:void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState){  /* Check the parameters */ //检查值的有效性&nbs
发表于 2019-10-21
stm32入门——跑马灯(基于stm32f103zet6)
STM32流水灯的几种实现方法
#include “stm32f10x.h”void RCC_Configuration(void);//2void GPIO_Configuration(void);//GPIOvoid Delay(u32 count){u32 i=0;for(;i<count;i++);}int main(void){ RCC_Configuration();//3LED_Init();while(1){GPIO_SetBits(GPIOA,GPIO_Pin_0);//第一灯亮Delay(800000); //延时GPIO_ResetBits(GPIOA,GPIO_Pin_0); //第一灯灭Delay(800000); //延时
发表于 2019-10-21
STM32学习探究:流水灯的实现
流水灯的实现这里我们使用 stm32mini 开发板实现外接流水灯,这里我采用了三个灯(说明问题就可以了)。外接的引脚分别为PA2,PB8,PC13三个引脚,在连接的时候,采用灯的正极接GPIO引脚,负极接GND(这是一种合理的方式)。注意:虽然接VCC也可以发光,但是这样不是合理的连接方式,而且,发光的情况刚好与接GND的情况相反。参考的相关资料如下:时钟使能:端口配置:端口输出:具体实现的代码如下://led.h文件#ifndef __LED_H#define __LED_H  #include "sys.h"//LED端口定义#define LED0 PAout(2)#define LED1
发表于 2019-10-21
STM32学习探究:流水灯的实现
STM32学习探究:流水灯的实现
流水灯的实现这里我们使用 stm32mini 开发板实现外接流水灯,这里我采用了三个灯(说明问题就可以了)。外接的引脚分别为PA2,PB8,PC13三个引脚,在连接的时候,采用灯的正极接GPIO引脚,负极接GND(这是一种合理的方式)。注意:虽然接VCC也可以发光,但是这样不是合理的连接方式,而且,发光的情况刚好与接GND的情况相反。参考的相关资料如下:时钟使能:端口配置:端口输出:具体实现的代码如下://led.h文件#ifndef __LED_H#define __LED_H  #include "sys.h"//LED端口定义#define LED0 PAout(2) #define LED1
发表于 2019-10-21
STM32学习探究:流水灯的实现
STM32流水灯的几种实现方法
#include “stm32f10x.h”void RCC_Configuration(void);//2void GPIO_Configuration(void);//GPIOvoid Delay(u32 count){u32 i=0;for(;i<count;i++);}int main(void){ RCC_Configuration();//3LED_Init();while(1){GPIO_SetBits(GPIOA,GPIO_Pin_0);//第一灯亮 Delay(800000); //延时 GPIO_ResetBits(GPIOA,GPIO_Pin_0); //第一灯灭 Delay(800000); //延时
发表于 2019-10-21
小广播
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2019 EEWORLD.com.cn, Inc. All rights reserved