由于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; }