#include "stm32f10x.h"
/* 定义Flash存储器的页大小和起始地址 */
#ifdef STM32F10X_LD
#define FLASH_PAGE_SIZE (uint32_t)0x400
#define FLASH_START_ADDR (uint32_t)0x08000000
#elif defined(STM32F10X_MD) || defined(STM32F10X_HD)
#define FLASH_PAGE_SIZE (uint32_t)0x800
#define FLASH_START_ADDR (uint32_t)0x08000000
#elif defined(STM32F10X_CL)
#define FLASH_PAGE_SIZE (uint32_t)0x800
#define FLASH_START_ADDR (uint32_t)0x08008000
#endif
/*
* 将数据写入Flash存储器
* address:Flash存储器地址
* data:存储要写入Flash存储器的数据的数组的指针
* len:数据数组的长度(数据项的数量)
* 返回值:0表示成功,1表示失败
*/
uint32_t Flash_WriteData(uint32_t address, uint32_t* data, uint32_t len) {
FLASH_Status flashStatus = FLASH_COMPLETE;
uint32_t pageAddress = address;
uint32_t pageIndex = 0;
uint32_t pageOffset = 0;
/* 解锁Flash */
FLASH_Unlock();
/* 擦除一页,将地址和指针设为起始地址 */
pageIndex = (address - FLASH_START_ADDR) / FLASH_PAGE_SIZE;
pageAddress = FLASH_START_ADDR + pageIndex * FLASH_PAGE_SIZE;
flashStatus = FLASH_ErasePage(pageAddress);
while(flashStatus != FLASH_COMPLETE) {
FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
flashStatus = FLASH_ErasePage(pageAddress);
}
pageOffset = address - pageAddress;
/* 写入数据 */
for(uint32_t i = 0; i < len; i++) {
uint32_t value = data[i];
flashStatus = FLASH_ProgramWord(address, value);
if(flashStatus != FLASH_COMPLETE) {
FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
FLASH_Lock();
return 1;
}
address += 4;
pageOffset += 4;
/* 如果当前页写满了,则需要刷新下一页 */
if(pageOffset >= FLASH_PAGE_SIZE) {
pageOffset = 0;
pageIndex++;
pageAddress = FLASH_START_ADDR + pageIndex * FLASH_PAGE_SIZE;
flashStatus = FLASH_ErasePage(pageAddress);
while(flashStatus != FLASH_COMPLETE) {
FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
flashStatus = FLASH_ErasePage(pageAddress);
}
}
}
/* 锁定Flash */
FLASH_Lock();
/* 成功 */
return 0;
}
int main(void) {
uint32_t address = FLASH_START_ADDR;
uint32_t data[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
uint32_t len = sizeof(data) / sizeof(data[0]);
/* 将数据写入Flash存储器 */
uint32_t result = Flash_WriteData(address, data, len);
/* 如果写入成功,则读取数据 */
if(result == 0) {
uint32_t* ptr = (uint32_t*)FLASH_START_ADDR;
for(uint32_t i = 0; i < len; i++) {
uint32_t value = *ptr;
ptr++;
}
}
while(1) {
}
}
在这个例子中,我们使用了条件编译指令来自动选择不同型号的单片机所需的Flash存储器的页大小和起始地址。这样可以在不修改代码的情况下,将此代码移植到不同型号的单片机中,实现不同内存大小的存储器操作功能。
仅用于学习交流,不足之处请留言指正。交流优化