stm32入门学习16-闪存

(一)闪存

在之前的学习中,已经学习过了W25Q64这个外挂闪存,在stm32内部也有一块闪存,其主要用于存放我们编译的代码,如果我们需要一些掉电不丢失的数据,但是又懒得外挂一块闪存,就可以把少量数据写入stm32内部的闪存中,其操作与写入外设闪存的操作基本相同,且有库函数封装,使用的函数也很简单

void FLASH_Unlock(void);
// 解锁 FLASH 编写擦除控制器

void FLASH_Lock(void);
// 锁定 FLASH 编写擦除控制器

FLASH_Status FLASH_ErasePage(uint32_t Page_Address);
// 擦除一页
 
FLASH_Status FLASH_EraseAllPages(void);
// 擦除所有

FLASH_Status FLASH_ProgramWord(uint32_t Address, uint32_t Data);
// 写入32位数据

FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data);
// 写入16位数据

(二)读取、写入、擦除

(1)读取

对于读取闪存,没有封装的库函数用于读取,因为要读取只要给定指针即可,通过解引用一个地址指针则可以读取任意位置任意大小的数据

uint32_t flash_read_word(uint32_t address)
{
	return *(uint32_t*)address;
}

uint16_t flash_read_halfword(uint32_t address)
{
	return *(uint16_t*)address;
}

uint8_t flash_read_byte(uint32_t address)
{
	return *(uint8_t*)address;
}

这里分别读取32比特(1字)、16比特(半字)、8比特(1字节),接收的是一个32位的无符号整形数字,里面存放要读取的地址,随后强转换为不同数据大小的指针,最后解引用读取该指针地址下的数据

(2)写入

写入只需要调用库函数即可,写入之前要先解锁编写擦除控制器,写完后要对编写擦除控制器上锁,stm还对写入等操作进行了加锁,还有写入等待事件等问题,但是这些封装的库函数都帮我们完成了

void flash_write_half_word(uint32_t address, uint16_t inf)
{
	FLASH_Unlock();
	FLASH_ProgramHalfWord(address, inf);
	FLASH_Lock();
}

void flash_write_word(uint32_t address, uint32_t inf)
{
	FLASH_Unlock();
	FLASH_ProgramWord(address, inf);
	FLASH_Lock();
}

这里分别写入16位数据和32位数据

(3)擦除

擦除有所有擦除和按页擦除,同样,擦除操作之前要解锁编写擦除控制器,擦除完成后要对其上锁

void flash_erase_page(uint32_t address)
{
	FLASH_Unlock();
	FLASH_ErasePage(address);
	FLASH_Lock();
}

void flash_erase_all()
{
	FLASH_Unlock();
	FLASH_EraseAllPages();
	FLASH_Lock();
}

(三)不覆盖写入

我们在写入之前必须执行擦除操作,如果我们在上电后写入,有可能把上次存储的掉电不丢失的数据擦除,我们可以在上电后进行一次初始化,把里面的数据都搬到数据里,然后再执行写入等操作

这里只操作闪存中的最后一页,将其最开始的16位作为标志位,判断之前是否写过,0x5555即原本有数据,0xFFFF为无数据

#define last_page 0x0801FC00

uint16_t information[128] = {0};

void op_flash_init()
{
	uint16_t i;
	if (flash_read_halfword(last_page) == 0x5555)
	{
		for (i = 0; i < 128; i++)
		{
			information[i] = flash_read_halfword(last_page+i*2);
		}
	}
}

 在写入数据之前,把标志位置为0x5555,随后擦除页,写入数据所有数据,我们在主程序中想要修改数据可以直接修改数组即可

void op_write_halfword()
{
	uint16_t i;
	information[0] = 0x5555;
	flash_erase_page(last_page);
	for (i = 0; i < 128; i++)
	{
		flash_write_half_word(last_page + i*2, information[i]);
	}
}

再写一个读写函数,方便读取最后一页的第几个16位数据

uint16_t op_read_half_word(int place)
{
	int i;
	for (i = 0; i < 128; i++)
	{
		information[i] = flash_read_halfword(last_page+i*2);
	}
	return information[place];
}

 这样我们就可以在主函数里先调用初始化函数,然后可以写入要写的数据,这样即使掉电也不会丢失

(四)读取芯片ID号

对于stm32芯片,每个芯片都有独一无二的芯片ID号,称为产品的唯一身份标识,总共有96位数据,其基地址为0x1FFF F7E8,可以通过这个地址加适当的地址偏移来读取芯片ID,芯片的ID有这些用途

这里就先读取芯片ID来显示一下

读取芯片ID和读取闪存一样,只要一个指针即可

#include "stm32f10x.h"                  // Device header
#include "OLED.h"

#define base_loc 0x1FFFF7E8

int main()
{
	OLED_Init();
	OLED_ShowHexNum(1, 1, *(uint16_t*)base_loc, 4);
	OLED_ShowHexNum(2, 1, *(uint16_t*)(base_loc+0x02), 4);
	OLED_ShowHexNum(3, 1, *(uint32_t*)(base_loc+0x04), 8);
	OLED_ShowHexNum(4, 1, *(uint32_t*)(base_loc+0x08), 8);
	while (1)
	{
		
	}
	return 0;
}

这样我们就可以读取自己stm32的身份标识了

(五)总结

通过读写stm32的闪存部分和读取芯片的身份标识,我们了解了读写stm32闪存部分的基本操作和方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值