stm32内部存储分为两种:RAM和ROM。
RAM:随机存储器。特点是 :1、可以随机访问空间内的某地址,并且速度快(通常和CPU通过总线交互),可以用来存放程序运算过程中产生的中间数据,即内存。2、掉电不能保存数据。
ROM:只读存储器。特点是:1、掉电可以保存数据。2、保存程序代码和const一类常量。
ROM中分为三部分:1、bootload(启动代码)、上电后最先执行此部分(主要用来检测系统基本情况如:晶振、电源等)。 2、存储区,用户编写的程序代码 (程序代码地址从0x08000000开始)。3、一些键值和flash管理寄存器。当系统复位后,程序指针首先指向0x08000000,即从此处开始执行程序。
大容量的芯片flash有512k。主存储区从0x08000000开始到0x08080000结束,将flash划分成128个区块,每个区块共2K字节。
此处尝试在主存储区中代码部分之外的区域存放一些常量数据,并在程序中读取出来。如果没有特定的存储设备,但是还想存储一些程序中运行的量在掉电后不丢失的情况可以试试。
实际运行:
具体代码如下(库函数):
一些常量个用到的头文件
#include "usart.h" //正点原子通用串口1配置
#include "sys.h" //正点原子通用系统配置
#include "delay.h" //正点原子通用延时函数
#include "stm32f10x_flash.h" //官方flash操作库函数
#define BASE_ADDR 0x08000000 //定义主存储区基地址
#define SAVE_ADDR 0x08050000 //定义数据存放的地址
#define sector_size 2048 //定义每个区的大小
#define flash_size 512 //定义flash的大小
u8 buffer1[]={"this will been locaed flash"}; //要写入的数据,注意:字符串只能用u8类型的数据,后期要转换成32位。
u16 buffersize =sizeof(buffer1); //从flash中读取出来存放数据的缓存,串口将此地址中的值发送。
u8 buffer2[sizeof(buffer1)]; //定义数据大小
main函数很简单,做一些初始化和串口准备工作。
此处关于flash的读写就俩函数(已经标注)。
正点原子源码中操作读写半字(16位)。此处读写一个字(32位)。
int main()
{
u16 i;
delay_init();
NVIC_PriorityGroupConfig( NVIC_PriorityGroup_2);
uart_init(4800);
write_to_falsh(SAVE_ADDR,(u32 *) buffer1, buffersize); //写入flash
read_from_flash(SAVE_ADDR,(u32*) buffer2,buffersize); //从flash中读取
while(1)
{
for(i=0;i<buffersize;i++)
{
USART_SendData( USART1, buffer2[i]);
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);
}
}
}
主要看下面两个读写函数:
从flash中地址为addr的地方读取num个数据存放到buff中
void read_from_flash(u32 addr,u32* buff,u16 num)
{
u16 i;
for(i=0;i<num;i++)
{
buff[i]=* addr;
addr+=4; //每次读取32位数据,共4个字节。下次读取4个字节后的地址
}
}
下面是写入flash
u8 write_to_falsh(u32 addr,u32* buf,u16 num)
{
u16 i;
u32 off_addr=addr-BASE_ADDR; //基地址的偏移地址
u32 sector_addr= off_addr/sector_size; //扇区地址
u32 sector_off = off_addr%sector_size; //扇区内偏移地址
u32 secremain=sector_size-sector_addr; //剩余量
if(addr<BASE_ADDR||addr>BASE_ADDR+1024*flash_size) return 0; //如果需要操作的地址超出主存储区,则视为非法地址,结束程序。
FLASH_Unlock(); //解锁,向两个KEY中写入键值,类似于开锁,用来保护flash防止误操作。
FLASH_ErasePage(sector_addr*sector_size+BASE_ADDR); //擦除整扇区,flash写入之前一定要检查该扇区是否被擦除,只有被擦了才能写入,库里有两种擦除,一种是擦除一个区,一种是擦除整页。
for(i=0;i<num;i++)
{
FLASH_ProgramWord(addr, (u32)buf[i]); //写一个字
addr+=4; //每次写入32位数据,共4个字节。下次写到4个字节后的地址
}
FLASH_Lock();//上锁,向两个KEY中写入键值,类似于开锁,用来保护flash防止误操作。
return 1;
}