STM32数据存储学习
做项目的过程中,发现自己要先定义两个很大的数组然后对该两组数据进行处理,但发现尤其是对于占据4个字节的float类型,一个几千大小的数组就让STM32的存储不足了,因此下面,一起探讨一下怎么办吧!(本人用的开发板是STM32F103ZET6战舰版)
1. STM32存储空间简介
首先说明一下我用的这块芯片的空间大小,RAM64K,FLASH大小为512K。其实这样一看对于一个读写而言,64K的大小貌似很充足,毕竟一个float量才占用4字节,这对于64000这个数字的确不算什么,但我要定义的是几千个大小的数组呀,而且是为了跑算法用的,而且算法中也要开差不多的数组,当然开上几个数组估计一兆都不够咱霍霍的,这个问题会在2.3中进行解答,现在先展开一下关于大数组安置的办法介绍。
这个图片可以在Keil里面的编译设置中的Target看到,左边第一个框代表着存储的起始位置,后边的Size代表着可以利用的大小,80000(16进制)对应的正好是我这块芯片的512K,右边的话也是相同的配置,可以看到大小的确差了八倍。有时候系统提示运行空间不足,如果更改这边的Size数据则会让程序正常编译,但这种情况却是改了编译环境但没能改变芯片实际的存储能力。既然64K不足,那么就把眼光放在FLASH上面:
FLASH主要包括主存储器、信息块和闪存存储器接口寄存器等三部分,主存储器用来放代码和const常量,所以在编程的时候,很多数据是一开始定好了且不会动的,可以用const进行声明。信息块主要是程序气动和写保护等操作,我这用不到便不多介绍。对于寄存器那肯定就是控制作用咯。
对于片外RAM的存储介绍统一放在2.3部分介绍。
2. 大数组定义的方案
下面介绍个人认为可行的两种方案,同时对数组的定义进行改善实现动态分配内存。其他的方法节省空间上我能想到的就是完善程序,增加常量并且增加指针等了。
2.1 FLASH存储并读取
对于FLASH的写入,STM32有集成的库函数我们可以直接使用,我们可以大体知道一下过程:
解锁->校验并擦除扇区->写入扇区->地址和指针偏移->写入完毕并上锁。
对于这样的一个流程其实也不是很复杂,主要是对扇区的数据读出并清理略显复杂,因为我们更偏重于应用,所以只需要知道以下的函数即可:
void STMFLASH_Write(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite)//写入参数
void STMFLASH_Read(u32 ReadAddr,u16 *pBuffer,u16 NumToRead) //读出参数
//第一个参数对应的写入的起始地址;第二个参数是传入数据的指针;第三个参数是传输的半字数。
2.2 动态数组的建立
话不多说,直接上代码:
int* ty1 = (int*)malloc(lookup*sizeof(int*));
ty1是数组起始位置,这也就是一个指针,malloc函数意味着动态分配内存,lookup是我定义的数组的长度,比如一个一维的4000个数据的数组,每个数据类型为u16,那么这就相当于开了4000个u16数据的数组地址,ty1返回的值是第一个数据的存储位置,当我们不用了这个数组的时候,便可以通过这个函数来进行空间释放:
free(ty1);
通过这个动态数组的建立可以避免跑算法的时候建立一个个大数组在RAM里面。
2.3 片外RAM的使用
用FLASH还是需要谨慎,毕竟是个存储程序和其他外设源数据的地方,所以探索一下另一个方法,就是片外的RAM,用片外的RAM也不用担心FLASH的操作不小心了。我用的这块板子是战舰版,有 XM8A51216芯片,大小为一兆个字节:
除了相应的地址线和数据线外,还包括:CEn 是芯片使能信号,低电平有效;OEn 是输出使能信号,低电平有效; WEn 是写使能信号,低电平有效; BLEn 和 BHEn 分别是高字节控制和低字节控制信号;这个芯片直接接在了FSMC上,可以通过32官方的库查看到相关原理图。
关于片外RAM的设置,首先肯定还是设置时钟,然后既然是FSMC的使用,那么肯定要设置FSMC的BANK设计,然后使能就可以了。
FSMC_SRAM_Init();//使能SRAM
FSMC_SRAM_WriteBuffer(u8* pBuffer,u32 WriteAddr,u32 n);//写入指定字节数的写入操作
FSMC_SRAM_ReadBuffer(u8* pBuffer,u32 ReadAddr,u32 n);//读出指定字节数的读出操作
参考文献:
《STM32F1开发指南库函数版本》