您的位置:首页 > 其它

STM32小白入门(第14天)-------Flash

2018-04-06 15:33 274 查看
一、Flash概述    闪存(Flash Memory)是一种长寿命的非易失性(在断电情况下仍能保持所存储的数据信息)的存储器。用途:SD卡、固态硬盘、芯片内存存储单元存储代码。




二、内部FLASH特征
1、以分区形式进行规划,配置数据最好从最后扇区进行操作,防止覆盖扇区0的代码。



2、写入数据之前得先擦除数据,类似与读书时的黑板原理。
    


思考题1:擦除完之后,扇区里面所有的数据是什么?答:所有的数据都是为0xFF,所有bit位都是1. 

思考题2:假如说现在已经擦除完扇区,先写入了1个字节,然后在下一个偏移地址再次写入新的字节是否在需要擦除扇区?答案:不需要的。思考题3:假如说现在已经擦除完扇区,先写了1个字节,然后在同一个地址再次写入新的字节是否在需要擦除扇区?答案:需要进行擦除!例子,已经写入数据为0x12345678,然后再写入新的数据为0x1111111,最后得到的数据居然是0x101010.


#define FLASH_USER_START_ADDR ADDR_FLASH_SECTOR_6 /* Start address of user Flash area */
#define FLASH_USER_END_ADDR ADDR_FLASH_SECTOR_7 /* End address of user Flash area */

/* Base address of the Flash sectors */
#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) /* Base address of Sector 0, 16 Kbytes */
#define ADDR_FLASH_SECTOR_1 ((uint32_t)0x08004000) /* Base address of Sector 1, 16 Kbytes */
#define ADDR_FLASH_SECTOR_2 ((uint32_t)0x08008000) /* Base address of Sector 2, 16 Kbytes */
#define ADDR_FLASH_SECTOR_3 ((uint32_t)0x0800C000) /* Base address of Sector 3, 16 Kbytes */
#define ADDR_FLASH_SECTOR_4 ((uint32_t)0x08010000) /* Base address of Sector 4, 64 Kbytes */
#define ADDR_FLASH_SECTOR_5 ((uint32_t)0x08020000) /* Base address of Sector 5, 128 Kbytes */
#define ADDR_FLASH_SECTOR_6 ((uint32_t)0x08040000) /* Base address of Sector 6, 128 Kbytes */
#define ADDR_FLASH_SECTOR_7 ((uint32_t)0x08060000) /* Base address of Sector 7, 128 Kbytes */
#define ADDR_FLASH_SECTOR_8 ((uint32_t)0x08080000) /* Base address of Sector 8, 128 Kbytes */
#define ADDR_FLASH_SECTOR_9 ((uint32_t)0x080A0000) /* Base address of Sector 9, 128 Kbytes */
#define ADDR_FLASH_SECTOR_10 ((uint32_t)0x080C0000) /* Base address of Sector 10, 128 Kbytes */
#define ADDR_FLASH_SECTOR_11 ((uint32_t)0x080E0000) /* Base address of Sector 11, 128 Kbytes */

uint32_t uwStartSector = 0;
uint32_t uwEndSector = 0;
uint32_t uwAddress = 0;
uint32_t uwSectorCounter = 0;

__IO uint32_t uwData32 = 0;

//获取所在扇区
static uint32_t GetSector(uint32_t Address)
{
uint32_t sector = 0;

if((Address < ADDR_FLASH_SECTOR_1) && (Address >= ADDR_FLASH_SECTOR_0))
{
sector = FLASH_Sector_0;
}
else if((Address < ADDR_FLASH_SECTOR_2) && (Address >= ADDR_FLASH_SECTOR_1))
{
sector = FLASH_Sector_1;
}
else if((Address < ADDR_FLASH_SECTOR_3) && (Address >= ADDR_FLASH_SECTOR_2))
{
sector = FLASH_Sector_2;
}
else if((Address < ADDR_FLASH_SECTOR_4) && (Address >= ADDR_FLASH_SECTOR_3))
{
sector = FLASH_Sector_3;
}
else if((Address < ADDR_FLASH_SECTOR_5) && (Address >= ADDR_FLASH_SECTOR_4))
{
sector = FLASH_Sector_4;
}
else if((Address < ADDR_FLASH_SECTOR_6) && (Address >= ADDR_FLASH_SECTOR_5))
{
sector = FLASH_Sector_5;
}
else if((Address < ADDR_FLASH_SECTOR_7) && (Address >= ADDR_FLASH_SECTOR_6))
{
sector = FLASH_Sector_6;
}
else if((Address < ADDR_FLASH_SECTOR_8) && (Address >= ADDR_FLASH_SECTOR_7))
{
sector = FLASH_Sector_7;
}
else if((Address < ADDR_FLASH_SECTOR_9) && (Address >= ADDR_FLASH_SECTOR_8))
{
sector = FLASH_Sector_8;
}
else if((Address < ADDR_FLASH_SECTOR_10) && (Address >= ADDR_FLASH_SECTOR_9))
{
sector = FLASH_Sector_9;
}
else if((Address < ADDR_FLASH_SECTOR_11) && (Address >= ADDR_FLASH_SECTOR_10))
{
sector = FLASH_Sector_10;
}

else/*(Address < FLASH_END_ADDR) && (Address >= ADDR_FLASH_SECTOR_11))*/
{
sector = FLASH_Sector_11;
}

return sector;
}

//擦除扇区
void FLASH_Eraze(void)
{
//解锁闪存
/* Enable the flash control register access ,使能闪存控制寄存器的访问*/
FLASH_Unlock();

/* Clear pending flags (if any) ,清空所有相关的标志位*/
FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR |
FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR);

/* Get the number of the start and end sectors,将扇区地址转换为扇区号 */
uwStartSector = GetSector(FLASH_USER_START_ADDR); //起始扇区为扇区6
uwEndSector = GetSector(FLASH_USER_END_ADDR); //结束扇区为扇区7

/* start the erase operation */
uwSectorCounter = uwStartSector;

//判断擦除是否已经到达结束扇区
while (uwSectorCounter <= uwEndSector)
{
/* Device voltage range supposed to be [2.7V to 3.6V], the operation will
be done by word
像手机升级的一样,必须保证电压稳定,同时看到如果擦除扇区,供电的电压必须为2.7V~3.6V
*/
if (FLASH_EraseSector(uwSectorCounter, VoltageRange_3) != FLASH_COMPLETE)
{
//擦除失败
printf("FLASH_EraseSector error\r\n");
while (1);

}
/* jump to the next sector ,切换到下一个扇区*/
if (uwSectorCounter == FLASH_Sector_11)
{
uwSectorCounter += 40;
}
else
{
uwSectorCounter += 8;
}
}
}

void FLASH_Wirte_Data(uint32_t data)
{
//对对应的地址写入数据,从扇区6开始写入数据
uwAddress = FLASH_USER_START_ADDR; //扇区6的起始地址

//判断当前的写入地址是否已经到达结束扇区地址
while (uwAddress < FLASH_USER_END_ADDR)
{
//对对应的地址写入4字节数据,全部数据位0x12345678
if (FLASH_ProgramWord(uwAddress, data) == FLASH_COMPLETE)
{
//写入成功后,地址偏移4个字节
uwAddress = uwAddress + 4;
}
else
{
//写入数据出问题,则将错误的地址进行打印
printf("FLASH_ProgramWord at %x error\r\n",uwAddress);
while (1);

}
}

//写入完毕后,则进行锁定闪存,不允许任何的修改
FLASH_Lock();
}

void FLASH_Read_Data(void)
{
//从起始扇区开始读取
uwAddress = FLASH_USER_START_ADDR;

//判断读取数据的地址是否已经到达结束扇区
while (uwAddress <
a7a6
FLASH_USER_END_ADDR)
{
//读取数据
uwData32 = *(__IO uint32_t*)uwAddress;

if (uwData32 != 0x12345678)
{
printf("flash read at %X,val=%X\r\n",uwAddress,uwData32);
}
//地址偏移4个字节
uwAddress = uwAddress + 4;
}
}

//在6扇区记录
void FLASH_Record(uint32_t data, uint32_t record_count)
{
//对对应的地址写入数据,从扇区6开始写入数据
//uwAddress = FLASH_USER_START_ADDR; //扇区6的起始地址

//一系列的字节数40
uwAddress = FLASH_USER_START_ADDR + uwRecordCounter + record_count*40;

//判断当前的写入地址是否已经到达结束扇区地址
if(uwAddress < FLASH_USER_END_ADDR)
{
uwRecordCounter = uwRecordCounter + 4;

//对对应的地址写入4字节数据
if (FLASH_ProgramWord(uwAddress, data) != FLASH_COMPLETE)
{
//写入数据出问题,则将错误的地址进行打印
printf("FLASH_ProgramWord at %x error\r\n",uwAddress);
while (1);
}

while(uwRecordCounter == 40)
{
uwRecordCounter = 0;
}
}

//写入完毕后,则进行锁定闪存,不允许任何的修改
//FLASH_Lock();
}

//读取出记录
void Record_DataRead(uint32_t record_count)
{
uint32_t Read_buf[10] = {0};
uint32_t Read_buf_count = 0;
uint32_t times = 0;

//从起始扇区开始读取
uwAddress = FLASH_USER_START_ADDR;

//判断读取数据的地址是否已经count条记录 每条记录40字节
while (uwAddress < (FLASH_USER_START_ADDR+record_count*40))
{
for(Read_buf_count = 0; Read_buf_count < 10; Read_buf_count++)
{
//读取数据
Read_buf[Read_buf_count] = *(__IO uint32_t*)uwAddress;

//地址偏移4字节
uwAddress = uwAddress + 4;
}

times++;

//格式:[001]2017/10/14 9:40:12 Temp=30.0 Humi=92.0
printf("[%03d]20%x/%x/%x %x:%x:%x Temp=%d.%d℃ Humi=%d.%d\r\n",times,Read_buf[0],Read_buf[1],
Read_buf[2],Read_buf[3],Read_buf[4],
Read_buf[5],Read_buf[6],Read_buf[7],
Read_buf[8],Read_buf[9]);
}

printf("读取完毕\r\n");

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: