c语言flash里能存文件吗,STM32内部FLASH打包读写
最近做到的项目在运行需要把一组uint8_t(unsigned char)的数据进行掉电储存,想到单片机STM32f030f4p6内部flash可以直接由程序操作,写了以下代码用于uint8_t数据打包保存和读取。
1、程序清单 与 测试结果
本程序包含5个文件,分别是:
1、Flash.c:内部flash读取储存相关函数
2、Flash.h:flash头文件
3、USART1.c:STM32F030F4P6的串口驱动,串口仅用于打印数据观察。
4、USART1.h:串口头文件
5、main.c:防止程序主入口
1、Flash.c
View Code
2、Flash.h
View Code
3、USART1.c
View Code
4、USART1.h
View Code
5、main.c
View Code
测试结果:
第54-199省略..
2、程序详解
2.1、内存结构:
STM32F0xx的flash结构如下:最多具有64页,每页1KByte大小。
我使用的STM32F030F4P6 flash区域有16K,所以实际上只有0-15页,本程序中把需要保存的数据数据存放在最后一页(第15页)中。
2.2、定义数据包结构
为了保证储存和读出flash的数据是正确的,本程序将写入flash数据分为3个区域
报头区:写入数据的时候,将第15页的第1、2字节写入0xaa55,在读出的时候如果此位置不是0xaa55,则表示这段数据数据无效,不是由自己存入的数据或者程序出现了异常;
长度:写入数据的时候,第15页的第3、4字节写入有效数据的长度,读出这个字段,就知道上次自己一共存入了多少数据;
数据段:从第15页的第5字节开始,全部字节(1020byte)用于储存uint8_t类型的数据;
2.3、写操作
写操作有如下步骤:
保护:由于我们只有1Kbyte空间,出去4个字节的报头和长度,实际只能存储1020个u8类型,写太多返回失败。
解flash锁
页擦除
写入数据包
上锁
/*******************************************************************************
* Function Name : Flash_eeprom_WriteWithPacked
* Description : Write a group of datas to flash.
* Input : buff:pointer of first data, length: write length
* Output :
* Return : true/false
*******************************************************************************/
bool writeMessageToFlash( uint8_t *buff , uint16_t length)
{
uint16_t temp;
int i;
/*Protection*/
if( (length+4) > STM32F0xx_PAGE_SIZE )
{
return false;
}
FLASH_Unlock( );
/*Clear all flags*/
FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPERR );
/*Erase first . Do not rember.*/
if(FLASH_COMPLETE != FLASH_ErasePage(STM32F0xx_FLASH_PAGE15_STARTADDR))//°üº¬Á˵ȴýbusy
{
return false;
}
/*Write head*/
FLASH_ProgramHalfWord( STM32F0xx_FLASH_PAGE15_STARTADDR, EEPPROM_PACKAGEHEAD );
/*Write length*/
FLASH_ProgramHalfWord( STM32F0xx_FLASH_PAGE15_STARTADDR+2 , length );
/*Write datas*/
for(i=0 ;i
{
temp = buff[2*i]|(uint16_t)buff[2*i+1]<<8;
FLASH_ProgramHalfWord( STM32F0xx_FLASH_PAGE15_STARTADDR+4+2*i , temp);
}
if( isItOddNumber(length) )//Write one more if length is odd number.
{
temp = (uint16_t)buff[length-1];
FLASH_ProgramHalfWord( STM32F0xx_FLASH_PAGE15_STARTADDR+4+(length-1) , temp);
}
/*Read out and check*/
for(i=0 ;i
{
if( *(uint8_t*)(STM32F0xx_FLASH_PAGE15_STARTADDR+4+i) != buff[i] )
{
FLASH_Lock();
return false;
}
}
FLASH_Lock();
return true;
}
2.3.1、解锁操作:
用户手册描述如下:
在(芯片)重置过后,为了防止多余的擦写操作flash会被保护。除了OBL_LAUNCH位用于重载option bit,FLASH_CR寄存器的其他部分都不可以访问。
需要把以下两个解锁序列写入FLASH_KEY寄存器,才能访问FLASH_CR:
0x45670123
0xCDEF89AB
检索官方库定位FLASH_Unlock()这个函数,它的底层实现与文档描述相符,另外增加了防止重复解锁的操作,直接使用FLASH_Unlock()这个函数即可以完成解锁。
2.3.2、页擦除
用户手册描述如下:
1、通过检查FLASH_SR寄存器的BSY位来确认flash没有使用
2、把FLASH_CR寄存器的PER位置SET
3、通过编写FLASH_AR寄存器来确认要擦除的页
4、将FLASH_CR寄存器的STRT位置SET
5、等待BSY位rst
6、检查FLASH_SR寄存器中的EOP标记(成功会置SET)(流程图没有、库函数没检查)
7、清除EOP标记(流程图没有、库函数没清除)
检索官方库定位到FLASH_ErasePage(uint32_t Page_Address)这个函数,它的底层实现与文档流程图描述相符,值得注意的是,手册描述中6、7步并没有出现在手册的流程图和库函数中(库版本V1.2.0)。但在使用中没有出现问题,这里先记录看以后使用中会不会出现问题
2.3.3、往flash中写入数据
用户手册描述如下
1、通过检查FLASH_SR寄存器的BSY位来确认flash没有使用
2、设置FLASH_CR寄存器的PG位
3、在目标地址上写入半个word的数据
4、等BSY位reset
5、检查FLASH_SR寄存器的EOP标记(SET表示成功)(流程图没有出现、库函数中没检查)
检索官方库定位到FLASH_ErasePage(uint32_t Page_Address)这个函数,它的底层实现与文档流程图描述相符,同样地,库函数没有检查第五步的EOP标记
2.3.4、上锁操作
根据手册提示,定位到库函数void FLASH_Lock(void)。只要置位LOCK位就上锁了。
2.4、读操作
程序如下
/*******************************************************************************
* Function Name : readPackedMessageFromFlash
* Description : Read packed message form flash
* Input : buff:point to first location of received buffer.length:Maxmum length of reception
* Output :
* Return : reception length
*******************************************************************************/
uint16_t readPackedMessageFromFlash( uint8_t *buff , uint16_t length)
{
int i;
uint16_t getLength;
if( !doseFlashHasPackedMessage() )
return 0;
/*Get valuable length*/
getLength = getValuablePackedMessageLengthofFlash();
/*Read out message*/
for(i=0;i
{
buff[i]= *(uint8_t*)(STM32F0xx_FLASH_PAGE15_STARTADDR+4+i);
}
return MIN(getLength,length);
}
根据用户手册提示,读操作是可以直接取址的,所以读操作实际只有如下一句只要用uint8_t类型取出目标地址再取值就可以了。
但是,我们的数据是打包的(详见2.2),所以还需要:
1、根据报头判断是不是有效数据
2、根据长度判断要读取多少数据
3、最后才是读出数据
2.4.1、判断数据有效性:
我们通过报头来判断数据是不是自己写入的。
也就是判断flash第15页的第1、2个字节是不是0xaa55,如果不是,那这段数据是无效的。
另外再判断一下长度字段,如果长度等于0,也就是后面没有数据,那这段数据也是无效的。
/*******************************************************************************
* Function Name : doseFlashHasPackedMessage
* Description : Does flash has packed messages
* Input : None
* Output :
* Return : ture/false
*******************************************************************************/
bool doseFlashHasPackedMessage(void)
{
uint16_t length;
uint16_t getHead;
/*Is head matched*/
getHead = (uint16_t)(*(uint16_t*)(STM32F0xx_FLASH_PAGE15_STARTADDR ));
if( EEPPROM_PACKAGEHEAD != getHead )
{
return false;
}
/*Is length zero*/
length = (*(uint16_t*)(STM32F0xx_FLASH_PAGE15_STARTADDR+2));
if( 0 == length)
{
return false;
}
return true;
}
2.4.2、根据长度读出数据:
在读Flash程序中,getLength是从flash中读出的长度,length是我们指定的最大读取长度。如果getLength大于我们指定读取长度,很可能会造成溢出,所以两者取小的一个防止溢出。
c语言flash里能存文件吗,STM32内部FLASH打包读写相关推荐
- map文件分析 stm32_使用STM32内部Flash额外的空间来存储数据
本次分享关于STM32内部FLASH的笔记. STM32 芯片内部的 FLASH 存储器,主要用于存储我们代码.如果内部FLASH存储完我们的代码还有剩余的空间,那么这些剩余的空间我们就可以利用起来, ...
- STM32CubeMX系列|STM32内部FLASH
STM32内部FLASH 1. 内部FLASH简介 之前的文章中介绍过STM32F1利用SPI与外部FLASH(W25QXX芯片)通讯的例程,本例程将介绍STM32F1的内部FLASH,通过内部FLA ...
- STM32内部flash详解(1)
STM32 内部FLAsh概述 今天说一下STM32中的内部flash. 当我们把写好的代码下载MCU中,这个代码时存放在flash中的.当芯片重启复位上电后,会通过内核对flash进行代码的加载运行 ...
- stm32内部Flash读写
文章目录 1.stm32内部flash介绍 2.读写驱动编写 3.源码 上篇文章讲到了STM32来驱动外部flah的操作,flash真是好东西啊,内存大,能存的东西多,这样我们就可以用它来做一些大点的 ...
- 读写STM32内部flash读写代码
读写STM32内部flash读写代码 由于老师的要求,所以写了一份读写STM32内部FLASH的代码,这样的话就可以把STM32里面没有用来保存代码段的部分用来存储数据了. 由于<stm32fl ...
- STM32 内部Flash读写 程序源码 [已验证]
目录 STM32 内部Flash带缓存读写 程序源码 0 Macro 1.Flash_Erase 2. Flash_Read_Byte 3.Flash_Write_NoBuffer 4.Flash_W ...
- STM32内部Flash读写问题
STM32Flash读写之Flash调试技巧 文章目录 1.先熟悉所用MCU的Flash存储大小以及扇区地址 2.Flsah写之前为什么要先擦除 3.Flash擦除长时间占用CPU 4.实测Flash ...
- STM32内部Flash的使用
简介 STM32内部自带不同大小的Flash,其主要功能是保存已经编译完成的代码.在实际的产品中为了节约成本如果有需要存储少量的数据会选择存放在内部Flash中. 注:STM32对于Flash 大小的 ...
- 用c语言做RFID读卡程序,2.STM32读卡号读写数据代码示例3.0(C语言)
文件名大小更新时间 2.STM32读卡号读写数据代码示例3.0(C语言)\HFRFID.uvgui.WEIZAI736912016-07-15 2.STM32读卡号读写数据代码示例3.0(C语言)\H ...
最新文章
- Linux常用命令汇总(二)
- Collections Arrays你会用么?
- docker 安装mysql
- 1014 Waiting in Line (30 分) 【未完成】【难度: 难 / 知识点: 大模拟】
- Delphi 105错误
- Linux版本_linux版本信息解析
- HB-X打不开的解决办法
- 转载(四).Net Framework中的委托与事件
- alert闪一下就没了_尾部贯穿式镀铬银饰条除了丑,还能闪瞎眼
- iOS - OC SQLite 数据库存储
- SAP MM模块-实施顾问岗位-面试手册-项目管理经验面试清单-英文
- 西南交通大学计算机网络,西南交通大学计算机网络实验2015-2016第2学期期末试卷...
- 回到顶部效果之加速置顶
- ac9560不支持承载_工程人还在为松软土层地质问题处理而烦恼?不,这里告诉你!...
- 雷士灯wifi控制方法_雷士照明驱动 WiFi 可调光 怎么设置
- Mockplus原型设计工具介绍
- 华为十年,总结出的12条经验!(作者是一级部门总监,华为副总裁)
- 微服务架构-ruoyi
- 台式机通过笔记本的WIFI连接上网,并实现笔记本对台式机的远程连接
- vue下利用canvas实现在线图片标注
热门文章
- php抓取搜狗图片,动手抓取搜狗搜索引擎壁纸API接口
- abap如何找屏幕增强_因增强导致BDC录屏执行异常的梗
- 学业水平考试网登录_海南高中学业水平考试成绩查询免费登录入口:http://ea.hainan.gov.cn/(已开通)...
- idea每次都要配置tomcat_电脑每次开机时间都不对?电脑每次开机都要重新设置时间解决方法...
- 基于nginx实现反向代理
- Java 内存模型和 JVM 内存结构真不是一回事
- python概念(一)python基本数据类型
- 搭配飞行员 dinic
- Atitit 关于处理环保行动联盟和动物解放阵线游击队的任命书 委任状
- 增强画面纵深感的几个小技巧