STM32读写内部FLASH的函数程序

合集下载

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字节的内置闪存存储器,⽤于存放程序和数据。

STM32实现内部Flash的读写(HAL库版)

STM32实现内部Flash的读写(HAL库版)

STM32实现内部Flash的读写(HAL库版) Flash 中⽂名字叫闪存,是⼀种长寿命的⾮易失性(断电数据不丢失)的存储器。

可以对称为块的存储器单元块进⾏擦写和再编程,在进⾏写⼊操作之前必须先执⾏擦除。

⼀个Nand Flash由多个块(Block)组成,每个块⾥⾯⼜包含很多页(page)。

每个页对应⼀个空闲区域/冗余区域(spare area),这个区域不是⽤来存储数据的,⽤于放置数据的校验值检测和纠错的。

块,是Nand Flash的擦除操作的基本/最⼩单位。

页,是Nand Flash的写⼊操作的基本/最⼩的单位。

⾸先简要写⼀下FLASH的读写流程: 对FLASH写⼊数据 解锁FLASH 擦除FLASH 写⼊数据到FLASH 锁住FLASH FLASH读取数据(直接读取相应的FLASH地址即可) 操作MCU⾥的Flash,还有⼏个注意事项: 1、往Flash写⼊数据的时候,要先对要写⼊的页进⾏擦除,如果要写的页⾥有数据,要先读出来在缓存区,再把页擦除,再写⼊数据;在擦除页之后,只要这次你写的数据⼤⼩不够⼀页,可以连续写⼊。

2、要计算好程序的内存,因为你的程序也是保存在MCU的Flash⾥的,如果你操作到保存着程序的内存,程序就会死掉,⾄于程序内存怎么看,你可以⽣成bin⽂件,bin⽂件的⼤⼩就是你程序所占内存的⼤⼩了,⽣成bin⽂件可以参考博客:;程序内存基本都是从Flash内存⼀开始存起的,这⾥以STM32Fo72c8t6举例,如下图。

看图可以看出,这个芯⽚的Flash内存范围是0x0800 0000 ~ 0x0802 0000 ,假设我要烧录进去的bin⽂件为10K,那我们操作Flash的时候,地址就要从0x0800 0000 + (0x400*11) 开始,避开程序的存储位置,Flash地址偏移1位就是1个字节。

3、要注意MCU⼀页的⼤⼩,⼀些MCU⼀页是1KB,⼀些MCU⼀页是2KB 下⾯举个例⼦写⼊数据0x0001到Flash中uint16_t my_add = 0x0001; uint32_t Robot_Num_Flash_Add = 0x08005000;FLASH_EraseInitTypeDef My_Flash; //声明 FLASH_EraseInitTypeDef 结构体为 My_FlashHAL_FLASH_Unlock();//解锁FlashMy_Flash.TypeErase = FLASH_TYPEERASE_PAGES; //标明Flash执⾏页⾯只做擦除操作My_Flash.PageAddress = Robot_Num_Flash_Add; //声明要擦除的地址My_Flash.NbPages = 1; //说明要擦除的页数,此参数必须是Min_Data = 1和Max_Data =(最⼤页数-初始页的值)之间的值uint32_t PageError = 0; //设置PageError,如果出现错误这个变量会被设置为出错的FLASH地址HAL_FLASHEx_Erase(&My_Flash, &PageError); //调⽤擦除函数擦除uint16_t Write_Flash_Data = my_add; //对Flash进⾏烧写,FLASH_TYPEPROGRAM_HALFWORD 声明操作的Flash地址的16位的,此外还有32位跟64位的操作,⾃⾏翻查HAL库的定义即可 HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, Robot_Num_Flash_Add, Write_Flash_Data);HAL_FLASH_Lock(); //锁住Flash 写完之后,接着就到读了,Flash写有次数限制,写的次数在1W次还是10W次(忘了)就不可写⼊了,⽽读是没有次数限制的,读多少次都可以,下⾯就把写⼊到Flash⾥的数据0x0001读出来uint32_t Robot_Num_Flash_Add = 0x08005000; ID_Num = *(__IO uint16_t*)( Robot_Num_Flash_Add ); //*(__IO uint16_t *)是读取该地址的参数值,其值为16位数据,⼀次读取两个字节,*(__IO uint32_t *)就⼀次读4个字节 printf("ID_num:0x%x\r\n", ID_Num); 经过上⾯的程序就可以实现 STM32 中 Flash 数据的读写了,具体怎么读写,每个案⼦不同,各位就可以根据需求去修改,只要注意好注意事项即可,代码已经实测可⽤。

关于STM32的flash读写数据和HardFault

关于STM32的flash读写数据和HardFault

关于STM32的flash读写数据和HardFault今天调试程序的时候需要把掉电前的数据存储到flash中之后等待下次初始化的时候把数据读进来。

刚刚开始的时候去找了一些stm32的flash的操作,真的是废话连篇的真正能用到的没几句话,这里我把自己调试好的flash读写数据的子函数跟大家分享一下。

void FLASH_WriteByte(u32 addr ,u16 flashdata1){FLASH_Status FLASHstatus = FLASH_COMPLETE;FLASH_Unlock();//解锁FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);FLASHstatus=FLASH_ErasePage(addr);//擦除整页FLASHstatus=FLASH_ProgramHalfWord(addr, flashdata1);//写入数据FLASH_Lock();//锁定}这个子函数就是将数据flashdata1写到地址addr中去。

数据的长度是可变的。

当需要读入数据的时候可以直接访问地址,如:rdata=*(u16 *)0x08014000; //读flash中默认数据0x08014000是存储的地址。

这样大家应该很清楚了吧。

flash读写数据还是比较简单的,这里希望能帮到大家。

但是在写入数据的时候,又遇到了另一个问题,就是程序运行的时候进入到这个HardFault_Handler函数中死循环了,不知道大家有没有遇到过这个问题,后来我查了一些资料,发现可能是存储器的分配有问题。

然后把地址改到更大的地方,又试了试,发现已经可以了。

建议大家这样试一试。

下面是我找的关于防止误擦除有用程序代码的方法方法一:首先要计算程序代码有多少,把FLASH存取地址设置在程序代码以外的地方,这样就不会破坏用户程序。

stm32Flash读写

stm32Flash读写

使用芯片是STM32F103RD,时钟8M,配置为72M,库函数3.5。

如果需要往串口测试数据,需要配置串口。

下面的程序都通过MDK编译,测试。

注意:FLASH的地址不能为奇数,否则会产生异常。

在这里数据类型:u_long为unsigned int;u_char为unsigned char,u_short为unsigned short.#define FLASH_PAGE_SIZE ((u_short)0x800) /*page size is 2048 byte*//** \stm32f106RD6 flash is 384k, addr is 0x0800_0000 to 0x0805_ffff* make the last page to save user data*/#define BANK_WRITE_START_ADDR (u_long)(0x08000000 + 382*1024)#define BANK_WRITE_END_ADDR (u_long)(0x08000000 + 384*1024)/** \ brief Read a half word from the specify FLASH addr** \ param dwiAddr The specify address in the flash between* BANK_WRITE_END_ADDR to BANK_WRITE_START_ADDR** \ return data read from the specify adddress.*/int eeReadHalfWord(u_long dwiAddr){u_short data;u_short *ptrFlash;ptrFlash = (u_short*)(dwiAddr);data = *ptrFlash;return (int)(u_int)data;}/** \ brief Read a word from the specify FLASH addr** \ param dwiAddr The specify address in the flash between* BANK_WRITE_END_ADDR to BANK_WRITE_START_ADDR* \ return data read from the specify addr.*/int eeReadWord(u_long dwiAddr){u_int data;u_int *ptrFlash;ptrFlash = (u_int*)(dwiAddr);data = *ptrFlash;return (int)(u_int)data;}/** \ brief check a block flash is needed to erase.** \ param dwiAddr The specify address in the flash between* BANK_WRITE_END_ADDR to BANK_WRITE_START_ADDR * \ param wiSize** \ return* -2 the block flash need to erase,if we write data to the flash,* 0 can write data to the block flash.*/int eeCheckBlockFlash(u_long dwiAddr, u_short wiSize){u_int nResult;u_short i = 0;for (i = 0; i < wiSize; i++){nResult = eeReadWord(dwiAddr);if (nResult != 0xffffffff){return -2;/*Flag This block in the flash is needed to erase.*/ }}return 0;}* \ brief write a half word to the specify piaddr** \ param dwiAddr The specify address in the flash between* BANK_WRITE_END_ADDR to BANK_WRITE_START_ADDR* \ param wiData The data is to save the specify addr.** \ return -1,addr error,* -2,addr is odd num.* -3,data save the specify addr is error.* 0 success write data to the specify addr.*/int eeWriteHalfWord(u_long dwAddr, u_short wiData){int nResult;/*Addr is not in the page.*/if((dwAddr>BANK_WRITE_END_ADDR)&&(dwAddr<BANK_WRITE_START_ADDR)) {return -1;}/*addr is a odd num*/if (dwAddr % 2 != 0){return -2;}FLASH_Unlock( );FLASH_ErasePage(dwAddr);FLASH_ProgramHalfWord(dwAddr, wiData);FLASH_Lock( );/*Check the save data is right or error*/nResult = eeReadHalfWord(dwAddr);if ((0xffff & nResult) != wiData){return -3;}return 0;}/** \ brief write a word to the specify piaddr** \ param dwiAddr The specify address in the flash between* BANK_WRITE_END_ADDR to BANK_WRITE_START_ADDR* \ param dwiData The data save to the specify addr.** \ return -1,addr error, -2 addr is odd number* -3,data save to the specify addr is error.* 0 success write data to the specify addr.*/int eeWriteWord(u_long dwiAddr, u_long dwiData){int nResult;if ((dwiAddr > BANK_WRITE_END_ADDR) && (dwiAddr<BANK_WRITE_START_ADDR)){return -1;}if (dwiAddr % 2 != 0){return -2;}FLASH_Unlock( );FLASH_ErasePage((u_long)dwiAddr);FLASH_ProgramWord((u_long)dwiAddr, dwiData);nResult = eeReadWord(dwiAddr);FLASH_Lock( );if (nResult != dwiData){return -3;}return 0;}/** \ brief write muti half data from the flash block* \ param dwiAddr save the data in the flash,The specify address in the flash between,* BANK_WRITE_END_ADDR to BANK_WRITE_START_ADDR.* \ param pciSrc pointer to the data need to save.** \ return -1 addr error, -2, addr is odd num, 0 write success.*/int eeWriteMultiHalfWord(u_long dwiAddr, const u_short *pciSrc, u_short wiDataLen){u_short i = 0;u_short *pdest = (u_short *)dwiAddr;int nResult;if ((dwiAddr > BANK_WRITE_END_ADDR) && (dwiAddr < BANK_WRITE_START_ADDR)){return -1;}if (dwiAddr % 2 != 0){return -2;}nResult = eeCheckBlockFlash(dwiAddr, wiDataLen);FLASH_Unlock( );if (nResult == -2){FLASH_ErasePage((u_long)pdest);}for (i = 0; i < wiDataLen; i++){FLASH_ProgramHalfWord((u_long)pdest, *pciSrc);pdest++;pciSrc++;}FLASH_Lock( );return 0;}/** \ brief write multi word data to the flash block** \ param dwiAddr save the data in the flash,The specify address in the flash between,* BANK_WRITE_END_ADDR to BANK_WRITE_START_ADDR.* \ param pciSrc pointer to the data need to save.* \ param wiDataLen read number of data.** \ return -1 addr error,* -2 addr num is odd.* 0 write success.*/int eeWriteMultiWord(u_long dwiAddr, const u_long *pciSrc, u_short wiDataLen){u_short i = 0;u_long *pDestAddr = (u_long*)dwiAddr;int nResult;/*The addr is over the specify page.*/if ((dwiAddr > BANK_WRITE_END_ADDR) && (dwiAddr< BANK_WRITE_START_ADDR)){return -1;}/*The addr(dwiAddr) is a odd num, write data here will be made a fault.*/if (dwiAddr % 2 != 0){return -2;}/*Check block Flash is needed to erase.*/nResult = eeCheckBlockFlash(dwiAddr, wiDataLen);FLASH_Unlock( );if (nResult == -2){FLASH_ErasePage((u_long)pDestAddr);}for (i = 0; i < wiDataLen; i++){FLASH_ProgramWord((u_long)pDestAddr, *pciSrc);pDestAddr++;pciSrc++;}FLASH_Lock( );return 0;}/** \ brief read multi half word data from the flash block** \ param dwiSrcAddr The specify address in the flash between* BANK_WRITE_END_ADDR to BANK_WRITE_START_ADDR* \ param piDestAddr Apointer to the addr that save the data from the flash.* \ param wiDataLen read number of data.** \ return -1 addr error,* -2 addr is a odd number* 0 read success.*/int eeReadMultiHalfWord(u_short *piDestAddr, u_long dwiSrcAddr, u_short wiDataLen) {u_short i = 0;u_short *pSrcAddr = (u_short *)dwiSrcAddr;/*The addr is over the specify page.*/if ((dwiSrcAddr > BANK_WRITE_END_ADDR) && (dwiSrcAddr < BANK_WRITE_START_ADDR)){return -1;}/*The addr(dwiAddr) is a odd num, write data here will be made a fault.*/if( dwiSrcAddr % 2 != 0){return -2;}for (i = 0; i < wiDataLen; i++){*piDestAddr = (u_short)(*pSrcAddr);piDestAddr++;pSrcAddr++;}return 0;}/** \ brief read multi word data from the flash block** \ param dwiSrcAddr The specify address in the flash between* BANK_WRITE_END_ADDR to BANK_WRITE_START_ADDR* \ param piDestAddr A pointer to the addr that save the data from the flash.* \ param wiDataLen read number of data.** \ return -1 addr error,* -2 addr is a odd number* 0 read success.*/int eeReadMultiWord(u_long *piDestAddr, u_long dwiSrcAddr, u_short wiDataLen){u_short i = 0;u_long *pSrcAddr = (u_long*)dwiSrcAddr;/*The addr is over the specify page.*/if ((dwiSrcAddr > BANK_WRITE_END_ADDR) && (dwiSrcAddr < BANK_WRITE_START_ADDR)){return -1;}/*The addr(dwiAddr) is a odd num, write data here will be made a fault.*/if (dwiSrcAddr % 2 != 0){return -2;}for (i = 0; i < wiDataLen; i++){*piDestAddr = *pSrcAddr;piDestAddr++;pSrcAddr++;}return 0;}。

stm32f4 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芯片内部的FLASH存储器,主要用于存储我们代码。

如果内部FLASH存储完我们的代码还有剩余的空间,那么这些剩余的空间我们就可以利用起来,存储一些需要掉电保存的数据。

本文以STM32103ZET为例。

STM32103ZET属于大容量产品,其闪存模块组织如下:其主存储器大小为512KB分为256页,每页大小都为2KB我们的程序般默认烧写到第0页的起始地址(0x08000000)处。

当BOOT引脚和BOOT引脚都接GND寸,就是从这个地址开始运行代码的。

这个地址在keil中可以看到:F 面对STM32内部FLASH 进行简单的读写测试:内部FLASH 读写测试 流程图如下:本流程图省略异常情况,只考虑成功的情况:f-Q Options for Target 'FLASH'一丄Utvice Til i«l I Output ] Li itinc | Ustr | C/C++ | AsmLinker Debue Vtiiitws\tSTHicroetedonici SR32F103ZEOpef^g syseiTi : |Sysem \^ewer Rle.{MHi): Bll-Cod* GeniFon —ARM Compter: | Use default cwnpiter veraion 5刁厂 Lse Cjoss-^ottile OrtimiiatorIv Lse Micro LIBotCancelCeCa-olts Help假如我们要下载的程序大小为4.05KB , 则第0、1、2页用于保存我们的程序,我们需要掉电保存的数据只能保存在第 3~第255页这一部分空间内。

我们最终要下载的程序大小可在工程对应的 .map 文件中看到。

.map 文件可以双击工程的Target 的名字快速打开,如:hrlphdrt Tool ; SVM 応 inJ 艸 hti 単 ,-■k ,A 弟=*七住」Mitw J 咖3口知,樹;卜( J... —. ■丹 Ft E4R vl«* PiQjtit “Ml Dtbug•ffli11 htBj£画 IF b.农-I r sj fLASj- In 討mi■. 1.7 viieiiii '.L二KP;L 叭1祠£ -L 二El 仍恤■走r二匚 top.gt £Jt±』CMS5三Q StriPaiph thr.ci二uc4114出, + e 4H ULiJry T'^CiJbd Mt*LMb|HELL ・md " D*fca ] ■W Egf icrtBli 畤TCT P Hmucfi>n 3 Hlih —b kp C b4i-i3 Jhdn_c.driR.Hbloral HD Size Ifodt + ・□ palFl*Total R>I 51■疋c £RM Eta - Zr TZatJ) Totdg flW S 上电 jt 屁It + 觀尿H * 也 G SU TL Use CustziEFife示例代码:本例的关键代码如下(以读写第255页为例):/******************************************************************************************************** -------------------------------------- STM32 Demo ------------------------工程说明:STM32内部FLASH实验作者:ZhengNian博客: zhengnianli.github.io公众号:嵌入式大杂烩********************************************************************************************************/#defi ne MAIN_CONFIG#i nclude "con fig.h"/* STM32F103ZET6有256页,每一页的大小都为2KB */#defi ne ADDR_FLASH _P AGE_255 ((ui nt32_t)0x0807F800) /* Page255 2KB *//* FLASH读写测试结果*/#defi ne #defi ne #defi ne/* Flash 读写测试buf */ #defi ne BufferSize 6ui nt16_t usFlashWriteBuf[BufferSize]= {0x0101,0x0202,0x0303,0x0404,0x0505,0x0606}; ui nt16_t usFlashReadBuf[BufferSize] = {0};/*供本文件调用的函数声明*/ static int FlashReadWriteTest(void);*********************************** ** 函数:main参数:void 返回:无 说明:主函数********************************************************************* ***********************************/ int main(v oid) {/*上电初始化*/ Sysl nit();/*内部Flash 读写测试*/if (TEST_SUCCESS == FlashReadWriteTest()) prin tf("Flash test success!' n"); } else {prin tf("Flash test failed!\n"); } while (1) {} }*************************************函数:FlashReadWriteTest ,内部Flash 读写测试函数 ** 参数:void**返回:TEST_ERROR :错误(擦除、写入错误) TEST_SUCCESS:成功TEST_FAILED :失败 **说明:无********************************************************************************************************/ static int FlashReadWriteTest(void) {TEST_ERROR -1 TEST_SUCCESS 0 TEST_FAILED 1 /*/*错误(擦除、写入错误)*/ /*成功*/失败*/uin t32_t ucStartAddr;/*解锁*/FLASH_U nIockO;/*擦除操作*/ ucStartAddr = ADDR_FLASH _P AGE_255;if (FLASH_CO MP LETE != FLAsH_Erase Page(ucStartAddr)) { prin tf("Erase Error!\n"); return TEST_ERROR;}elseucStartAddr = ADDR_FLASH _P AGE_255;printf("擦除成功,此时FLASH中值为:\n");for (i nt i = 0; i < BufferSize; i++){usFlashReadBuf[i] = *(ui nt32_t*)ucStartAddr;prin tf("ucFlashReadBuf[%d] = 0x%.4x\n", i, usFlashReadBuf[i]); ucStartAddr += 2;}}/*写入操作*/ucStartAddr = ADDR_FLASH _P AGE_255;printf("\n往FLASH中写入的数据为:\n");for (i nt i = 0; i < BufferSize; i++){if (FLASH_CO MP LETE != FLASH _P rogramHalfWord(ucStartAddr, usFlashWriteBuf[i])) {prin tf("Write Error!\n");return TEST_ERROR;} "prin tf("ucFlashWriteBuf[%d] = 0x%.4x\n", i, usFlashWriteBuf[i]); ucStartAddr += 2;} /*上锁*/ FLASH_Lock();/*读取操作*/ucStartAddr = ADDR_FLASH _P AGE_255;printf("\n 从FLASH 中读出的数据为:\n"); for (i nt i = 0; i < BufferSize; i++) {usFlashReadBuf[i] = *(__10 uin t16_t*)ucStartAddr;prin tf("ucFlashReadBuf[%d] = 0x%.4x\n", i, usFlashReadBuf[i]); ucStartAddr += 2; }/*读出的数据与写入的数据做比较*/ for (i nt i = 0; i < BufferSize; i++) {if (usFlashReadBuf[i] != usFlashWriteBuf[i]) {return TEST_FAILED; } }return TEST_SUCCESS; }/******************************************************************** *************************************** End Of File********************************************************************* ***********************************/(1)进行解锁操作STM32的闪存编程是由内嵌的闪存编程/擦除控制器(FPEC )管理,这个模块包含的寄存器如下:STM32复位后,FPEC 模块是被保护的, 不能写入FLASH_CR 寄存器;通 过写入特定的序列到FLASH_KEYF 寄存器可以打开FPEC 模块(即写入KEY1和KEY2 ,只有在写保护被解除后,我们才能操作相关寄存器。

读写STM32内部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。

stm32f103c8 flash读写例程

stm32f103c8 flash读写例程

以下是一个使用STM32F103C8微控制器进行Flash读写的例程:```c#include "stm32f10x.h"#include "stm32f10x_flash.h"void Flash_Init(void){FLASH_DeInit(); // 关闭所有已启用的闪存接口FLASH_EraseSector(FLASH_Addr_0); // 擦除第一个扇区FLASH_Write_Enable(); // 使能写操作}uint32_t Flash_Read(uint32_t ReadAddr, uint8_t *pBuffer){uint32_t ReadData;if (ReadAddr >= FLASH_Addr_Start_Page && ReadAddr < FLASH_Addr_End_Page) {FLASH_Lock(); // 锁定闪存,防止其他操作干扰FLASH_Unlock(); // 解锁闪存FLASH_EraseSector(ReadAddr); // 擦除指定地址的扇区FLASH_Write_Enable(); // 使能写操作FLASH_ProgramWord(ReadAddr, *pBuffer); // 写入数据到指定地址FLASH_Lock(); // 再次锁定闪存FLASH_Unlock(); // 解锁闪存FLASH_Read(ReadAddr, &ReadData); // 从指定地址读取数据FLASH_Lock(); // 再次锁定闪存FLASH_Unlock(); // 解锁闪存}else{ReadData = 0;}return ReadData;}uint32_t Flash_Write(uint32_t WriteAddr, uint8_t *pBuffer){uint32_t WriteData;if (WriteAddr >= FLASH_Addr_Start_Page && WriteAddr < FLASH_Addr_End_Page) {FLASH_Lock(); // 锁定闪存,防止其他操作干扰FLASH_Unlock(); // 解锁闪存FLASH_EraseSector(WriteAddr); // 擦除指定地址的扇区FLASH_Write_Enable(); // 使能写操作FLASH_ProgramWord(WriteAddr, *pBuffer); // 写入数据到指定地址FLASH_Lock(); // 再次锁定闪存FLASH_Unlock(); // 解锁闪存FLASH_Read(WriteAddr, &WriteData); // 从指定地址读取数据FLASH_Lock(); // 再次锁定闪存FLASH_Unlock(); // 解锁闪存}else{WriteData = 0;}return WriteData;}```这个例程包含了一个初始化函数`Flash_Init()`,用于初始化Flash设备。

关于STM32的FLASH操作

关于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内部flash读写代码

读写STM32内部flash读写代码2019.01 -------------------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。

stm32f单片机内部flash模拟EEPROM操作源码

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。

stm32 flash 读取数据 初始化函数

stm32 flash 读取数据 初始化函数

stm32 flash 读取数据初始化函数STM32是一款32位ARM Cortex-M系列的微控制器,具有强大的性能和丰富的外设。

在STM32中,Flash存储器是一种用于存储程序代码或配置数据的非易失性存储器。

在本文中,我们将讨论如何读取Flash存储器中的数据,并分享一些与初始化函数相关的内容。

一、Flash存储器读取数据为了读取Flash存储器中的数据,首先需要了解存储器的基本结构。

在STM32中,Flash存储器被分为多个扇区(Sector)。

每个扇区的大小通常为2KB或4KB,并通过一个Flash地址来访问。

读取Flash存储器的一种常见方法是使用指针操作。

首先,您需要定义一个指向Flash存储器地址的指针变量。

然后,您可以使用该指针访问存储器中的数据。

以下是一个简单的示例代码:c#include "stm32f4xx.h"#define FLASH_ADDRESS 0x08008000 Flash存储器的起始地址uint32_t *flash_data = (uint32_t *)FLASH_ADDRESS; 定义一个指向Flash 存储器的指针变量int main(void){uint32_t data = *flash_data; 读取存储器中的数据在这里可以进行后续操作...while (1){主循环}}在上述示例中,我们首先定义了一个Flash存储器的起始地址`FLASH_ADDRESS`,然后将其转换为指向32位数据类型的指针变量`flash_data`。

接下来,我们通过间接引用指针`flash_data`来读取存储器中的数据,并将其存储在`data`变量中。

您可以在后续的代码中使用`data`变量进行进一步的操作。

需要注意的是,读取Flash存储器中的数据时,需要确保访问的地址处于有效范围内,并且使用正确的数据类型进行读取。

此外,读取Flash存储器中的数据与写入数据不同,不需要先擦除相应的扇区。

STM32-FLASH

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读写例程

stm32 flash读写例程

stm32 flash读写例程摘要:1.STM32 Flash存储器概述2.STM32 Flash读写操作步骤3.STM32 Flash读写实例4.注意事项正文:一、STM32 Flash存储器概述STM32 Flash存储器分为两个区域:系统区域和用户区域。

系统区域存储固件和启动代码,用户区域用于存储用户数据。

STM32提供了丰富的库函数和HAL(硬件层)驱动程序,方便开发者实现对Flash存储器的读写操作。

二、STM32 Flash读写操作步骤1.初始化:对Flash模块进行初始化,包括时钟、GPIO等。

2.擦除:在进行写入操作前,需要对目标区域进行擦除。

擦除方式以页为单位。

3.写入:将数据写入Flash存储器。

注意写入地址为奇数时可能会出错。

4.读取:从Flash存储器中读取数据。

三、STM32 Flash读写实例以下是一个简单的STM32 Flash读写实例:1.定义Flash 写入数据函数:```cvoid FlashWrite(uint32_t add, uint16_t dat) {// 打开Flash控制时钟RCCHSICMD(ENABLE);// 设置Flash写入地址FLASH_WriteAddress = add;// 写入16位数据FLASH_DataWrite(dat);// 等待Flash写入完成while (FLASH_BusyStatus != 0);// 关闭Flash控制时钟RCCHSICMD(DISABLE);}```2.定义Flash 读取数据函数:```cuint16_t FlashRead(uint32_t add){// 打开Flash控制时钟RCCHSICMD(ENABLE);// 设置Flash读取地址FLASH_ReadAddress = add;// 读取16位数据uint16_t data = FLASH_DataRead();// 关闭Flash控制时钟RCCHSICMD(DISABLE);return data;}```四、注意事项1.Flash 读写操作时,需注意地址和数据长度。

STM32 对内部FLASH读写接口函数

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

STM32FLASH操作

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获取堆栈顶的地址。

不同的复位类型还有对其他寄存的不同复位方式,这就完成了复位。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Address=Address+4;
}
//检验数据是否出错
Address = StartAddr;
i=0;
while((Address < EndAddr) && (MemoryProgramStatus != 0))
{
if((*(vu32*) Address) != p_data[i++])
int MemoryProgramStatus=1;
u32 Address = 0x0;
int i=0;
Address = StartAddr;
while((Address < EndAddr) && (MemoryProgramStatus != 0))
{
p_data[i++]=(*(vu32*) Address);
{ MemoryProgramStatus = 0;
return 1;
}
Address += 4;
}
return 0;
}
int flash_read(u32 StartAddr,u32 *p_data,u32 size)
{
u32 EndAddr=StartAddr+size*4;
}
//开始写数据
Address = StartAddr;
i=0;
while((Address<EndAddr)&&(FLASHStatus==FLASH_COMPLETE))
{ FLASHStatus=FLASH_ProgramWord(Address,p_data[i++]);
Address += 4;
}
return 0;
}
//注:需在stm32f10x_conf.h中先定义#define _FLASH_PROG
#include "stm32f10x_flash.h"
//根据芯片的类型,决定每个page的大小。1k or 2k
#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)
#endif
u8 flash_write(u32 StartAddr,u32 *p_data,u32 size)
//擦页
FLASHStatus=FLASH_COMPLETE;
for(EraseCounter=0;(EraseCounter<NbrOfPage)&&(FLASHStatus==FLASH_COMPLETE);EraseCounter++)
{
FLASHStatus=FLASH_ErasePage(StartAddr+(PageSize*EraseCounter));
/*******************************************************************************
flash的写函数:
ቤተ መጻሕፍቲ ባይዱ输入:
u32 StartAddr flash起始地址
u32 *p_data 待写入数据指针,比如一个数组的名字。此数组必须是32位的数据。
u32 size 写入数据的数量,比如数组的长度。
输出:
0:正确执行
非0:出错
注意:输入数据一定是u32 的指针,即数据一定是按照4字节对齐写入的。
所以:size也是u32的个数(字节数的4分之一)
直接改文件扩展名即可使用。
*******************************************************************************/
//为一是通过
FLASH_Unlock(); //解锁函数
NbrOfPage=((EndAddr-StartAddr)/FLASH_PAGE_SIZE)+1; //有多少个页被擦除
//清除所有已有标志
FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
{
volatile FLASH_Status FLASHStatus;
u32 EndAddr=StartAddr+size*4;
vu32 NbrOfPage = 0;
u32 EraseCounter = 0x0, Address = 0x0;
int i;
int MemoryProgramStatus=1;
相关文档
最新文档