STM32单片机-FLASH闪存

2024-06-21 03:04
文章标签 闪存 stm32 单片机 flash

本文主要是介绍STM32单片机-FLASH闪存,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

STM32单片机-FLASH闪存

  • 一、FLASH简介
  • 二、FLASH工作原理
  • 三、读写内部FLASH
  • 四、读取芯片ID

一、FLASH简介

  • STM32F1系列的FLASH包含程序存储器系统存储器选项字节三个部分,通过闪存存储器接口(外设)可以对程序存储器和选项字节进行擦除和编程
  • 读写FLASH的用途:

  利用程序存储器的剩余空间来保存掉电不丢失的用户数据
  通过在程序中编程(IAP),实现程序的自我更新

  • 在线编程(ICP)用于更新存储器的全部内容,它通过JTAGSWD协议系统加载程序(Bootloader)下载程序
  • 程序中编程(IAP)可以使用微控制器支持的任一种通信接口下载程序

  下图为中容量闪存模块组织
  主存储器:用来存放程序代码,主要且容量最大的部分,基本单位是1K的页,C8T6只有64K
  信息块启动程序代码-系统存储器,存放原厂写入的Bootloader,用于串口下载。用户选择字节-存放独立的参数
  闪存存储器接口寄存器:普通外设,存储介质是SRAM,控制擦除和编程

在这里插入图片描述

二、FLASH工作原理

  下图为FLASH基本结构图
  整个闪存分为程序存储器、系统存储器和选项字节
  以C8T6为例,程序存储器为64K,最后一页地址是0x0800 FC00。左边控制器是闪存管理院,可以擦除和编程程序存储器和选项字节。选项字节配置程序存储器的读写保护

在这里插入图片描述

FPEC擦除和编程程序存储器和选项字节时需要前置操作

  • FLASH解锁:FLASH操作前需要解锁,在键寄存器写入指定的键值来实现

  FPEC有三个键值:RDPRT键 = 0x000000A5(解除读保护)、KEY1 = 0x45670123、KEY2 = 0xCDEF89AB
  复位后,FPEC被保护,不能写入FLASH_CR。在FLASH_KEYR先写入KEY1,再写入KEY2解锁。错误的操作序列会在下次复位前锁死FPEC和LASH_CR
  加锁:设置FLASH_CR中的LOCK位锁住FPEC和FLASH_CR

  下图为闪存页擦除过程
  判断LOCK锁没锁,需要解锁,随后置寄存器、判断页地址、等待状态寄存器标志位,擦除

在这里插入图片描述

  下图为闪存全擦除过程
  判断LOCK锁没锁,需要解锁,随后置寄存器、等待状态寄存器标志位,擦除

在这里插入图片描述

  下图为闪存写入过程
  判断LOCK锁没锁,需要解锁,随后置寄存器、在指定地址写入数据、等待状态寄存器标志位

在这里插入图片描述

三、读写内部FLASH

  读内部FLASH指定地址的数据,只需要调用读函数即可uint16_t Data = *((__IO uint16_t *)(0x8000000)),其中数据位数可以更改,地址可以更改
  指定地址写数据时,需要先擦除再写
  下面为MyFLASH.c,其中包括擦除写数据

#include "stm32f10x.h"                  // Device header/*
@brief:读取指定地址FLASH里的地址-32、16和8位
*/
uint32_t MyFLASH_ReadWord(uint32_t Address)
{return *((__IO uint32_t *)(Address));//读取32位数据
}
uint16_t MyFLASH_ReadHalfWord(uint32_t Address)
{return *((__IO uint16_t *)(Address));//读取16位数据
}
uint8_t MyFLASH_ReadByte(uint32_t Address)
{return *((__IO uint8_t *)(Address));//读取8位数据
}/*
@brief:全擦除
*/
void MyFLASH_EraseAllPages()
{FLASH_Unlock();//解锁FLASH_EraseAllPages();FLASH_Lock();//锁上
}
/*
@brief:指定页擦除
*/
void MyFLASH_ErasePage(uint32_t PageAddress)
{FLASH_Unlock();//解锁FLASH_ErasePage(PageAddress);FLASH_Lock();//锁上
}
/*
@brief:指定地址写32位数据
*/
void MyFLASH_ProgramWord(uint32_t Address,uint32_t Data)
{FLASH_Unlock();//解锁FLASH_ProgramWord(Address,Data);FLASH_Lock();//锁上
}
/*
@brief:指定地址写16位数据
*/
void MyFLASH_ProgramHalfWord(uint32_t Address,uint16_t Data)
{FLASH_Unlock();//解锁FLASH_ProgramHalfWord(Address,Data);FLASH_Lock();//锁上
}

  由于FLASH是擦除后再写入,擦除后还容易丢数据,可以在RSAM里新建一个数组,FLASH的数据复制到SRAM,实现掉电不丢失,往FLASH里写入SRAM里的数据,实现参数的任意读写和保存
  首次上电,FLASH数据复制给SRAM数组时,需要判断第一个数据-标志位(任意设置),之后断电上电或者复位时,存在FLASH的数据(不丢失)继续复制给SRAM
  下面为Store.c

uint16_t Store_Data[512];void Store_Init()
{//第一次需要判断标志位if(MyFLASH_ReadHalfWord(0x0800FC00) != 0xA5A5){MyFLASH_ErasePage(0x0800FC00);MyFLASH_ProgramHalfWord(0x0800FC00,0xA5A5);for(uint16_t i = 1;i<512;i++){MyFLASH_ProgramHalfWord(0x0800FC00+i*2,0x0000);}}//设置闪存最后一页第一个半字为A5A5,剩下全部为0for(uint16_t i = 0;i<512;i++){Store_Data[i] = MyFLASH_ReadHalfWord(0x0800FC00+i*2);}//上电时保证数据不丢失,将FLASH数据复制到SRAM数组中
}
/*
@brief:往闪存里面写数据(SRAM数组-FLASH)
*/
void Store_Save()
{MyFLASH_ErasePage(0x0800FC00);for(uint16_t i = 0;i<512;i++){MyFLASH_ProgramHalfWord(0x0800FC00+i*2,Store_Data[i]);}
}
/*
@brief:清除FLASH
*/
void Store_Clear()
{for(uint16_t i = 1;i<512;i++)//标志位不擦除{Store_Data[i] = 0x0000;}Store_Save();
}

  下面为main.c,按键1-SRAM数组值加1,按键2-清零数组

uint8_t KeyNum;int main(void)
{OLED_Init();Key_Init();Store_Init();OLED_ShowString(1,1,"FLAG:");OLED_ShowString(2,1,"Data:");while(1){KeyNum = Key_GetNum();if(KeyNum == 1){Store_Data[1] ++;Store_Data[2] += 2;Store_Data[3] += 3;Store_Data[4] += 4;Store_Save();//SRAM数组写入到FLASH}if(KeyNum == 2){Store_Clear();}OLED_ShowHexNum(1,6,Store_Data[0],4);OLED_ShowHexNum(3,1,Store_Data[1],4);OLED_ShowHexNum(3,6,Store_Data[2],4);OLED_ShowHexNum(4,1,Store_Data[3],4);OLED_ShowHexNum(4,6,Store_Data[4],4);}
}

四、读取芯片ID

  读取ID只需要读取指定地址的数据即可

int main(void)
{OLED_Init();OLED_ShowString(1,1,"F_SIZE:");OLED_ShowHexNum(1,8,*((__IO uint16_t *)(0x1FFFF7E0)),4);OLED_ShowString(2,1,"U_ID:");OLED_ShowHexNum(2,6,*((__IO uint16_t *)(0x1FFFF7E8)),4);OLED_ShowHexNum(2,11,*((__IO uint16_t *)(0x1FFFF7E8+0x02)),4);OLED_ShowHexNum(3,1,*((__IO uint32_t *)(0x1FFFF7E8+0x04)),8);OLED_ShowHexNum(4,1,*((__IO uint32_t *)(0x1FFFF7E8+0x08)),8);while(1){}
}

这篇关于STM32单片机-FLASH闪存的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1080027

相关文章

51单片机学习记录———定时器

文章目录 前言一、定时器介绍二、STC89C52定时器资源三、定时器框图四、定时器模式五、定时器相关寄存器六、定时器练习 前言 一个学习嵌入式的小白~ 有问题评论区或私信指出~ 提示:以下是本篇文章正文内容,下面案例可供参考 一、定时器介绍 定时器介绍:51单片机的定时器属于单片机的内部资源,其电路的连接和运转均在单片机内部完成。 定时器作用: 1.用于计数系统,可

零基础STM32单片机编程入门(一)初识STM32单片机

文章目录 一.概要二.单片机型号命名规则三.STM32F103系统架构四.STM32F103C8T6单片机启动流程五.STM32F103C8T6单片机主要外设资源六.编程过程中芯片数据手册的作用1.单片机外设资源情况2.STM32单片机内部框图3.STM32单片机管脚图4.STM32单片机每个管脚可配功能5.单片机功耗数据6.FALSH编程时间,擦写次数7.I/O高低电平电压表格8.外设接口

STM32单片机PWR电源控制详解

文章目录 1. PWR概述 2. 电源结构框图 3. 上电复位和掉电复位 4. 可编程电压监测器 5. 低功耗模式 6. 模式选择 6.1 睡眠模式 6.2 停止模式 6.3 待机模式 7. 代码示例 1. PWR概述 PWR(Power Control)电源控制,负责管理STM32内部的电源供电部分,可以实现可编程电压监测器和低功耗模式的功能。 可编程电压监测器

google gemini1.5 flash视频图文理解能力初探(一)

市面能够对视频直接进行分析的大模型着实不多,而且很多支持多模态的大模型那效果着实也不好。 从这篇公众号不只是100万上下文,谷歌Gemini 1.5超强功能展示得知,Gemini 1.5可以一次性处理1小时的视频、11小时的音频或100,000行代码,并衍生出更多的数据分析玩法。能力覆盖: 跨模式理解和推理,当给出一部 44 分钟的巴斯特-基顿(Buster Keaton)无声电影时,该模型能准

【单片机毕业设计选题24024】-房间自动除湿控制系统

系统功能: 系统分为手动和自动模式,上电默认为自动模式。自动模式下如果获取到湿度 值大于设定的湿度值则自动打开风扇,手动模式下手动开关风扇。 系统上电后显示“欢迎使用除湿控制系统请稍后”,两秒钟后进入主页面显示。 第一行显示系统模式,手动或自动模式 第二行显示获取到的温湿度 第三行显示设置的湿度阈值 第四行显示风扇状态和系统报警状态,风扇状态有开关状态,系统状态和OK和 NG状态。

STM32学习之一:什么是STM32

目录 1.什么是STM32 2.STM32命名规则 3.STM32外设资源 4. STM32的系统架构 5. 从0到1搭建一个STM32工程 学习stm32已经很久了,因为种种原因,也有很久一段时间没接触过stm32了。等我捡起来的时候,发现很多都已经忘记了,重新捡起来吧。 每次谈到stm32如何如何,那么该如何解释什么是stm32呢? 1.什么是STM32 stm32

Ubuntu安装火狐Flash Player插件

1、进入官网下载页面选择:.tar.gz,适用于其他Linux。此次文件名为install_flash_player_11_linux.x86_64.tar.gz 2、解压文件 tar -zxvf install_flash_player_11_linux.x86_64.tar.gz 3、利用whereis命令查找mozilla文件夹的路径 whereis mozill

基于51单片机抽奖系统

基于51单片机抽奖系统 (仿真+程序) 功能介绍 具体功能: 1.利用5片74HC495对单片机的IO进行串并转换,进而控制5个1位数码管; 2.采用一个独立按键用于抽奖系统的启停控制; 3.8位拨码开关是用于设定随机数发生器的“种子值”(初始值); ​演示视频: 基于51单片机抽奖系统  添加图片注释,不超过 140 字(可选) 程序 #inclu

STM32学习 修改系统主频

前面时钟树的学习说明单片机的主频是可以修改的,那么怎么更改系统的主频,这里做一个简单的介绍。首先要明白,单片机的程序是如何运行,这里简单说明一下。 对应的代码在startup_stm32....文件里面,这里是复位程序的汇编代码。 复位子程序是系统上电后第一个执行的程序,调用 SystemInit 函数初始化系统时钟,然后调用 C 库函数 _mian,最终调用 main 函数去到 C

使用J-Link Commander查找STM32死机问题

接口:PA13,PA14,请勿连接复位引脚。 输入usb命令 这里我已经连接过了STM32F407VET6了。 再输入connect命令 这里我已经默认选择了SWD接口,4000K速率。 可以输入speed 4000命令选择4000K速率: 写一段崩溃代码进行测试: void CashCode(void){*((volatile uint32_t*) 0x080FFFFF)