43. STM32内部Flash实验
STM32学习笔记:读写内部Flash(介绍+附代码)
STM32学习笔记:读写内部Flash(介绍+附代码)⼀、介绍⾸先我们需要了解⼀个内存映射:stm32的flash地址起始于0x0800 0000,结束地址是0x0800 0000加上芯⽚实际的flash⼤⼩,不同的芯⽚flash⼤⼩不同。
RAM起始地址是0x2000 0000,结束地址是0x2000 0000加上芯⽚的RAM⼤⼩。
不同的芯⽚RAM也不同。
Flash中的内容⼀般⽤来存储代码和⼀些定义为const的数据,断电不丢失,RAM可以理解为内存,⽤来存储代码运⾏时的数据,变量等等。
掉电数据丢失。
STM32将外设等都映射为地址的形式,对地址的操作就是对外设的操作。
stm32的外设地址从0x4000 0000开始,可以看到在库⽂件中,是通过基于0x4000 0000地址的偏移量来操作寄存器以及外设的。
⼀般情况下,程序⽂件是从 0x0800 0000 地址写⼊,这个是STM32开始执⾏的地⽅,0x0800 0004是STM32的中断向量表的起始地址。
在使⽤keil进⾏编写程序时,其编程地址的设置⼀般是这样的:程序的写⼊地址从0x08000000(数好零的个数)开始的,其⼤⼩为0x80000也就是512K的空间,换句话说就是告诉编译器flash的空间是从0x08000000-0x08080000,RAM的地址从0x20000000开始,⼤⼩为0x10000也就是64K的RAM。
这与STM32的内存地址映射关系是对应的。
M3复位后,从0x08000004取出复位中断的地址,并且跳转到复位中断程序,中断执⾏完之后会跳到我们的main函数,main函数⾥边⼀般是⼀个死循环,进去后就不会再退出,当有中断发⽣的时候,M3将PC指针强制跳转回中断向量表,然后根据中断源进⼊对应的中断函数,执⾏完中断函数之后,再次返回main函数中。
⼤致的流程就是这样。
1.1、内部Flash的构成:STM32F429 的内部 FLASH 包含主存储器、系统存储器、 OTP 区域以及选项字节区域,它们的地址分布及⼤⼩如下:STM32F103的中容量内部 FLASH 包含主存储器、系统存储器、 OTP 区域以及选项字节区域,它们的地址分布及⼤⼩如下:注意STM32F105VC的是有64K或128页x2K=256k字节的内置闪存存储器,⽤于存放程序和数据。
STM32F使用内部FLASH程序详解
STM32F0xx_FLASH_PAGE15_STARTADDR,
EEPPROM_PACKAGEHEAD );
/*Write length*/
FLASH_ProgramHalfWord( STM32F0xx_FLASH_PAGE15_STARTADDR+2 , length );
/*Write datas*/
但是,我们的数据是打包的(详见 2.2),所以还需要: 根据报头判断是不是有效数据 根据长度判断要读取多少数据 最后才是读出数据 4.1、判断数据有效性:
我们通过报头来判断数据是不是自己写入的。也就是判断 flash 第 15 页的第 1、2 个字 节是不是 0xaa55,如果不是,那这段数据是无效的。另外再判断一下长度字段,如果长度等 于 0,也就是后面没有数据,那这段数据也是无效的。
* Input
: buff:pointer of first data, length: write length
* Output
:
* Return
: true/false
*******************************************************************************/
* Function Name : readPackedMessageFromFlash
* Description : Read packed message form flash
* Input
: buff:point to first location of received buffer.length:Maxmum
* Input
: None
* Output
STM32的FLASH操作
关于STM32的FLASH操作说到STM32的FLSAH,我们的第一反应是用来装程序的,实际上,STM32的片内FLASH不仅用来装程序,还用来装芯片配置、芯片ID、自举程序等等。
当然,FLASH还可以用来装数据。
FLASH分类根据用途,STM32片内的FLASH分成两部分:主存储块、信息块。
主存储块用于存储程序,我们写的程序一般存储在这里。
信息块又分成两部分:系统存储器、选项字节。
系统存储器存储用于存放在系统存储器自举模式下的启动程序(BootLoader),当使用ISP方式加载程序时,就是由这个程序执行。
这个区域由芯片厂写入BootLoader,然后锁死,用户是无法改变这个区域的。
选项字节存储芯片的配置信息及对主存储块的保护信息。
FLASH的页面STM32的FLASH主存储块按页组织,有的产品每页1KB,有的产品每页2KB。
页面典型的用途就是用于按页擦除FLASH。
从这点来看,页面有点像通用FLASH的扇区。
STM32产品的分类STM32根据FLASH主存储块容量、页面的不同,系统存储器的不同,分为小容量、中容量、大容量、互联型,共四类产品。
小容量产品主存储块1-32KB,每页1KB。
系统存储器2KB。
中容量产品主存储块64-128KB,每页1KB。
系统存储器2KB。
大容量产品主存储块256KB以上,每页2KB。
系统存储器2KB。
互联型产品主存储块256KB以上,每页2KB。
系统存储器18KB。
对于具体一个产品属于哪类,可以查数据手册,或根据以下简单的规则进行区分:STM32F101xx、STM32F102xx 、STM32F103xx产品,根据其主存储块容量,一定是小容量、中容量、大容量产品中的一种,STM32F105xx、STM32F107xx 是互联型产品。
互联型产品与其它三类的不同之处就是BootLoader的不同,小中大容量产品的BootLoader只有2KB,只能通过USART1进行ISP,而互联型产品的BootLoader 有18KB,能通过USAT1、4、CAN等多种方式进行ISP。
分享STM32FLASH擦除以及防止误擦除程序代码、写入
分享STM32 FLASH 擦除(以及防止误擦除程序代码)、写入编译环境:我用的是(Keil)MDK4.7.2stm32库版本:我用的是3.5.0一、本文不对FLASH的基础知识做详细的介绍,不懂得地方请查阅有关资料。
对STM32 内部FLASH进行编程操作,需要遵循以下流程:FLASH解锁清除相关标志位擦除FLASH(先擦除后写入的原因是为了工业上制作方便,即物理实现方便)写入FLASH锁定FLASH实例:#define FLASH_PAGE_SIZE ((uint16_t)0x400) //如果一页为1K大小#define WRITE_START_ADDR ((uint32_t)0x08008000)//写入的起始地址#define WRITE_END_ADDR((uint32_t)0x0800C000)//结束地址uint32_t EraseCounter = 0x00, Address = 0x00;//擦除计数,写入地址uint32_t Data = 0x3210ABCD;//要写入的数据uint32_t NbrOfPage = 0x00;//记录要擦除的页数volatile FLASH_Status FLASHStatus =FLASH_COMPLETE;/*FLASH擦除完成标志*/void main(){/*解锁FLASH*/FLASH_Unlock();/*计算需要擦除FLASH页的个数 */NbrOfPage = (WRITE_END_ADDR - WRITE_START_ADDR) / FLASH_PAGE_SIZE;/* 清除所有挂起标志位 */FLASH_ClearFlag(FLASH_FLAG_EOP |FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);/* 擦除FLASH 页*/for(EraseCounter = 0; (EraseCounter 只要()里面的数是flash第xx页中对应的任何一个地址!就是擦除xx页全部内容!防止误擦除有用程序代码的方法方法一:首先要计算程序代码有多少,把FLASH存取地址设置在程序代码以外的地方,这样就不会破坏用户程序。
stm32f4 flash读写例程
一、概述STM32F4是ST公司推出的一款高性能的32位微控制器,它具有强大的性能和丰富的外设资源,广泛应用于工业控制、消费电子、通信设备等领域。
其中,STM32F4的Flash存储器模块具有较大的存储容量和快速的读写速度,非常适合用来存储程序代码和数据。
本文将介绍如何使用STM32F4的Flash存储器模块进行读写操作的例程。
二、开发环境准备1. 基本硬件准备:准备一块STM32F4开发板,如STM32F407ZGT6开发板。
一台电脑,安装了Keil或者其他的开发环境。
2. 软件准备:在电脑上安装好STM32CubeMX和Keil或者其他的开发环境。
三、创建工程1. 打开STM32CubeMX,新建一个工程,选择对应的芯片型号,例如选择STM32F407ZGT6。
2. 配置时钟树,使得系统时钟为想要的频率,一般选择高频率以获得更快的Flash读写速度。
3. 配置Flash存储器,选择合适的扇区大小和擦写次数。
4. 生成代码,导出工程。
四、编写代码1. 在Keil或者其他的开发环境中打开刚刚生成的工程。
2. 找到Flash读写相关的API,一般在芯片提供的库函数中可以找到。
3. 根据需要编写Flash读写的代码,例如可以编写一个函数来实现向Flash写入数据的功能。
五、编译下载1. 编译代码,生成bin文件。
2. 将bin文件下载到STM32F4开发板中,可以使用ST-Link或者其他下载工具来完成。
六、调试运行1. 确保下载成功,重启开发板。
2. 进行调试,观察Flash读写是否正常。
七、注意事项1. 在进行Flash写入操作时,一定要小心谨慎,避免对程序的正常运行造成影响。
2. 在进行Flash擦除操作时,务必注意擦除的范围,避免擦除了不该擦除的数据。
3. 在进行Flash读写操作时,需要留意Flash的特性和限制,以免造成不必要的麻烦。
八、总结本文介绍了如何在STM32F4开发板上使用Flash存储器进行读写操作的例程,从开发环境准备到代码编写再到调试运行都有详细的步骤说明,并给出了注意事项和总结。
读写STM32内部flash读写代码
读写STM32内部flash读写代码分类:单片机stm32 2012-03-25 06:16 10343人阅读评论(2) 收藏举报flashfunctionbyte编程存储io由于老师的要求,所以写了一份读写STM32内部FLASH的代码,这样的话就可以把STM32里面没有用来保存代码段的部分用来存储数据了。
由于《stm32flash编程手册》是很久很久以前看的,现在也没心情去仔细看那份手册了。
大概浏览了一下,只看到了STM32里面的flash是以16位为单位读写的。
为什么记住这个,因为之前想写一个字节老是出错,所以翻翻手册,果然看到不能写1个字节数据。
而且还发现,flash写地址为奇数时也会出错。
所以这份代码里面写flash的地址只能是偶数。
浏览过程中还发现,手册里面说写flash和擦除flash的时候会影响cpu的运行速度,没仔细看(真心不想看)。
其他具体手册里面的资料的话没有了,看有没有高手仔细看完,然后写个总结什么的。
而且flash的读写保护也没看清楚,好像这些保护都是针对页大小来保护的话。
这样的话就可以只保护代码段,这些放数据段不用保护了,这样可以省下flash芯片,不错吧。
废话不多说,直接上代码。
flash读写代码也不用初始化,拿来直接就用。
哈哈。
-------------------DataFlash.c----------------------------------#include "DataFlash.h"uint16_t Flash_Write_Without_check(uint32_t iAddress, uint8_t *buf, uint16_t iNumByteToWrite) {uint16_t i;volatile FLASH_Status FLASHStatus = FLASH_COMPLETE;i = 0;// FLASH_UnlockBank1();while((i < iNumByteToWrite) && (FLASHStatus == FLASH_COMPLETE)) {FLASHStatus = FLASH_ProgramHalfWord(iAddress, *(uint16_t*)buf);i = i+2;iAddress = iAddress + 2;buf = buf + 2;}return iNumByteToWrite;}/*** @brief Programs a half word at a specified Option Byte Data address. * @note This function can be used for all STM32F10x devices.* @param Address: specifies the address to be programmed.* @param buf: specifies the data to be programmed.* @param iNbrToWrite: the number to write into flash* @retval if success return the number to write, -1 if error**/int Flash_Write(uint32_t iAddress, uint8_t *buf, uint32_t iNbrToWrite) {/* Unlock the Flash Bank1 Program Erase controller */ uint32_t secpos;uint32_t iNumByteToWrite = iNbrToWrite;uint16_t secoff;uint16_t secremain;uint16_t i = 0;uint8_t tmp[FLASH_PAGE_SIZE];FLASH_UnlockBank1();secpos=iAddress & (~(FLASH_PAGE_SIZE -1 )) ;//扇区地址secoff=iAddress & (FLASH_PAGE_SIZE -1); //在扇区内的偏移secremain=FLASH_PAGE_SIZE-secoff; //扇区剩余空间大小volatile FLASH_Status FLASHStatus = FLASH_COMPLETE;if(iNumByteToWrite<=secremain) secremain = iNumByteToWrite;//不大于4096个字节while( 1 ) {Flash_Read(secpos, tmp, FLASH_PAGE_SIZE); //读出整个扇区for(i=0;i<secremain;i++) { //校验数据if(tmp[secoff+i]!=0XFF)break; //需要擦除}if(i<secremain) { //需要擦除FLASHStatus = FLASH_ErasePage(secpos); //擦除这个扇区if(FLASHStatus != FLASH_COMPLETE)return -1;for(i=0;i<secremain;i++) { //复制tmp[i+secoff]=buf[i];}Flash_Write_Without_check(secpos ,tmp ,FLASH_PAGE_SIZE);//写入整个扇区} else {Flash_Write_Without_check(iAddress,buf,secremain);//写已经擦除了的,直接写入扇区剩余区间.}if(iNumByteToWrite==secremain) //写入结束了break;else {secpos += FLASH_PAGE_SIZE;secoff = 0;//偏移位置为0buf += secremain; //指针偏移iAddress += secremain;//写地址偏移iNumByteToWrite -= secremain; //字节数递减if(iNumByteToWrite>FLASH_PAGE_SIZE)secremain=FLASH_PAGE_SIZE;//下一个扇区还是写不完else secremain = iNumByteToWrite; //下一个扇区可以写完了}}FLASH_LockBank1();return iNbrToWrite;}/*** @brief Programs a half word at a specified Option Byte Data address. * @note This function can be used for all STM32F10x devices.* @param Address: specifies the address to be programmed.* @param buf: specifies the data to be programmed.* @param iNbrToWrite: the number to read from flash* @retval if success return the number to write, without error**/int Flash_Read(uint32_t iAddress, uint8_t *buf, int32_t iNbrToRead) { int i = 0;while(i < iNbrToRead ) {*(buf + i) = *(__IO uint8_t*) iAddress++;i++;}return i;}-------------------DataFlash.h----------------------------------#ifndef __DATAFLASH_H__#define __DATAFLASH_H__#include "stm32f10x.h"#include "stm32f10x_flash.h"#if defined (STM32F10X_HD) || defined (STM32F10X_HD_VL) || defined (STM32F10X_CL) || defined (STM32F10X_XL)#define FLASH_PAGE_SIZE ((uint16_t)0x800)#else#define FLASH_PAGE_SIZE ((uint16_t)0x400)#endifint Flash_Read(uint32_t iAddress, uint8_t *buf, int32_t iNbrToRead) ;int Flash_Write(uint32_t iAddress, uint8_t *buf, uint32_t iNbrToWrite);#endif。
关于STM32的FLASH操作
关于STM32的FLASH操作STM32是一款由意法半导体(STMicroelectronics)推出的32位精简型单片机系列。
它采用了ARM Cortex-M内核,并在Flash和内存等方面进行了优化,提供了强大的性能和丰富的外设功能。
FLASH是STM32芯片上的一种非易失性存储器,可以用于存储应用程序代码、数据、配置信息等。
在STM32中进行FLASH操作可以通过编程和标准库函数两种方式实现。
下面将依次介绍这两种方法的使用。
一、编程方式编程方式是直接对FLASH进行底层的读写操作,需要对相关寄存器进行配置和控制。
1.写入数据在STM32的FLASH中写入数据的操作需要经历以下步骤:1) 解锁FLASH:通过FLASH_Unlock(函数解锁FLASH,使其可写入。
2) 擦除FLASH:通过FLASH_ErasePage(函数擦除要写入的FLASH扇区。
3) 写入数据:通过FLASH_ProgramByte(、FLASH_ProgramHalfWord(、FLASH_ProgramWord(等函数对FLASH进行数据写入。
4) 上锁FLASH:通过FLASH_Lock(函数上锁FLASH,防止误操作。
以下是一个简单的例子,演示如何通过编程方式对STM32的FLASH进行数据写入:```c#include "stm32f10x_flash.h"void ConfigureFlash(void)FLASH_Unlock(; // 解锁FlashFLASH_ClearFlag(FLASH_FLAG_EOP , FLASH_FLAG_PGERR ,FLASH_FLAG_WRPRTERR); // 清除状态标志FLASH_ErasePage(FLASH_START_ADDR); // 擦除扇区FLASH_Lock(; // 上锁Flash```2.读取数据读取STM32的FLASH数据需要通过指针的方式直接读取存储器的地址,如下所示:```c#define READ_FLASH(addr) (*(volatile uint32_t*)(addr))void ReadFlash(void)uint32_t data = READ_FLASH(FLASH_START_ADDR);//在这里对读取的数据进行处理```二、标准库函数方式STM32提供了一套标准库函数,方便开发者进行FLASH操作。
STM32片内FLASH特定地址写入数据不被擦除方法
STM32中存储区分为:随机存取存储器RAM和只读存储器ROM。
其中:RAM为常说的内存,比如手机的2G内存4G内存等,就是程序跑起来的时候所占用的存储空间,特点是掉电数据丢失。
ROM为常说的硬盘,比如手机的64G和128G等,可以简单的理解为硬盘的存储空间,特点是掉电数据不丢失,所以又叫“非易失性存储器件”。
ROM又包含:EEPROM和flash。
作为ROM的一份子,flash的特点自然是掉电数据不丢失。
但是,flash在STM32中比较重要,程序也是保存在这个地方,所以轻易不让用户进行随意的读写,以避免不必要的问题。
1、STM32 FLASH操作流程Flash操作已经属于嵌入式设备中很底层的操作了,直接对地址进行存取,简单描述,Flash操作大致需要以下流程:1、确定要写入Flash的首地址(稍后介绍确定地址的方法)2、解锁Flash3、对Flash进行操作(写入数据)4、对Flash重新上锁1.1 如何查找并选定要写入Flash十六进制地址值的方法要想选定安全的Flash地址进行读写,可以根据自己的STM32 MCU型号,查找数据手册,确定FLASH的地址区段,因为起始段会存储代码,所以一定要避开起始段,以避免数据错误。
(我一般是根据Flash大小计算Flash的最末尾地址,往前推一段地址空间,在这里一般不会对代码中的数据产生覆盖等影响)我此次操作Flash使用的MCU是STM32103C8T6,所以以该型号MCU为例进行描述:在数据手册中,可以看到STM32103C8T6的flash起始地址是0x0800 0000(如下图所示),而STM32103C8T6的Flash大小为64K,可以计算出STM32103C8T6的Flash地址范围是:0x0800 0000——0x0800 FFFF(计算方法参考另一篇博客:STM32内存大小与地址的对应关系以及计算方法)。
这里选取0x0800 F000作为读写操作的起始地址,对于C8T6这款MCU,操作这个起始地址应该算是很安全的范围了。
STM32-FLASH
STM32 flash操作对芯片内部flash进行操作的函数,包括读取,状态,擦除,写入等等,可以允许程序去操作flash上的数据。
基础应用1,FLASH时序延迟几个周期,等待总线同步操作。
推荐按照单片机系统运行频率,0—24MHz时,取Latency=0;24—48MHz时,取Latency=1;48~72MHz时,取Latency=2。
所有程序中必须的用法:FLASH_SetLatency(FLASH_Latency_2);位置:RCC初始化子函数里面,时钟起振之后。
基础应用2,开启FLASH预读缓冲功能,加速FLASH的读取。
所有程序中必须的用法:FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);位置:RCC初始化子函数里面,时钟起振之后。
3、阅读lib:调试所有外设初始化的函数。
我的理解——不理解,也不需要理解。
只要知道所有外设在调试的时候,EWRAM需要从这个函数里面获得调试所需信息的地址或者指针之类的信息。
基础应用1,只有一个函数debug。
所有程序中必须的。
用法:#ifdef DEBUGdebug();#endif位置:main函数开头,声明变量之后。
4、阅读nvic:系统中断管理。
我的理解——管理系统内部的中断,负责打开和关闭中断。
基础应用1,中断的初始化函数,包括设置中断向量表位置,和开启所需的中断两部分。
所有程序中必须的。
用法:void NVIC_Configuration(void){NVIC_InitTypeDef NVIC_InitStructure; //中断管理恢复默认参数#ifdef VECT_TAB_RAM //如果C/C++ Compiler\Preprocessor\Defined symbols中的定义了VECT_TAB_RAM(见程序库更改内容的表格)NVIC_SetVectorTable(NVIC_V ectTab_RAM, 0x0); //则在RAM调试#else //如果没有定义VECT_TAB_RAMNVIC_SetVectorTable(NVIC_V ectTab_FLASH, 0x0);//则在Flash里调试#endif //结束判断语句//以下为中断的开启过程,不是所有程序必须的。
STM32使用内部FLASH模拟EEPROM
每个页面都有三种可能的状态 :
●ERASED:: 页面为空。
●RECEIVE_DATA: 该页面正在接收来自另一个完整页面的数据。
●VALID_PAGE: 页面包含有效数据,该状态不会改变,直到所有有效数据完全转移到被擦除的页面。
下图为不同页的切换状态图,
一般情况下,在使用这种方法时,用户并不预先知道更新频率的变化。
本文档中描述的软件和实现使用两个 Flash 内存页面来模拟 EEPROM
每个变量元素由一个虚拟地址和一个存储在 Flash 内存中的值定义,以供后续检索或更新(在实现的软件中,虚拟地址和数据都是 16 位长)。
当数据被修改时,与之前的虚拟地址相关联的修改后的数据被存储到一个新的 Flash 内存位置中。
数据检索返回最新 Flash 内存位置中的修改数据
下图为 EEPROM 格式结构
下面图片的例子展示了三个 EEPROM 变量(Var1,Var2 及 Var3),并附有下列虚拟地址 :Var1: 5555h, Var2: 6666h, Var3: 7777h。
STM32 对内部FLASH读写接口函数
STM32对内部FLASH读写接口函数(2011-09-19 19:37:29)转载▼分类:安防,监控标签:stm32flash存储参数eepromit因为要用内部FLASH代替外部EEPROM,把参数放在STM32的0x08000000+320K处,其中20K是bootloader,300K是应用程序。
原理:先要把整页FLASH的内容搬到RAM中,然后在RAM中改动,然后擦除整页FLASH,再把改动后的内容写入原Flash页。
下面程序调试通过。
/****************************************************************************** ** Function Name : I2C_EE_BufferRead* Description : Reads a block of data from the EEPROM.* Input :* -RomAddr* -NumByteToRead* -pRomData* Output : None* Return : None******************************************************************************* void I2C_EE_BufferRead(u16 RomAddr,u16 NumByteToRead,u8 *pRomData){u32 param_flashbase;u8* ptr;param_flashbase = 0x8000000+(300+20)*1024;ptr = (u8*)(param_flashbase + RomAddr);while( NumByteToRead-- >0){*pRomData = *ptr; //直接赋值即可printf("0x%x ",*pRomData);pRomData++;ptr++;}return;}/****************************************************************************** ** Function Name :I2C_EE_BufferWrite* Description : Write a block of data to the EEPROM.* Input :* -RomAddr* -NumByteToRead* -pRomData* Output : None* Return : None******************************************************************************* void I2C_EE_BufferWrite(u8 DeviceType,u8 SlaveAddr,u16 RomAddr,u16 NumByteToWrite,u8 *pRomData){uint32_t param_flashbase;uint32_t tempaddress;uint32_t startaddress;uint32_t FlashAddress;uint32_t datasource;u8 buf1[PAGE_SIZE];u8 buf2[PAGE_SIZE];u32 pagenumber = 0x0;u32 EraseCounter = 0x0;u32 i = 0;FLASH_Status FLASHStatus = FLASH_COMPLETE;param_flashbase = 0x8000000+(300+20)*1024;startaddress=tempaddress = param_flashbase+RomAddr;/*********************起始指针不在Flash页的开始端*********************if( (tempaddress%PAGE_SIZE) != 0){ printf("startptr not in Page head \r\n");if( ((startaddress%PAGE_SIZE)+NumByteToWrite) > PAGE_SIZE ) /*超出一页范围{I2C_EE_BufferRead(0,0,(tempaddress-(tempaddress % PAGE_SIZE)),PAGE_SIZE,buf1); /*把起始地址所在页的内容读到内存buf1中memcpy(buf1+(tempaddress % PAGE_SIZE),pRomData,PAGE_SIZE-(tempaddress % PAGE_SIZE)); /*把需要写入的数据覆盖到buf1中while( FLASHStatus == FLASH_ErasePage(tempaddress) ) /*buf1写入到Flash{i=PAGE_SIZE/4;datasource = (uint32_t)buf1;FlashAddress = tempaddress-(tempaddress % PAGE_SIZE);while(i-- >0){FLASH_ProgramWord(FlashAddress,*(uint32_t*)datasource);if (*(uint32_t*)FlashAddress != *(uint32_t*)datasource){printf("I2C_EE_BufferWrite error!\r\n");return ;}datasource += 4;FlashAddress += 4;}break;}NumByteToWrite -= PAGE_SIZE-(startaddress % PAGE_SIZE); 需要写入字节数减去,上面覆盖上去的数据的字节数tempaddress += PAGE_SIZE-(tempaddress % PAGE_SIZE); /*把ptr指针指向下一个页起始位置if((NumByteToWrite % PAGE_SIZE) != 0) /*末指针不在Flash页的开始端{//读取1 PAGE 数据到内存,修改,然后写进去I2C_EE_BufferRead(0,0,tempaddress,PAGE_SIZE,buf2);memcpy(buf2,pRomData+PAGE_SIZE-startaddress%PAGE_SIZE+NumByteToWrite-Num ByteToWrite%PAGE_SIZE,(NumByteToWrite%PAGE_SIZE));while( FLASHStatus == FLASH_ErasePage( tempaddress+NumByteToWrite) ) /*把buf2写入到Flash中*{i=PAGE_SIZE/4;datasource = (uint32_t)buf2;FlashAddress = (tempaddress+NumByteToWrite-(NumByteToWrite % PAGE_SIZE)); /*末地址指针的页首while(i-- >0){FLASH_ProgramWord(FlashAddress,*(uint32_t*)datasource);if (*(uint32_t*)FlashAddress != *(uint32_t*)datasource){printf("I2C_EE_BufferWrite error!\r\n");return ;}datasource += 4;FlashAddress += 4;}break;}}NumByteToWrite -= NumByteToWrite % PAGE_SIZE;//擦除Flashpagenumber = NumByteToWrite/PAGE_SIZE;for (EraseCounter = 0; (EraseCounter < pagenumber) && (FLASHStatus ==FLASH_COMPLETE); EraseCounter++){FLASHStatus = FLASH_ErasePage( tempaddress + PAGE_SIZE*EraseCounter );}//写Flashdatasource = *(uint32_t *)(pRomData+ PAGE_SIZE-(startaddress % PAGE_SIZE) );FlashAddress = tempaddress;while( pagenumber-- > 0 ){i=PAGE_SIZE/4;while(i -- >0){FLASH_ProgramWord(FlashAddress,*(uint32_t*)datasource);if (*(uint32_t*)FlashAddress != *(uint32_t*)datasource){printf("I2C_EE_BufferWrite error!\r\n");return ;}datasource += 4;FlashAddress += 4;}}}else /*写的内容没有超出一页范围{printf("FlashWrire --in one page \r\n");I2C_EE_BufferRead(0,0,(startaddress-(startaddress % PAGE_SIZE)),PAGE_SIZE,buf1); /*把起始地址所在页的内容读到内存buf1中memcpy( (buf1+(tempaddress % PAGE_SIZE)),pRomData, NumByteToWrite ); /*把需要写入的数据覆盖到buf1中while( FLASHStatus == FLASH_ErasePage(tempaddress) ){i=PAGE_SIZE/4;datasource = (uint32_t)buf1;FlashAddress = tempaddress-(tempaddress % PAGE_SIZE);while(i-- >0){FLASH_ProgramWord(FlashAddress,*(uint32_t*)datasource);if (*(uint32_t *)FlashAddress != *(uint32_t *)datasource) /*读取Flash中的数据,看是否写入正确{printf("I2C_EE_BufferWrite error!\r\n");return ;}datasource += 4;FlashAddress += 4;}break;}}}/*******************起始指针在Flash页的开始端****************************else{ printf("startptr in Page head \r\n");if((NumByteToWrite % PAGE_SIZE) != 0){//读取1 PAGE 数据到内存,修改,然后写进去I2C_EE_BufferRead(0,0,(u16)(tempaddress+NumByteToWrite-(NumByteToWrite %PAGE_SIZE)),PAGE_SIZE,buf1);printf("already copy to bug1 \r\n");memcpy(buf1,pRomData+NumByteToWrite-(NumByteToWrite %PAGE_SIZE),(NumByteToWrite % PAGE_SIZE));//end of debug}//擦除Flashif( (NumByteToWrite%PAGE_SIZE) == 0 ){pagenumber = NumByteToWrite/PAGE_SIZE;}else{pagenumber = NumByteToWrite/PAGE_SIZE + 1;}for (EraseCounter = 0; (EraseCounter < pagenumber) && (FLASHStatus ==FLASH_COMPLETE); EraseCounter++){FLASHStatus = FLASH_ErasePage(startaddress + (PAGE_SIZE * EraseCounter)); }//写Flashif( pagenumber == 1) /*只有一页{i=PAGE_SIZE/4;datasource = (uint32_t)buf1;FlashAddress = startaddress;while(i-- >0){FLASH_ProgramWord(FlashAddress,*(uint32_t *)datasource);if (*(uint32_t *)FlashAddress != *(uint32_t *)datasource){printf("I2C_EE_BufferWrite error!\r\n");return ;}datasource +=4;FlashAddress +=4;}}else /*很多页时,先写前面页,最后写buf1{while( pagenumber-- > 1 ){datasource = (u32)pRomData;FlashAddress = startaddress;i=PAGE_SIZE/4;while(i -- >0){FLASH_ProgramWord( FlashAddress, *(uint32_t *)datasource );if (*(uint32_t *)FlashAddress != *(uint32_t *)datasource){printf("I2C_EE_BufferWrite error!\r\n");return ;}datasource += 4;FlashAddress += 4;}}//写后面的页datasource = (uint32_t)buf1;FlashAddress = startaddress+(pagenumber-1)*PAGE_SIZE;i=PAGE_SIZE/4;while(i -- >0){FLASH_ProgramWord( FlashAddress, *(uint32_t *)datasource ); if (*(uint32_t *)FlashAddress != *(uint32_t *)datasource){printf("I2C_EE_BufferWrite error!\r\n");return ;}datasource += 4;FlashAddress += 4;}}}}。
STM32在SRAM、FLASH中调试代码的配置方法
STM32在SRAM、FLASH中调试代码的配置方法STM32的FLASH擦写次数有限(大概为1万次),所以为了延长FLASH的使用时间,我们平时调试时可以选择在SRAM中进行硬件调试。
除此之外,SRAM 存储器的写入速度比在内部FLASH 中要快得多,所以下载程序到SRAM中的速度较快。
所以我们很有必要建立两个版本的工程配置,在SRAM中调试程序完毕后,再把代码下载到FLASH中即可。
这篇笔记主要分享在keil5中配置FLASH调试与SRAM调试的详细配置方法及如何切换两种配置。
本篇笔记以STM32F103ZET6为例。
其FLASH大小为512KB,SRAM的大小为64KB。
FLASH基地址为0x08000000,SRAM基地址为0x20000000。
在STM32F10XXX 里,可以通过BOOT1、BOOT0引脚来选择三种不同的模式:我们要在FLASH中进行硬件仿真调试还是在RAM中进行硬件仿真调试需要对这两个boot脚进行对应的设置以及程序下载的地址进行设置。
在F L A S H中进行硬件仿真调试1、硬件设置BOOT0配置为0,BOOT1随意设置。
2、keil设置本文以keil5为例。
步骤如下:(1)点击如下按钮,修改target的名称:target的名称是可以随意更改的,这里我们改为FLASH。
(2)点击Project->Options for Target Flash...(也可以点击魔术棒那个图标)进行配置。
首先对Target选项卡设置:设置IROM1的起始地址为0x8000000,大小为0x80000,即FLASH的基地址与大小。
设置IRAM1为0x20000000,大小为0x10000,即SRAM的基地址与大小。
(3)Debug选项设置:调试器根据实际进行选择,我们这里使用的调试器是ULINK2。
其它的按默认设置即可,然后点击Settings:(4)编译,然后按Ctrl+F5进入调试界面:然后点击全速运行:在Disassembly窗口中可看到地址为0x0800xxxx,说明代码烧进了FLASH中,这时候就可以像使用其他C语言IDE调试C语言程序一样打断点、单步运行我们的STM32程序啦。
STM32 FLASH实验-SPI
所以代码为:
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;//
选择全双工 SPI 模式
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //主机模式
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //8 位 SPI
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
//时钟悬空高
电平
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
//在第二个时
钟采集数据
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
//Nss 使用软件控
2、配置 GPIO 口的模式。 这这里我们要打开 GPIOG 和 GPIOB 的时钟,然后将片选端 PG13 设置
为推挽输出,然后设置 SPI 使用的 GPIO 口,将 PB13、PB14 和 PB15 设置 为复用推挽输入。大家可能疑惑为什么 PB14 也设置为输出呢?它不是应该 输入吗?在这里它是作为复用端口了,所以设置为复用推挽输出就是跟外设 连接,要外设自己来决定输入输出了。
/* SPI 的 IO 口设置 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure);
STM32FLASH操作
STM32 flash操作对芯片内部flash进行操作的函数,包括读取,状态,擦除,写入等等,可以允许程序去操作flash上的数据。
一、存储器映射1、统一编址,程序存储器、数据存储器、外设寄存器组织在一个4GB的地址空间。
2、小端格式3、映像(stm32f107,256KB产品)可以看到,所谓的256KB闪存,是指主存储,片上FLASH如下图所示:介绍了片上的资源后,来看他们的地址映像。
芯片将4GB的空间,划分为8个512MB的块(block),这些块有些是整块不用的,芯片对地址的安排可以参考数据手册,memory mapping章节中的那个图。
只有block1、2、3、7是使用的。
地址中block7是核内的外设对应的地址,block2是其他外设对应的地址。
block1的低地址64KB是片上SRAM,block0则如下图option bytes即是选项字节;system memory就是系统存储,也即片上ROM;这两部分就是所谓信息块。
Flash就是指主存储,有256KB。
再往下看alias to flash or system memory.....这个区域256KB就是启动开始的区域。
这个区域并没有一个自己的存储器,只是根据BOOT0、BOOT1的接法来选择哪个存储器映射到这个地址上。
如下图选择用户闪存启动,是典型的做法;选择系统存储器,则在ST烧写进去的自举程序引导下,通过USART1下载程序;选择从SRAM执行代码则方便调试,比较快。
二、复位CM3将复位视作异常,优先级最高的异常。
stm32f1有三种复位:系统复位、电源复位、备份区复位。
前两种是真正的复位,对他的响应由硬件完成,这个响应对软件流的影响是这样的:程序指针指向0x0000 0004,这个单元存储的是复位服务子程序(或者汇编叫子过程),同时从0x0000 0000获取堆栈顶的地址。
不同的复位类型还有对其他寄存的不同复位方式,这就完成了复位。
stm32f单片机内部flash模拟EEPROM操作源码
#include "stmflash.h"#include "delay.h"#include "usart.h"//解锁STM32的FLASHvoid STMFLASH_Unlock(void){FLASH->KEYR=FLASH_KEY1; //写入解锁序列.FLASH->KEYR=FLASH_KEY2;}//flash上锁void STMFLASH_Lock(void){FLASH->CR|=(u32)1<<31;//上锁}//得到FLASH状态//返回值://0,操作完成//1,忙//2,操作异常u8 STMFLASH_GetStatus(void){u32 res=0;res=FLASH->SR;if(res&(1<<16))return 1; //忙else if(res&(1<<4))return 2; //操作异常else if(res&(1<<5))return 2; //操作异常else if(res&(1<<6))return 2; //操作异常else if(res&(1<<7))return 2; //操作异常return 0; //没有任何状态/操作完成. }//等待操作完成//time:要延时的长短(单位:10us)//返回值://0,完成//2,操作异常//0XFF,超时u8 STMFLASH_WaitDone(u32 time){u8 res;do{res=STMFLASH_GetStatus();if(res!=1)break;//非忙,无需等待了,直接退出.delay_us(10);time--;}while(time);if(time==0)res=0xff;//TIMEOUTreturn res;}//擦除扇区//sectoraddr:扇区地址,范围是:0~11.//0~3,16K扇区;4,64K扇区;5~11,128K扇区.//返回值:执行情况u8 STMFLASH_EraseSector(u32 sectoraddr){u8 res=0;res=STMFLASH_WaitDone(200000);//等待上次操作结束,最大2sif(res==0){FLASH->CR&=~(3<<8); //清除PSIZE原来的设置FLASH->CR|=2<<8; //设置为32bit宽,确保VCC=2.7~3.6V之间!!FLASH->CR&=~(0X1F<<3);//清除原来的设置FLASH->CR|=sectoraddr<<3;//设置要擦除的扇区FLASH->CR|=1<<1; //扇区擦除FLASH->CR|=1<<16; //开始擦除res=STMFLASH_WaitDone(200000);//等待操作结束,最大2sif(res!=1) //非忙{FLASH->CR&=~(1<<1);//清除扇区擦除标志.}}return res;}//在FLASH指定地址写一个字//faddr:指定地址(此地址必须为4的倍数!!)//dat:要写入的数据//返回值:0,写入成功// 其他,写入失败u8 STMFLASH_WriteWord(u32 faddr, u32 dat){u8 res;res=STMFLASH_WaitDone(0XFF);if(res==0)//OK{FLASH->CR&=~(3<<8); //清除PSIZE原来的设置FLASH->CR|=2<<8; //设置为32bit宽,确保VCC=2.7~3.6V之间!!FLASH->CR|=1<<0; //编程使能*(vu32*)faddr=dat; //写入数据res=STMFLASH_WaitDone(0XFF);//等待操作完成,一个字编程,最多100us.if(res!=1)//操作成功{FLASH->CR&=~(1<<0);//清除PG位.}}return res;}//读取指定地址的一个字(32位数据)//faddr:读地址//返回值:对应数据.u32 STMFLASH_ReadWord(u32 faddr){return *(vu32*)faddr;}//获取某个地址所在的flash扇区//addr:flash地址//返回值:0~11,即addr所在的扇区u8 STMFLASH_GetFlashSector(u32 addr){if(addr<ADDR_FLASH_SECTOR_1)return 0;else if(addr<ADDR_FLASH_SECTOR_2)return 1;else if(addr<ADDR_FLASH_SECTOR_3)return 2;else if(addr<ADDR_FLASH_SECTOR_4)return 3;else if(addr<ADDR_FLASH_SECTOR_5)return 4;else if(addr<ADDR_FLASH_SECTOR_6)return 5;else if(addr<ADDR_FLASH_SECTOR_7)return 6;else if(addr<ADDR_FLASH_SECTOR_8)return 7;else if(addr<ADDR_FLASH_SECTOR_9)return 8;else if(addr<ADDR_FLASH_SECTOR_10)return 9;else if(addr<ADDR_FLASH_SECTOR_11)return 10;return 11;}//从指定地址开始写入指定长度的数据//特别注意:因为STM32F4的扇区实在太大,没办法本地保存扇区数据,所以本函数// 写地址如果非0XFF,那么会先擦除整个扇区且不保存扇区数据.所以// 写非0XFF的地址,将导致整个扇区数据丢失.建议写之前确保扇区里// 没有重要数据,最好是整个扇区先擦除了,然后慢慢往后写.//该函数对OTP区域也有效!可以用来写OTP区!//OTP区域地址范围:0X1FFF7800~0X1FFF7A0F(注意:最后16字节,用于OTP数据块锁定,别乱写!!)//WriteAddr:起始地址(此地址必须为4的倍数!!)//pBuffer:数据指针//NumToWrite:字(32位)数(就是要写入的32位数据的个数.)void STMFLASH_Write(u32 WriteAddr,u32 *pBuffer,u32 NumToWrite){u8 status=0;u32 addrx=0;u32 endaddr=0;if(WriteAddr<STM32_FLASH_BASE||WriteAddr%4)return; //非法地址STMFLASH_Unlock(); //解锁FLASH->ACR&=~(1<<10); //FLASH擦除期间,必须禁止数据缓存搞了我两晚上才发现这个问题!addrx=WriteAddr; //写入的起始地址endaddr=WriteAddr+NumToWrite*4; //写入的结束地址if(addrx<0X1FFF0000) //只有主存储区,才需要执行擦除操作!!{while(addrx<endaddr) //扫清一切障碍.(对非FFFFFFFF的地方,先擦除){if(STMFLASH_ReadWord(addrx)!=0XFFFFFFFF)//有非0XFFFFFFFF的地方,要擦除这个扇区{status=STMFLASH_EraseSector(STMFLASH_GetFlashSector(addrx));if(status)break; //发生错误了}else addrx+=4;}}if(status==0){while(WriteAddr<endaddr)//写数据{if(STMFLASH_WriteWord(WriteAddr,*pBuffer))//写入数据{break; //写入异常}WriteAddr+=4;pBuffer++;}}FLASH->ACR|=1<<10; //FLASH擦除结束,开启数据fetchSTMFLASH_Lock();//上锁}//从指定地址开始读出指定长度的数据//ReadAddr:起始地址//pBuffer:数据指针//NumToRead:字(32位)数void STMFLASH_Read(u32 ReadAddr,u32 *pBuffer,u32 NumToRead){u32 i;for(i=0;i<NumToRead;i++){pBuffer[i]=STMFLASH_ReadWord(ReadAddr);//读取4个字节.ReadAddr+=4;//偏移4个字节.}}//////////////////////////////////////////测试用/////////////////////////////////////////////WriteAddr:起始地址//WriteData:要写入的数据void Test_Write(u32 WriteAddr,u32 WriteData){STMFLASH_Write(WriteAddr,&WriteData,1);//写入一个字}//////////////////////////////////////////h文件///////////////////////////////////////////#ifndef __STMFLASH_H__#define __STMFLASH_H__#include "sys.h"//FLASH起始地址#define STM32_FLASH_BASE 0x08000000 //STM32 FLASH的起始地址//FLASH解锁键值#define FLASH_KEY1 0X45670123#define FLASH_KEY2 0XCDEF89AB//FLASH 扇区的起始地址#define ADDR_FLASH_SECTOR_0 ((u32)0x08000000) //扇区0起始地址, 16 Kbytes #define ADDR_FLASH_SECTOR_1 ((u32)0x08004000) //扇区1起始地址, 16 Kbytes #define ADDR_FLASH_SECTOR_2 ((u32)0x08008000) //扇区2起始地址, 16 Kbytes #define ADDR_FLASH_SECTOR_3 ((u32)0x0800C000) //扇区3起始地址, 16 Kbytes #define ADDR_FLASH_SECTOR_4 ((u32)0x08010000) //扇区4起始地址, 64 Kbytes #define ADDR_FLASH_SECTOR_5 ((u32)0x08020000) //扇区5起始地址, 128 Kbytes #define ADDR_FLASH_SECTOR_6 ((u32)0x08040000) //扇区6起始地址, 128 Kbytes #define ADDR_FLASH_SECTOR_7 ((u32)0x08060000) //扇区7起始地址, 128 Kbytes #define ADDR_FLASH_SECTOR_8 ((u32)0x08080000) //扇区8起始地址, 128 Kbytes#define ADDR_FLASH_SECTOR_9 ((u32)0x080A0000) //扇区9起始地址, 128 Kbytes #define ADDR_FLASH_SECTOR_10 ((u32)0x080C0000) //扇区10起始地址,128 Kbytes #define ADDR_FLASH_SECTOR_11 ((u32)0x080E0000) //扇区11起始地址,128 Kbytesvoid STMFLASH_Unlock(void); //FLASH解锁void STMFLASH_Lock(void); //FLASH上锁u8 STMFLASH_GetStatus(void); //获得状态u8 STMFLASH_WaitDone(u32 time); //等待操作结束u8 STMFLASH_ErasePage(u32 sectoraddr); //擦除页u8 STMFLASH_WriteWord(u32 faddr, u32 dat); //写入字u32 STMFLASH_ReadWord(u32 faddr); //读出字void STMFLASH_WriteLenByte(u32 WriteAddr,u32 DataToWrite,u16 Len); //指定地址开始写入指定长度的数据void STMFLASH_Write(u32 WriteAddr,u32 *pBuffer,u32 NumToWrite); //从指定地址开始写入指定长度的数据void STMFLASH_Read(u32 ReadAddr,u32 *pBuffer,u32 NumToRead); //从指定地址开始读出指定长度的数据//测试写入void Test_Write(u32 WriteAddr,u32 WriteData);#endif。
stm32h743对应的flash算法
stm32h743对应的flash算法摘要:1.STM32H743简介2.FLASH算法概述3.FLASH算法实现4.性能优化策略5.总结正文:一、STM32H743简介STM32H743是一款高性能、低功耗的微控制器,基于ARM Cortex-M7内核。
这款芯片具有丰富的外设和功能,广泛应用于各种嵌入式系统和工业控制领域。
在这篇文章中,我们将重点讨论STM32H743对应的FLASH算法。
二、FLASH算法概述FLASH算法是指针对FLASH存储器的编程和擦除操作所设计的一种算法。
在STM32H743中,FLASH算法负责对芯片内部的FLASH memory进行读写操作。
为了确保数据的安全性和可靠性,FLASH算法需要满足以下几个要求:1.高效性:保证在较短的时间内完成FLASH存储器的编程和擦除操作。
2.可靠性:确保FLASH存储器在多次编程和擦除循环过程中不会损坏。
3.安全性:防止非法访问和数据篡改。
三、FLASH算法实现1.编程操作在STM32H743中,编程操作主要包括以下几个步骤:(1)预充电:对FLASH页面进行预充电,以便后续编程操作。
(2)编程:根据预设的编程数据和地址,将数据写入FLASH页面。
(3)校验:编程完成后,对写入的数据进行校验,确保数据正确。
2.擦除操作擦除操作主要包括以下几个步骤:(1)预充电:对FLASH页面进行预充电,以便后续擦除操作。
(2)擦除:根据预设的擦除范围,将FLASH页面中的数据擦除。
(3)校验:擦除完成后,对页面进行校验,确保数据已被成功擦除。
四、性能优化策略1.优化编程和擦除算法,减少操作时间。
2.采用多级页缓存技术,提高数据传输速率。
3.优化预充电策略,降低功耗。
4.采用错误纠正码(ECC)技术,提高数据可靠性。
五、总结STM32H743是一款高性能的微控制器,其内部的FLASH算法在保证数据安全、可靠性的同时,还需具备较高的性能。
通过对FLASH算法的详细分析和优化,我们可以提高其在实际应用中的性能表现,满足各种复杂场景的需求。
STM32内部FLASH读写操作详解(附代码)
(2)擦除将要写的页STM32 的 FLASH 在编程的时候,也必须要求其写⼊地址的 FLASH 是被擦除了的(也就是其值必须是 0XFFFF),否则⽆法写⼊,在 FLASH_SR 寄存器的 PGERR 位将得到⼀个警告。
STM32 的闪存擦除分为两种:页擦除和整⽚擦除。
也就是其最⼩擦除单位为1页,尽管你只需往某页⾥写10个字节数据或者更少的数据,你也必须先擦除该页(2*1024个字节)。
我们这⾥使⽤按页擦除,固件库中按页擦除的函数为:左右滑动查看全部代码>>>/* 按页擦除 */FLASH_Status FLASH_ErasePage(uint32_t Page_Address);其返回值为枚举:左右滑动查看全部代码>>>typedef enum{ FLASH_BUSY = 1, /* 忙 */ FLASH_ERROR_PG, /* 编程错误 */FLASH_ERROR_WRP, /* 写保护错误 */ FLASH_COMPLETE, /* 操作完成 */FLASH_TIMEOUT /* 操作超时 */}FLASH_Status;(3)往上⼀步擦写成功的页写⼊数据STM32 闪存的编程每次必须写⼊16 位。
虽然固件库中有如下三个写操作的函数:左右滑动查看全部代码>>>FLASH_Status FLASH_ProgramWord(uint32_t Address, uint32_t Data);FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data);FLASH_StatusFLASH_ProgramOptionByteData(uint32_t Address, uint8_t Data);分别为按字(32bit)写⼊、按半字(16bit)写⼊、按字节(8bit)写⼊函数。
STM32教程系列之FLASH
一、实现的功能1.实现对STM32Fxxx的片内FLASH的擦除和烧写,并读出后进行检验。
2.用串口打印出检验FLASH内容是否正确的变量值。
二、实验操作及现象1.双击FLASH.eww打开工程文件,然后进行编译。
2.用Flash Loader将程序下载到ARM内,或者利用JLINK等仿真器进行仿真。
3.在程序运行前,用串口线将开发板的串口1和PC机的串口1连接,并打开“串口调试助手”,设置波特率为115200,将会看到每0.5秒显示一次“Flash Status=1”,则说明FLASH操作成功,否则说明FLASH操作失败。
三、片内FLASH学习大家可能会疑惑,既然我们可以利用工具将代码下载芯片内部,为什么还要讲解Flash编程呢?目的是让大家掌握后可以编写自己的BootLoader,例如用CAN总线接口来更新产品中的升级代码,不需要将产品拆卸即可完成。
另外一个很重要的问题就是我们要保护好自己编写的代码,否则被破_解后,就成别人的产品了。
1.解除Flash锁复位后,闪存擦写控制器模块是被保护的,不能写入FLASH_CR寄存器,通过写入两个关键字(KEY1,KEY2)到FLASH_KEYR寄存器打开闪存擦写控制器,才可以进行其他闪存操作。
其中KEY1为0x45670123,KEY2为0xCDEF89AB。
编程如下:FLASH->KEYR = FLASH_KEY1;FLASH->KEYR = FLASH_KEY2;2.页擦除在FLASH操作中,每次擦除只能擦除一页,不能一个字节一个字节的擦除,其实所谓的擦出就是将指定的页全部填写成0XFF,下面是页擦除的过程:-检查FLASH_SR寄存器的BSY位,以确认没有其他正在进行的闪存操作;-用FLASH_AR寄存器选择要擦除的页;-设置FLASH_CR寄存器的PER位为1;-设置FLASH_CR寄存器的STRT位为1;-等待BSY位变为0;-读出被擦除的页并做验证。
STM32实验报告
实验一:一个灯的闪烁一、实验要求1.熟悉使用STM32F103ZET6开发板2.利用C语言程序实现一个灯闪烁二、电路原理图图1-1 LED灯硬件连接图三、软件分析1.本实验用到以下3个库函数(省略了参数):RCC_DeInit();RCC_APB2PeriphClockCmd();GPIO_Init();2.配置输入的时钟:SystemInit()主要对RCC寄存器进行配置,GPIOA连接在APB2上,因此RCC_APB2PeriphClockCmd()函数需要使能APB2Periph_GPIOA3.声明GPIO结构:PF6~PF10口配置为输出=GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10;4.应用GPIO口:点亮LED1有五种方法①ODR寄存器法:GPIOA->ODR=0xffbf;②位设置/清除寄存器法:GPIOA->BRR|=0X001;③方法③只适用于GPIOx_BSRR寄存器④GPIO_WriteBit()函数法:GPIO_Write(0xffbf);⑤置位复位库函数法:GPIO_ResetBits(GPIOF,GPIO_Pin_8);5.主函数程序:int main(void){RCC_Configuration(); /* 配置系统时钟*/GPIO_Configuration(); /* 配置GPIO IO口初始化*/ for(;;){GPIOF->ODR = 0xfeff; /* PF8=0 --> 点亮D3 */Delay(600000);GPIOF->ODR = 0xffff; /* PF8=1 --> 熄灭D3 */Delay(600000);}}四、实验现象下载程序后开发板上的LED1灯闪烁五、总结通过对本实验可以发现,和51等8位单片机相比,STM32对I/O端口的操作变得复杂了许多。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
FLASH_BUSY = 1,//忙 FLASH_ERROR_PG,//编程错误 FLASH_ERROR_WRP,//写保护错误 FLASH_COMPLETE,//操作完成 FLASH_TIMEOUT//操作超时 }FLASH_Status;
普中STM32开发板带您进入ARM世界
(5)等待操作完成 FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout); (6)读取 FLASH 指定地址数据 vu16 STM32_FLASH_ReadHalfWord(u32 faddr) {
②信息块。该部分分为 2 个小部分,其中启动程序代码,是用来存储 ST 自带的启动程序,用于串口下载代码,当 BOOT0 接 V3.3, BOOT1 接 GND 的时候,运行的就是这部分代码。用户选择字节,则 一般用于配置写保护、读部分用于控制闪存读写等,是整个闪存模 块的控制机构。
return *(vu16*)faddr; }
普中STM32开发板带您进入ARM世界
3.硬件电路
本实验使用到硬件资源如下: (1)D1指示灯 (2)K_UP和K_DOWN按键 (3)串口1 (4)TFTLCD模块 (5)STM32F1内部FLASH
D1指示灯用来提示系统运行状态,K_UP和K_DOWN按键用来控制内部 FLASH数据的读写,TFTLCD模块和串口1用来显示读写的数据。
普中STM32开发板带您进入ARM世界
STM32内部Flash实验
Байду номын сангаас
普中STM32开发板带您进入ARM世界
本讲主要内容
1.STM32F1内部FLASH介绍 2.内部FLASH操作步骤 3.硬件电路 4.编写STM32F1内部FLASH控制程序
普中STM32开发板带您进入ARM世界
1.STM32F1内部FLASH介绍
普中STM32开发板带您进入ARM世界
2.内部FLASH操作步骤
具体步骤如下:(闪存Flash相关库函数在stm32f10x_flash.c和 stm32f10x_flash.h文件中) (1)解锁和锁定 void FLASH_Unlock(void); void FLASH_Lock(void); (2)写操作 FLASH_Status FLASH_ProgramWord(uint32_t Address, uint32_t
不同型号的 STM32,其 FLASH 容量也有所不同,最小的只有 16K 字 节,最大的则达到了 1024K 字节。我们STM32F1开发板使用的芯片是 STM32F103ZET6,其FLASH 容量为 512K 字节,属于大容量芯片。
普中STM32开发板带您进入ARM世界
大容量产品的Flash模块组织结构图
普中STM32开发板带您进入ARM世界
①主存储器。该部分用来存放代码和数据常数(如 const 类型的数据) 。对于大容量产品,其被划分为 256 页,每页 2K 字节。注意,小 容量和中容量产品则每页只有 1K 字节。从上图可以看出主存储器的 起始地址就是 0X08000000, BOOT0、BOOT1 都接 GND 的时候,就是 从 0X08000000开始运行代码的。
(3)擦除操作 FLASH_Status FLASH_ErasePage(uint32_t Page_Address); FLASH_Status FLASH_EraseAllPages(void); FLASH_Status FLASH_EraseOptionBytes(void);
普中STM32开发板带您进入ARM世界
Data); FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t
Data); FLASH_Status FLASH_ProgramOptionByteData(uint32_t Address,
uint8_t Data);
普中STM32开发板带您进入ARM世界
普中STM32开发板带您进入ARM世界
4.编写STM32F1内部FLASH控制程序
本章所要实现的功能是:使用K__UP和K_DOWN键控制内部FLASH的写入 和读取,并将数据显示在TFTLCD和串口助手上,同时控制D1指示灯不断 闪烁,提示系统正常运行。本章我们使用的是STM32F1的内部FLASH,程 序框架如下: (1)编写FLASH读数据函数 (2)编写FLASH写数据函数 (3)编写主函数