由于Flash具有擦写速度快,读取方便,掉电不丢失等优点,在工程项目中,常常开辟一块儿数据来存放各个传感器的数据!
在stm32中,无需对于flash进行特别的初始化,但是还是先要去掉写保护,在写这个程序遇到的最大问题是无法进行debug,因为根本就看不到数据,最后只能使用串口发送数据来进行调试
需要注意的是
stm32只能一字(u32)或者半字(u16)输入,且利用flash写入时,其实地址必须为偶数,为奇数无法继续执行
擦除只能是全擦除或者单页擦除
用的是stm32F103VE,下面是调试过的代码
bsp_storge.h
#ifndef _BSP_STORAGE_H
#define _BSP_STORAGE_H
#include "stm32f10x_flash.h"
#include"stdint.h"
#include "bsp_usart.h"
#define Sector_DataSize 256
uint32_t MonthData_TempAddr=(uint32_t)0x0807f700; // 地址计数指针
uint32_t MonthDataStaAddr=(uint32_t)0x08032000; //当前月扇区起始地址
uint32_t MonthDataEndAddr=(uint32_t)0x0807f800; // 当前月扇区终止地址
static FLASH_Status PutDataIntoFlash(uint32_t Address1,uint8_t *buf,uint32_t len);
void ReadFromFlash(uint32_t Addr,uint8_t *buf,uint32_t len);
FLASH_Status WriteToFlash(uint32_t TempAddr,uint8_t *RomData,uint32_t len,uint32_t DataStaAddr,uint32_t DataEndAddr);
void flashtext(void) ;
#endif /*_BSP_STORAGE_H */
bsp_storage.c
#include "bsp_storage.h"
#define PageSize 2048
//#define MonthDataStaAddr ((uint32_t)0x08032000) //sector:100
//#define MonthDataEndAddr ((uint32_t)0x08039FFF) //sector:115 end
//#define LastMonthDataStaAddr ((uint32_t)0x0803A000) //sector:116
//#define LastMonthDataEndAddr ((uint32_t)0x08041FFF) //sector:131 end
//
//#define BeforeLastMonthDataStaAddr ((uint32_t)0x08042000) //sector:132
//#define BeforeLastMonthDataStaAddr ((uint32_t)0x0804AFFF) //sector:149 end
/***************************************************************************************************
*\Function PutDataIntoFlash(uint32_t Address1,uint8_t *buf,uint8_t len)
*\Description 将数据放入到flash中
*\Parameter uint32_t Address1
*\Parameter uint8_t *buf
*\Parameter uint8_t len
*\Return void
*\Note 2014年7月19日 地址只能是偶数
*\Log PutDataIntoFlash(0x0807F800,aaa,5);
*
***************************************************************************************************/
static FLASH_Status PutDataIntoFlash(uint32_t Address1,uint8_t *buf,uint32_t len)
{
uint32_t i;
uint16_t TempData16;// 十六位临时数据变量
FLASH_Status status = FLASH_COMPLETE;
if(len%2==0) // 数据长度奇偶判断
{
for(i=0;i<len;)
{
TempData16=(uint16_t)buf[i]; // 数据进行高低位置调换,人为的将大端模式转换为小端模式,便于数据的读取
TempData16= TempData16|0xFF00;
TempData16= ((((uint16_t)buf[i+1])<<8)|0x00FF)&TempData16;
if(status == FLASH_COMPLETE)
{
status=FLASH_ProgramHalfWord(Address1,TempData16);
Address1+=2;
}
else
{
break;
}
i=i+2;
}
}
else
{
for(i=0;i<len;)
{
TempData16=(uint16_t)buf[i]; // 数据进行高低位置调换,人为的将大端模式转换为小端模式,便于数据的读取
TempData16&=buf[i]; // 数据进行高低位置调换,人为的将大端模式转换为小端模式,便于数据的读取
if(i+2<len) // 数据长度为奇数的时候,将最后一位数据置为(00)
{
TempData16= TempData16|0xFF00;
TempData16= ((((uint16_t)buf[i+1])<<8)|0x00FF)&TempData16;
}
else
TempData16&=0x00FF;
if(status == FLASH_COMPLETE)
{
status=FLASH_ProgramHalfWord(Address1,TempData16);
Address1+=2;
}
else
{
break;
}
i=i+2;
}
}
return status;
}
/***************************************************************************************************
*\Function ReadFromFlash(uint32_t Addr,uint8_t *buf,uint32_t len)
*\Description 读flash中特定位置的值
*\Parameter uint32_t Addr
*\Parameter uint8_t *buf
*\Parameter uint32_t len
*\Return void
*\Note 2014年7月19日
*\Log ReadFromFlash(0x0807F800,buf,5);
***************************************************************************************************/
void ReadFromFlash(uint32_t Addr,uint8_t *buf,uint32_t len)
{
uint32_t address=Addr;
while(len--)
{
*buf=*(uint32_t*)address;
buf++;
address++;
}
return;
}
/***************************************************************************************************
*\Function FLASH_Status WriteToFlash(uint32_t TempAddr,uint8_t *RomData,uint32_t len,uint32_t DataStaAddr,uint32_t DataEndAddr)
*\Description 将数据写入到Flash中
*\Parameter uint32_t Addr 实际存入起始地址 全局变量写入
*\Parameter uint8_t *RomData 需要写入的数据
*\Parameter uint32_t len 数据长度
*\Parameter uint32_t DataStaAddr 扇区总数据起始地址
*\Parameter uint32_t DataEndAddr 扇区总数据结束地址
*\Return FLASH_Status
*\Note 起始地址必须为偶数,且必须为256的倍数 2014年7月20日
*\Log WriteToFlash(MonthData_TempAddr,buf,256,MonthDataStaAddr,MonthDataEndAddr);
***************************************************************************************************/
FLASH_Status WriteToFlash(uint32_t TempAddr,uint8_t *RomData,uint32_t len,uint32_t DataStaAddr,uint32_t DataEndAddr)
{
/*///
数据长度 256字节 一页共8组数据
第一组数据 起始:0 终止 :255
第二组数据 起始:256 终止 :511
第三组数据 起始:512 终止 :767
第四组数据 起始:768 终止 :1023
....... ..........
....... ..........
第八组数据 起始:1792 终止 :2047
每组数据中:
起始20字节 : 标志使用码,当前储存数据组,
终止20字节 :
/
*/
FLASH_Status status;
uint32_t staAddr; // 将要写入的扇区起始地址
uint32_t count; // 对于扇区内的分组进行计数
uint8_t buf1[PageSize]={0};
uint32_t i,j;
FLASH_Unlock();
FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
staAddr=TempAddr-(TempAddr%PageSize);
count=(TempAddr%PageSize)/Sector_DataSize;
/* 读出*/
ReadFromFlash(staAddr,buf1,PageSize); // 从flash中读出当前页的值
/*更改数据*/
for(i=count*Sector_DataSize,j=0;i<count*Sector_DataSize+Sector_DataSize;i++,j++)
{
buf1[i]=RomData[j];
}
/* 擦除整页 */
status=FLASH_ErasePage(staAddr);
/* 写回 */
status=PutDataIntoFlash(staAddr,buf1,PageSize);
MonthData_TempAddr=TempAddr+Sector_DataSize; // 为下一次写入更新地址
if(MonthData_TempAddr>=DataEndAddr) // DataEndAddr,DataStaAddr即使开始的时候定为全局变量,但仍旧无法传值,估计是因为写flash的原因,对于地址的传入还是用参数传入
{
MonthData_TempAddr=DataStaAddr;
}
FLASH_Lock();
return status;
}
/***************************************************************************************************
*\Function flashtext(void)
*\Description flash测试函数
*\Return void
*\Note 2014年7月21日
*\Log
***************************************************************************************************/
void flashtext(void)
{
// uint32_t temp3;
// uint32_t Addr;
// uint8_t aaa[5]={0x01,0x02,0x03,0x04,0x05};
// uint8_t buf[7]={0};
uint8_t buf[256]={0x01,0x02,0x03,0x04,0x05};
// FlagStatus status=RESET;
// status=FLASH_GetReadOutProtectionStatus();
// Usart_Sendchar(USART2,0x12);
// WriteToFlash(0x08032000,buf,256);
// WriteToFlash(0x08032100,buf,256);
// WriteToFlash(0x08032200,buf,256);
WriteToFlash(MonthData_TempAddr,buf,256,MonthDataStaAddr,MonthDataEndAddr);
WriteToFlash(MonthData_TempAddr,buf,256,MonthDataStaAddr,MonthDataEndAddr);
WriteToFlash(MonthData_TempAddr,buf,256,MonthDataStaAddr,MonthDataEndAddr);
// WriteToFlash(MonthData_TempAddr,buf,256);
//WriteToFlash(MonthData_TempAddr,buf,256);
//FLASH_ErasePage(0x0807F800);
/// PutDataIntoFlash(0x0807F800,aaa,5);
// ReadFromFlash(0x0807F800,buf,5);
// NumDisplayOnLCD(buf,5);
// FLASH_ProgramHalfWord(0x0807F800,0x0123);
while(1);
//
// Addr=*(__IO uint16_t *) (((uint32_t)0x0807F801));
// Usart_Sendchar(USART2,(uint8_t)Addr);
//Addr=(uint32_t)0x0801FC00;
// temp3=*(__IO uint32_t*)Addr;
}
版权声明:本文为xiaoleiacm原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。