小松的STM32教程(14)——内部flash模拟eeprom

小松的STM32教程(14)——内部flash模拟eeprom,第1张

预备 ICP和IAP 存储器地址映射(注意RCT6只有128页)
  • 存储器大小:我们说的flash大小,指的是主存储器的大小
  • 信息块:
    • 启动程序代码,用于存储ST自带的启动程序,用于串口下载代码
    • 用户选择字节一般用于配置读保护和写保护等功能
  • 接口寄存器:用于配置flash读写等
B0和B1

在开发板上有两个跳线帽,可以用来切换B0(Boot0)和B1(Boot1),模式如下

B0B1描述
GNDGND从0x8000000运行(主存储器基地址)
3.3GND从信息块运行
flash写
  1. 只有解除写保护才能 *** 作相关寄存器(检查FLASH_CR的LOCK是否解锁)
  2. flash编程时确保没有其他正在进行的编程 *** 作(检查FLASH_SR的BSY位)
  3. 每次编程必须写入半字,否则会出错(设置FLASH_CR寄存器的PG位为1)
  4. flash编程时,写入地址的flash必须是被擦除的,否则无法写入
flash页擦除
  1. 设置CR寄存器的PER为1
  2. 配置AR寄存器选择擦除页
  3. 配置CR寄存器的STRT为1
  4. 等待SR的BSY为0
  5. 读出验证
整片擦除
  1. 设置CR的MER为1
  2. 设置CR的STAT为1
  3. 等待SR的BSY为0
  4. 读出验证
寄存器(具体的参看flash编程手册)
  1. KEYR寄存器写入FPEC解锁键
  2. CR寄存器:锁,开始等
  3. SR寄存器:检查忙
  4. AR寄存器:写地址
flash *** 作常用库函数

stm32flash.h
#ifndef __STMFLASH_H__
#define __STMFLASH_H__
#include "sys.h"  

#define STM32_FLASH_SIZE 256 	 		//定义flash大小
#define STM32_FLASH_WREN 1              //允许写
#define STM32_FLASH_BASE 0x08000000 	//STM32 FLASH基地址

u16 STMFLASH_ReadHalfWord(u32 faddr);		  //读半字(2字节)
void STMFLASH_WriteLenByte(u32 WriteAddr,u32 DataToWrite,u16 Len);	//ָ写指定长度字节
u32 STMFLASH_ReadLenByte(u32 ReadAddr,u16 Len);						//ָ读给定长度字节
void STMFLASH_Write(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite);		//写
void STMFLASH_Read(u32 ReadAddr,u16 *pBuffer,u16 NumToRead);   		//读

//�����
void Test_Write(u32 WriteAddr,u16 WriteData);								   
#endif


stm32flash.c
#include "stmflash.h"
#include "delay.h"

u16 STMFLASH_ReadHalfWord(u32 faddr)//给地址读取半字
{
	return *(vu16*)faddr; 
}

#if STM32_FLASH_WREN

void STMFLASH_Write_NoCheck(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite)//进行不检查的写
{ 			 		 
	u16 i;
	for(i=0;i<NumToWrite;i++)//写numtowrite个半字
	{
		FLASH_ProgramHalfWord(WriteAddr,pBuffer[i]);
	    WriteAddr+=2;//写地址+2(由于是半字)
	}  
} 

#if STM32_FLASH_SIZE<256
#define STM_SECTOR_SIZE 1024 //�ֽ�
#else 
#define STM_SECTOR_SIZE	2048
#endif		 

u16 STMFLASH_BUF[STM_SECTOR_SIZE/2];

void STMFLASH_Write(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite)//写
{
	u32 secpos;
	u16 secoff;
	u16 secremain;
 	u16 i;    
	u32 offaddr;

	if(WriteAddr<STM32_FLASH_BASE||(WriteAddr>=(STM32_FLASH_BASE+1024*STM32_FLASH_SIZE)))return;//在可写空间之外写
	FLASH_Unlock();	//解锁flash
	offaddr=WriteAddr-STM32_FLASH_BASE;//计算偏移地址
	secpos=offaddr/STM_SECTOR_SIZE;	//计算所在sector的地址
	secoff=(offaddr%STM_SECTOR_SIZE)/2;	//计算sector的偏移量
	secremain=STM_SECTOR_SIZE/2-secoff;	//计算sector-sector偏移量

	if(NumToWrite<=secremain)secremain=NumToWrite;
	while(1) 
	{	
		STMFLASH_Read(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE,STMFLASH_BUF,STM_SECTOR_SIZE/2);
		for(i=0;i<secremain;i++)
		{
			if(STMFLASH_BUF[secoff+i]!=0XFFFF)break;
		}

		if(i<secremain)
		{
			FLASH_ErasePage(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE);//擦除页
			for(i=0;i<secremain;i++)
			{
				STMFLASH_BUF[i+secoff]=pBuffer[i];	  //写
			}
			STMFLASH_Write_NoCheck(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE,STMFLASH_BUF,STM_SECTOR_SIZE/2);
		}else STMFLASH_Write_NoCheck(WriteAddr,pBuffer,secremain);
		if(NumToWrite==secremain)break;
		else
		{
			secpos++;
			secoff=0;
		   	pBuffer+=secremain;
			WriteAddr+=secremain;
		   	NumToWrite-=secremain;
			if(NumToWrite>(STM_SECTOR_SIZE/2))secremain=STM_SECTOR_SIZE/2;
			else secremain=NumToWrite;
		}	 
	};	
	FLASH_Lock();
}
#endif


void STMFLASH_Read(u32 ReadAddr,u16 *pBuffer,u16 NumToRead)//将数据读到缓存数组里
{
	u16 i;
	for(i=0;i<NumToRead;i++)
	{
		pBuffer[i]=STMFLASH_ReadHalfWord(ReadAddr);
		ReadAddr+=2;
	}
}



void Test_Write(u32 WriteAddr,u16 WriteData)//测试写一个半字
{
	STMFLASH_Write(WriteAddr,&WriteData,1);
}





主函数调用
#include "delay.h"
#include "sys.h"
#include "key.h"
#include "oled.h"
#include "stmflash.h"
const u8 TEXT_Buffer[]={"STM32 FLASH TEST"};
#define SIZE sizeof(TEXT_Buffer)	 	//数组长度
#define FLASH_SAVE_ADDR  0X08020000 	//设置FLASH 保存地址(必须为偶数,且其值要大于本代码所占用FLASH的大小+0X08000000)
 int main(void)
 {
	u8 datatemp[SIZE];
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2
	delay_init();	    	 //延时函数初始化
 	KEY_Init();				//按键初始化
 	OLED_Init();

	while(1)
	{
		if(KEY0)
		{
			OLED_Refresh();
				//OLED_Refresh();
				OLED_ShowString(0,0,"start write",16,1);
				STMFLASH_Write(FLASH_SAVE_ADDR,(u16*)TEXT_Buffer,SIZE);
				OLED_ShowString(0,16,"write finished",16,1);
				OLED_ShowString(0,32,"                ",16,1);
				OLED_Refresh();

		}
		if(!KEY0){
				OLED_Refresh();
				OLED_ShowString(0,0,"start read ",16,1);
				STMFLASH_Read(FLASH_SAVE_ADDR,(u16*)datatemp,SIZE);
				OLED_ShowString(0,16,"read data is    ",16,1);
				OLED_ShowString(0,32,datatemp,16,1);
				OLED_Refresh();
			}
	}
}
学习目标 作业
  1. 阅读flash库

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/707199.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-24
下一篇 2022-04-24

发表评论

登录后才能评论

评论列表(0条)

保存