使用STM32的FLASH保存数据
为了防止“掉电丢失数据”,我们最先想到的是EEPROM,但是若考虑到降低成本和PCB布线的空间,使用CPU内部的FLASH空间来保存数据,是最好的选择。尤其是在STM32芯片上,应用案例还是比较多的。
STM32的FLASH是以半字保存数据的,因此,我们可以将“掉电数据”以双字节为最小存储单位去进行访问。
STM32没有自带 的EEPROM,但是它具有 IAP功能,因此,我们可以把它的 FLASH 当成 EEPROM 来使用。
1、STM32_Internal_FLASH.h文件如下:
#ifndef _STM32_Internal_FLASH_H
#define _STM32_Internal_FLASH_H
#include "stm32f10x.h"
#include "sys.h"
#define STM32_FLASH_BASE_ADDRESS ( (uint32_t)0x08000000 )
//STM32 FLASH的编程起始地址
#define STM32_FLASH_SIZE 512
//所选STM32的FLASH容量大小(单位为K)
#if STM32_FLASH_SIZE<256 //CPU的FLASH空间小于256K字节
#define STM_SECTOR_SIZE 1024 //每个扇区为1024个字节
#define STMFLASH_WriteLength_SIZE 512 //每个扇区为512个半字
#define STM32_FLASH_START_ADDRESS ( (uint32_t)0x0800FC00 )
//数据保存到STM32F103C8T6最后一页,即第64页,号码为63,页大小为1KB
#else
#define STM_SECTOR_SIZE 2048 //每个扇区为2048个字节
#define STMFLASH_WriteLength_SIZE 1024 //每个扇区为1024个半字
#define STM32_FLASH_START_ADDRESS ( (uint32_t)0x0807F800 )
//数据保存到STM32F103ZET6最后一页,即第256页,号码为255,页大小为2KB
#endif
union EEPROM_Uint16_Data_TYPE
{ unsigned char b[2]; //b[1]和Data的高8位值相等;b[0]和Data的低8位值相等;
uint16_t Data;
};
union EEPROM_U32_Data_TYPE
{ u8 b[4]; //b[3]和Data的高8位值相等;b[0]和Data的低8位值相等;
u32 Data;
};
union EEPROM_FLOAT_DATA_TYPE
{ u8 b[4]; //b[3]和float_data的高8位值相等;b[0]和float_data的低8位值相等;
float float_data;
};
union EEPROM_DOUBLE_DATA_TYPE
{ u8 b[8]; //b[7]和float_data的高8位值相等;b[0]和float_data的低8位值相等;
double float_data;
};
extern void STMFLASH_Read(u32 tReadAddr,u16 *pBuffer,u16 tSize);
extern void IAP_Write_APP_BIN(uint32_t gIAP_FlashAddress,u8 *pBuffer,u16 len);
extern void EEPROM_U16_Data_Write(u16 x,uint32_t addr);
extern u16 EEPROM_U16_Data_Read(uint32_t addr);
extern void EEPROM_U32_Data_Write(u32 x,uint32_t addr);
extern u32 EEPROM_U32_Data_Read(uint32_t addr);
extern void EEPROM_Float_Data_Write(float x,uint32_t addr);
extern float EEPROM_Float_Data_Read(uint32_t addr);
extern void EEPROM_Double_Data_Write(double x,uint32_t addr);
extern double EEPROM_Double_Data_Read(uint32_t addr);
extern void CPU_FLASH_Read_Write_Test(void);
#endif
2、STM32_Internal_FLASH.c文件如下:
#include "STM32_Internal_FLASH.h"
#include "stdio.h"
void STMFLASH_Read(u32 tReadAddr,u16 *pBuffer,u16 tSize);
void IAP_Write_APP_BIN(uint32_t gIAP_FlashAddress,u8 *pBuffer,u16 len);
void EEPROM_U16_Data_Write(u16 x,uint32_t addr);
u16 EEPROM_U16_Data_Read(uint32_t addr);
void EEPROM_U32_Data_Write(u32 x,uint32_t addr);
u32 EEPROM_U32_Data_Read(uint32_t addr);
void EEPROM_Float_Data_Write(float x,uint32_t addr);
float EEPROM_Float_Data_Read(uint32_t addr);
void EEPROM_Double_Data_Write(double x,uint32_t addr);
double EEPROM_Double_Data_Read(uint32_t addr);
void CPU_FLASH_Read_Write_Test(void);
//函数功能:从CPU的FLASH地址tReadAddr处读取半字(16位数据)
//tReadAddr:CPU的FLASH地址(此地址必须为2的倍数!!)
//返回值:返回半字(16位数据)
u16 STMFLASH_ReadHalfWord(u32 tReadAddr)
{
return *(vu16*)tReadAddr;
}
//从CPU的FLASH地址tReadAddr处读取tSize个半字(16位数据),保存到首地址为pBuffer的缓冲区中
//tReadAddr:起始地址
//pBuffer:数据指针
//tSize:半字(16位)数
void STMFLASH_Read(u32 tReadAddr,u16 *pBuffer,u16 tSize)
{
u16 i;
for(i=0;i<tSize;i++)
{
pBuffer[i]=STMFLASH_ReadHalfWord(tReadAddr);
//从CPU的FLASH地址tReadAddr处读取半字(16位数据)
tReadAddr=tReadAddr+2;//偏移2个字节.
}
}
//函数功能:将STMFLASH_BUF[]中前STMFLASH_WriteLength个半字,从FLASH起始地址为STMFLASH_WriteAddress开始处写入,在写之前不检查能否写入
//STMFLASH_WriteAddress:CPU的FLASH起始地址
//STMFLASH_BUF:待写数据缓冲区的起始指针
//STMFLASH_WriteLength:需要写入"半字(16位)"的个数
//STMFLASH_WriteLength;要写入的双字节数,待写数据在STMFLASH_BUF[]中
//STMFLASH_BUF[STMFLASH_WriteLength_SIZE];//最多是2K字节,即1K个双字节
void STMFLASH_Write_NoCheck(u32 STMFLASH_WriteAddress,u16 *STMFLASH_BUF,u16 STMFLASH_WriteLength)
{
u16 k;
for(k=0;k<STMFLASH_WriteLength;k++)
//循环写入STMFLASH_WriteLength个"半字"
{
FLASH_ProgramHalfWord(STMFLASH_WriteAddress,STMFLASH_BUF[k]);
STMFLASH_WriteAddress=STMFLASH_WriteAddress+2;
//CPU的FLASH地址增加2,指向下一个地址
}
}
const char IAP_FlashAddress1_REG[]="\r\nIAP_FlashAddress1=0x";
const char IAP_FlashAddress2_REG[]="\r\nIAP_FlashAddress2=0x";
//函数功能:将pBuffer[]中前tSize个半字,从FLASH起始地址为tWriteAddr开始处写入,在写之前检查能否写入
//IAP_FlashAddress:起始地址(此地址必须为2的倍数!!)
//pBuffer:数据指针,数据在IAP_Buffer[]中
//tSize:装载烧写数据的数量,单位为半字,和IAP_Buffer_Length一样
void STMFLASH_Write(uint32_t gIAP_FlashAddress,u16 *pBuffer,u16 tSize)
{
u16 t;
u16 i;
u16 tmp;
u8 flag;
u16 STMFLASH_BUF[STMFLASH_WriteLength_SIZE];
//最多是2K字节,即1K个双字节
u16 STMFLASH_WriteLength;
//要写入的双字节数,待写数据在STMFLASH_BUF[]中
u32 STMFLASH_WriteAddress; //写地址
u16 STMFLASH_BUF_Index; //用来指示STMFLASH_BUF[]中待写数据的下标
u16 STMFLASH_BUF_Load_Length;
//用来指示STMFLASH_BUF[]中待装载的数据长度
uint32_t gIAP_FlashSectorNumber; //扇区号从0开始
uint32_t gIAP_FlashOffsetAddress;//其值为(IAP_FlashAddress-0X08000000)
(void)flag;
if( gIAP_FlashAddress<STM32_FLASH_BASE_ADDRESS||(gIAP_FlashAddress>=(STM32_FLASH_BASE_ADDRESS+1024*STM32_FLASH_SIZE)) )
return;//非法地址
FLASH_Unlock();//解锁
while(1)//循环写FLASH
{
gIAP_FlashOffsetAddress=gIAP_FlashAddress-STM32_FLASH_BASE_ADDRESS;
//计算"待写数据"在FLASH中的偏移地址
gIAP_FlashSectorNumber=gIAP_FlashOffsetAddress/STM_SECTOR_SIZE;
//计算"待写数据"在FLASH中的扇区号码,从0开始
tmp=gIAP_FlashOffsetAddress%STM_SECTOR_SIZE;
//计算"当前扇区"已经写了多少个字节
STMFLASH_BUF_Index=tmp/2;//计算"当前扇区"已经写了多少个半字
STMFLASH_BUF_Load_Length=STMFLASH_WriteLength_SIZE-STMFLASH_BUF_Index;
//计算"待写数据"的数量
if(tSize<=STMFLASH_BUF_Load_Length)
//"待写数据的数量"没有越过当前扇区的范围
{
flag=0;
STMFLASH_BUF_Load_Length=tSize;
}
else flag=1;
gIAP_FlashAddress=gIAP_FlashSectorNumber*STM_SECTOR_SIZE;
gIAP_FlashAddress=gIAP_FlashAddress+STM32_FLASH_BASE_ADDRESS;
//计算扇区的首地址
STMFLASH_Read(gIAP_FlashAddress,STMFLASH_BUF,STMFLASH_WriteLength_SIZE);//根据扇区首地址,读出整个扇区的内容
for(i=0;i<STMFLASH_BUF_Load_Length;i++)//检查"待写的区域"是否需要擦除
{
t=STMFLASH_BUF_Index+i;//计算"修改数据"的下标值
if(STMFLASH_BUF[t]!=0XFFFF)break;//需要擦除
}
if(i<STMFLASH_BUF_Load_Length)//"待写的区域"需要擦除
{
FLASH_ErasePage(gIAP_FlashAddress);//根据扇区首地址,擦除这个扇区
for(i=0;i<STMFLASH_BUF_Load_Length;i++)//装载"待编程数据"
{
t=STMFLASH_BUF_Index+i;
//得到在STMFLASH_BUF[]中的下标偏移量
STMFLASH_BUF[t]=pBuffer[i];
//装载"待写数据"到STMFLASH_BUF[]中
}
STMFLASH_WriteAddress=gIAP_FlashAddress;
//将"扇区首地址"作为"写起始地址"
STMFLASH_WriteLength=STMFLASH_BUF_Index+STMFLASH_BUF_Load_Length;
//计算“写入半字的数量“
STMFLASH_Write_NoCheck(STMFLASH_WriteAddress,STMFLASH_BUF,STMFLASH_WriteLength);//写入整个扇区
tmp=STMFLASH_WriteLength;tmp=(u16)(tmp<<1);//计算已写字节数量
gIAP_FlashAddress=gIAP_FlashAddress+tmp;//记录写结束地址
printf("%s",IAP_FlashAddress1_REG);
printf("%x",gIAP_FlashAddress);
}
else//"待写的区域"不需要擦除
{
for(i=0;i<STMFLASH_BUF_Load_Length;i++)//装载"待编程数据"
{
STMFLASH_BUF[i]=pBuffer[i];
}
gIAP_FlashAddress=gIAP_FlashAddress+tmp; //计算写起始地址
STMFLASH_WriteAddress=gIAP_FlashAddress; //记录写地址
STMFLASH_WriteLength=STMFLASH_BUF_Load_Length;
//计算“写入半字的数量“
STMFLASH_Write_NoCheck(STMFLASH_WriteAddress,STMFLASH_BUF,STMFLASH_WriteLength);
//写已经擦除了的,直接写入扇区剩余区间
tmp=STMFLASH_WriteLength;tmp=(u16)(tmp<<1);//计算已写字节数量
gIAP_FlashAddress=gIAP_FlashAddress+tmp;//记录写结束地址
printf("%s",IAP_FlashAddress2_REG);
printf("%x",gIAP_FlashAddress);
}
if(tSize==STMFLASH_BUF_Load_Length)
{
break;//写入结束了
}
else//写入未结束
{
gIAP_FlashSectorNumber++;//扇区编号增1
STMFLASH_BUF_Index=0;//偏移位置为0
pBuffer=pBuffer+STMFLASH_BUF_Load_Length;
//已经写了STMFLASH_BUF_Load_Length个半字,修改pBuffer指针,指向需要写的数据
tSize=tSize-STMFLASH_BUF_Load_Length;//计算"剩余的待写数据"的个数
if( tSize>(STMFLASH_WriteLength_SIZE) )//超过一个扇区
STMFLASH_BUF_Load_Length=STMFLASH_WriteLength_SIZE;
//下一个扇区还是写不完
else//不足一个扇区
{
STMFLASH_BUF_Load_Length=tSize;//下一个扇区可以写完了
}
}
}
FLASH_Lock();//上锁
}
//gIAP_FlashAddress:烧写数据的起始地址
//pBuffer[]:待烧写数据块的首地址
//len:烧写数据的数量(字节)
void IAP_Write_APP_BIN(uint32_t gIAP_FlashAddress,u8 *pBuffer,u16 len)
{
u16 t;
u16 i;
u16 tmp1,tmp2;
u16 gIAP_Buffer[1024];
u16 gIAP_Buffer_Length;
if( gIAP_FlashAddress<STM32_FLASH_BASE_ADDRESS||(gIAP_FlashAddress>=(STM32_FLASH_BASE_ADDRESS+1024*STM32_FLASH_SIZE)) )return;//非法地址
i=0;
for(t=0;t<len;)//若Len>2048则循环写入
{
tmp1=*pBuffer;tmp1=(u16)(tmp1&0x00FF);pBuffer++;
tmp2=*pBuffer;tmp2=(u16)(tmp2<<8);tmp2=(u16)(tmp2&0xFF00);pBuffer++;
tmp2=(u16)(tmp2|tmp1);//合成半字(16位),生成"待写数据"
gIAP_Buffer[i]=tmp2;i++;//将"待写数据"保存到IAP_Buffer[]中
if(i==STMFLASH_WriteLength_SIZE)//满1K个半字,则执行写入CPU的FLASH
{
i=0;
gIAP_Buffer_Length=STMFLASH_WriteLength_SIZE;
//装载烧写数据的数量,单位为半字
STMFLASH_Write(gIAP_FlashAddress,gIAP_Buffer,gIAP_Buffer_Length);
}
t=t+2;//因为读取的是半字,所以要加2
}
if(i)//还有i个半字等待写入FLASH
{
gIAP_Buffer_Length=i;//装载烧写数据的数量,单位为半字
STMFLASH_Write(gIAP_FlashAddress,gIAP_Buffer,gIAP_Buffer_Length);
//将最后的一些内容字节写进去
}
}
//函数功能:将u16型数据x保存到CPU的FLASH中,保存数据的地址为addr;
void EEPROM_U16_Data_Write(u16 x,uint32_t addr)
{
union EEPROM_Uint16_Data_TYPE temp;
temp.Data=x;
IAP_Write_APP_BIN(addr,temp.b,2);
}
//函数功能:从CPU的FLASH中读取u16型数据
u16 EEPROM_U16_Data_Read(uint32_t addr)
{
u16 rerurn_value;
STMFLASH_Read(addr,&rerurn_value,1);
//从CPU的FLASH地址addr处读取1个半字(16位数据),保存到首地址为"&rerurn_value"的缓冲区中
//返回数据保存在rerurn_value中
return(rerurn_value);
}
//函数功能:将u32型数据x保存到CPU的FLASH中,保存数据的地址为addr;
void EEPROM_U32_Data_Write(u32 x,uint32_t addr)
{
union EEPROM_U32_Data_TYPE temp;
temp.Data=x;
IAP_Write_APP_BIN(addr,temp.b,4);
}
//函数功能:从CPU的FLASH中读取u32型数据
u32 EEPROM_U32_Data_Read(uint32_t addr)
{
union EEPROM_U32_Data_TYPE temp;
u16 rerurn_value;
temp.Data=0;
STMFLASH_Read(addr,&rerurn_value,1);
//从CPU的FLASH地址addr处读取1个半字(16位数据),保存到首地址为"&rerurn_value"的缓冲区中
//返回数据保存在rerurn_value中
temp.b[0]=(u8)( rerurn_value&0x00FF );
temp.b[1]=(u8)( (u16)(rerurn_value>>8)&0x00FF );
addr=addr+2;//因为数据是以半字保存的,因此地址addr需要加2
STMFLASH_Read(addr,&rerurn_value,1);
//从CPU的FLASH地址addr处读取1个半字(16位数据),保存到首地址为"&rerurn_value"的缓冲区中
//返回数据保存在rerurn_value中
temp.b[2]=(u8)( rerurn_value&0x00FF );
temp.b[3]=(u8)( (u16)(rerurn_value>>8)&0x00FF );
return(temp.Data);
}
//函数功能:将float型数据x保存到CPU的FLASH中,保存数据的地址为addr;
void EEPROM_Float_Data_Write(float x,uint32_t addr)
{
union EEPROM_FLOAT_DATA_TYPE temp;
temp.float_data=x;
IAP_Write_APP_BIN(addr,temp.b,4);
}
//函数功能:从CPU的FLASH中读取float型数据
float EEPROM_Float_Data_Read(uint32_t addr)
{
union EEPROM_FLOAT_DATA_TYPE temp;
u16 rerurn_value;
temp.float_data=0;
STMFLASH_Read(addr,&rerurn_value,1);
//从CPU的FLASH地址addr处读取1个半字(16位数据),保存到首地址为"&rerurn_value"的缓冲区中
//返回数据保存在rerurn_value中
temp.b[0]=(u8)( rerurn_value&0x00FF );
temp.b[1]=(u8)( (u16)(rerurn_value>>8)&0x00FF );
addr=addr+2;//因为数据是以半字保存的,因此地址addr需要加2
STMFLASH_Read(addr,&rerurn_value,1);
//从CPU的FLASH地址addr处读取1个半字(16位数据),保存到首地址为"&rerurn_value"的缓冲区中
//返回数据保存在rerurn_value中
temp.b[2]=(u8)( rerurn_value&0x00FF );
temp.b[3]=(u8)( (u16)(rerurn_value>>8)&0x00FF );
return(temp.float_data);
}
//函数功能:将double型数据x保存到CPU的FLASH中,保存数据的地址为addr;
void EEPROM_Double_Data_Write(double x,uint32_t addr)
{
union EEPROM_DOUBLE_DATA_TYPE temp;
temp.float_data=x;
IAP_Write_APP_BIN(addr,temp.b,8);
}
//函数功能:从CPU的FLASH中读取double型数据
double EEPROM_Double_Data_Read(uint32_t addr)
{
union EEPROM_DOUBLE_DATA_TYPE temp;
u16 rerurn_value;
temp.float_data=0;
STMFLASH_Read(addr,&rerurn_value,1);
//从CPU的FLASH地址addr处读取1个半字(16位数据),保存到首地址为"&rerurn_value"的缓冲区中
//返回数据保存在rerurn_value中
temp.b[0]=(u8)( rerurn_value&0x00FF );
temp.b[1]=(u8)( (u16)(rerurn_value>>8)&0x00FF );
addr=addr+2;//因为数据是以半字保存的,因此地址addr需要加2
STMFLASH_Read(addr,&rerurn_value,1);
//从CPU的FLASH地址addr处读取1个半字(16位数据),保存到首地址为"&rerurn_value"的缓冲区中
//返回数据保存在rerurn_value中
temp.b[2]=(u8)( rerurn_value&0x00FF );
temp.b[3]=(u8)( (u16)(rerurn_value>>8)&0x00FF );
addr=addr+2;//因为数据是以半字保存的,因此地址addr需要加2
STMFLASH_Read(addr,&rerurn_value,1);
//从CPU的FLASH地址addr处读取1个半字(16位数据),保存到首地址为"&rerurn_value"的缓冲区中
//返回数据保存在rerurn_value中
temp.b[4]=(u8)( rerurn_value&0x00FF );
temp.b[5]=(u8)( (u16)(rerurn_value>>8)&0x00FF );
addr=addr+2;//因为数据是以半字保存的,因此地址addr需要加2
STMFLASH_Read(addr,&rerurn_value,1);
//从CPU的FLASH地址addr处读取1个半字(16位数据),保存到首地址为"&rerurn_value"的缓冲区中
//返回数据保存在rerurn_value中
temp.b[6]=(u8)( rerurn_value&0x00FF );
temp.b[7]=(u8)( (u16)(rerurn_value>>8)&0x00FF );
return(temp.float_data);
}
#define STM32_FLASH_U16_DATA_ADDRESS (STM32_FLASH_START_ADDRESS) //占2个字节,如保存0xABCD
#define STM32_FLASH_U32_DATA_ADDRESS (STM32_FLASH_U16_DATA_ADDRESS+2) //占4个字节,如保存0x12345678
#define STM32_FLASH_FLOAT_DATA_ADDRESS (STM32_FLASH_U32_DATA_ADDRESS+4) //占4个字节,如保存123.456
#define STM32_FLASH_DOUBLE_DATA_ADDRESS (STM32_FLASH_FLOAT_DATA_ADDRESS+4) //占8个字节,如保存1234567.89
#define STM32_FLASH_U16_DATA_ADDRESS1 (STM32_FLASH_DOUBLE_DATA_ADDRESS+8) //占2个字节,如保存0xDCBA
#define STM32_FLASH_U32_DATA_ADDRESS1 (STM32_FLASH_U16_DATA_ADDRESS1+2) //占4个字节,如保存0x87654321
#define STM32_FLASH_FLOAT_DATA_ADDRESS1 (STM32_FLASH_U32_DATA_ADDRESS1+4) //占4个字节,如保存456.123
#define STM32_FLASH_DOUBLE_DATA_ADDRESS1 (STM32_FLASH_FLOAT_DATA_ADDRESS1+4) //占8个字节,如保存89.1234567
const char Address_REG[]="\r\nAddress: ";
const char Data_REG[]=" Data: ";
/*
Address: 0807F800 Data: ABCD
Address: 0807F812 Data: DCBA
Address: 0807F802 Data: 12345678
Address: 0807F814 Data: 87654321
Address: 0807F806 Data: 123.456001
Address: 0807F818 Data: 456.122986
Address: 0807F80A Data: 1234567.890000
Address: 0807F81C Data: 89.123457
Modify Data Test
Address: 0807F800 Data: AAAA
Address: 0807F812 Data: BBBB
Address: 0807F802 Data: CCCCCCCC
Address: 0807F814 Data: DDDDDDDD
Address: 0807F806 Data: 111.222000
Address: 0807F818 Data: 333.444000
Address: 0807F80A Data: 555.666000
Address: 0807F81C Data: 777.888000
*/
void CPU_FLASH_Read_Write_Test(void)
{
u16 u16_Data;
u32 u32_Data;
float float_Data;
double double_Data;
EEPROM_U16_Data_Write(0xABCD,STM32_FLASH_U16_DATA_ADDRESS);
EEPROM_U16_Data_Write(0xDCBA,STM32_FLASH_U16_DATA_ADDRESS1);
EEPROM_U32_Data_Write(0x12345678,STM32_FLASH_U32_DATA_ADDRESS);
EEPROM_U32_Data_Write(0x87654321,STM32_FLASH_U32_DATA_ADDRESS1);
EEPROM_Float_Data_Write(123.456,STM32_FLASH_FLOAT_DATA_ADDRESS);
EEPROM_Float_Data_Write(456.123,STM32_FLASH_FLOAT_DATA_ADDRESS1);
EEPROM_Double_Data_Write(1234567.89,STM32_FLASH_DOUBLE_DATA_ADDRESS);
EEPROM_Double_Data_Write(89.1234567,STM32_FLASH_DOUBLE_DATA_ADDRESS1);
u16_Data=EEPROM_U16_Data_Read(STM32_FLASH_U16_DATA_ADDRESS);
printf("%s",Address_REG);printf("%08X",STM32_FLASH_U16_DATA_ADDRESS);
printf("%s",Data_REG);printf("%02X",u16_Data);
u16_Data=EEPROM_U16_Data_Read(STM32_FLASH_U16_DATA_ADDRESS1);
printf("%s",Address_REG);printf("%08X",STM32_FLASH_U16_DATA_ADDRESS1);
printf("%s",Data_REG);printf("%02X",u16_Data);
u32_Data=EEPROM_U32_Data_Read(STM32_FLASH_U32_DATA_ADDRESS);
printf("%s",Address_REG);printf("%08X",STM32_FLASH_U32_DATA_ADDRESS);
printf("%s",Data_REG);printf("%04X",u32_Data);
u32_Data=EEPROM_U32_Data_Read(STM32_FLASH_U32_DATA_ADDRESS1);
printf("%s",Address_REG);printf("%08X",STM32_FLASH_U32_DATA_ADDRESS1);
printf("%s",Data_REG);printf("%04X",u32_Data);
float_Data=EEPROM_Float_Data_Read(STM32_FLASH_FLOAT_DATA_ADDRESS);
printf("%s",Address_REG);printf("%08X",STM32_FLASH_FLOAT_DATA_ADDRESS);
printf("%s",Data_REG);printf("%f",float_Data);
float_Data=EEPROM_Float_Data_Read(STM32_FLASH_FLOAT_DATA_ADDRESS1);
printf("%s",Address_REG);printf("%08X",STM32_FLASH_FLOAT_DATA_ADDRESS1);
printf("%s",Data_REG);printf("%f",float_Data);
double_Data=EEPROM_Double_Data_Read(STM32_FLASH_DOUBLE_DATA_ADDRESS);
printf("%s",Address_REG);printf("%08X",STM32_FLASH_DOUBLE_DATA_ADDRESS);
printf("%s",Data_REG);printf("%lf",double_Data);
double_Data=EEPROM_Double_Data_Read(STM32_FLASH_DOUBLE_DATA_ADDRESS1);
printf("%s",Address_REG);printf("%08X",STM32_FLASH_DOUBLE_DATA_ADDRESS1);
printf("%s",Data_REG);printf("%lf",double_Data);
//修改数据测试
printf("\r\nModify Data Test");
EEPROM_U16_Data_Write(0xAAAA,STM32_FLASH_U16_DATA_ADDRESS);
EEPROM_U16_Data_Write(0xBBBB,STM32_FLASH_U16_DATA_ADDRESS1);
EEPROM_U32_Data_Write(0xCCCCCCCC,STM32_FLASH_U32_DATA_ADDRESS);
EEPROM_U32_Data_Write(0xDDDDDDDD,STM32_FLASH_U32_DATA_ADDRESS1);
EEPROM_Float_Data_Write(111.222,STM32_FLASH_FLOAT_DATA_ADDRESS);
EEPROM_Float_Data_Write(333.444,STM32_FLASH_FLOAT_DATA_ADDRESS1);
EEPROM_Double_Data_Write(555.666,STM32_FLASH_DOUBLE_DATA_ADDRESS);
EEPROM_Double_Data_Write(777.888,STM32_FLASH_DOUBLE_DATA_ADDRESS1);
u16_Data=EEPROM_U16_Data_Read(STM32_FLASH_U16_DATA_ADDRESS);
printf("%s",Address_REG);printf("%08X",STM32_FLASH_U16_DATA_ADDRESS);
printf("%s",Data_REG);printf("%02X",u16_Data);
u16_Data=EEPROM_U16_Data_Read(STM32_FLASH_U16_DATA_ADDRESS1);
printf("%s",Address_REG);printf("%08X",STM32_FLASH_U16_DATA_ADDRESS1);
printf("%s",Data_REG);printf("%02X",u16_Data);
u32_Data=EEPROM_U32_Data_Read(STM32_FLASH_U32_DATA_ADDRESS);
printf("%s",Address_REG);printf("%08X",STM32_FLASH_U32_DATA_ADDRESS);
printf("%s",Data_REG);printf("%04X",u32_Data);
u32_Data=EEPROM_U32_Data_Read(STM32_FLASH_U32_DATA_ADDRESS1);
printf("%s",Address_REG);printf("%08X",STM32_FLASH_U32_DATA_ADDRESS1);
printf("%s",Data_REG);printf("%04X",u32_Data);
float_Data=EEPROM_Float_Data_Read(STM32_FLASH_FLOAT_DATA_ADDRESS);
printf("%s",Address_REG);printf("%08X",STM32_FLASH_FLOAT_DATA_ADDRESS);
printf("%s",Data_REG);printf("%f",float_Data);
float_Data=EEPROM_Float_Data_Read(STM32_FLASH_FLOAT_DATA_ADDRESS1);
printf("%s",Address_REG);printf("%08X",STM32_FLASH_FLOAT_DATA_ADDRESS1);
printf("%s",Data_REG);printf("%f",float_Data);
double_Data=EEPROM_Double_Data_Read(STM32_FLASH_DOUBLE_DATA_ADDRESS);
printf("%s",Address_REG);printf("%08X",STM32_FLASH_DOUBLE_DATA_ADDRESS);
printf("%s",Data_REG);printf("%lf",double_Data);
double_Data=EEPROM_Double_Data_Read(STM32_FLASH_DOUBLE_DATA_ADDRESS1);
printf("%s",Address_REG);printf("%08X",STM32_FLASH_DOUBLE_DATA_ADDRESS1);
printf("%s",Data_REG);printf("%lf",double_Data);
}
#include "string.h"
//写CPU的最后一个扇区
void Write_CPU_Last_SECTOR (void)
{
u8 buf[STM_SECTOR_SIZE];
memset(buf,0,STM_SECTOR_SIZE);
buf[0]=0x11;
buf[1]=0x22;
buf[2]=0x33;
buf[3]=0x44;
buf[4]=0x55;
buf[5]=0x66;
buf[6]=0x77;
buf[7]=0x88;
buf[STM_SECTOR_SIZE-9]=0x99;
buf[STM_SECTOR_SIZE-8]=0x88;
buf[STM_SECTOR_SIZE-7]=0x77;
buf[STM_SECTOR_SIZE-6]=0x66;
buf[STM_SECTOR_SIZE-5]=0x55;
buf[STM_SECTOR_SIZE-4]=0x44;
buf[STM_SECTOR_SIZE-3]=0x33;
buf[STM_SECTOR_SIZE-2]=0x22;
buf[STM_SECTOR_SIZE-1]=0x11;
IAP_Write_APP_BIN(STM32_FLASH_START_ADDRESS,buf,STM_SECTOR_SIZE);
}
3、测试结果:
编译配置:
使用J-Flash烧写程序,启动CPU,然后再读回程序,发现以前保存的数据仍旧存在,便于反复烧写,方便生产。