历史上的今天
返回首页

历史上的今天

今天是:2024年12月20日(星期五)

正在发生

2021年12月20日 | STM32嵌入式FLASH擦除与写入

2021-12-20 来源:eefocus

嵌入式Flash

Flash具有以下主要特性:

1.对于STM32F40x和 STM32F41x,容量高达1 MB;对于STM32F42x和STM32F43x,容量高达2MB。128位宽数据读取---------意思就是128/8=16(字节)


2.字节、半字、字和双字数据写入----对应一个字节,两个字节,四个字节,八个字节。(推荐以字读取和写入,即四个字节,刚好32位)


3.扇区擦除与全部擦除

扇区擦除就像你删除电脑的C盘内容,不删除D-F盘内容一样。

扇区擦除完的数据都为0XFF


4.存储器组织结构Flash 结构如下:

-主存储器块,分为4个16 KB扇区、1个64 KB扇区和7个128 KB扇区-系统存储器,器件在系统存储器自举模式下从该存储器启动


编程的时候,要注意写入数据是在哪个扇区,而且要知道扇区地址,不能够超过芯片的FLASH大小,例如你是512KB的,最多就到扇区7。


512字节OTP (一次性可编程,once time program),用于存储用户数据。OTP区域还有16个额外字节,用于锁定对应的OTP数据块。选项字节,用于配置读写保护、BOR级别、软件/硬件看门狗以及器件处于待机或停止模式下的复位。低功耗模式(有关详细信息,请参见参考手册的“电源控制(PWR)”部分)


STM32片内自带SRAM和FLASH,FLASH是用来存储程序的,SRAM是用来存储程序运行中的中间变量,通常不同型号的STM32的SRAM和FLASH大小是不相同的。例如STM32L431RCT6,SRAM容量大小为64KB,闪存FLASH的容量大小为256KB。


库函数的识别方法:硬件开头+大小写结合,ucos系统的代码量可能有100kb。


编程(根据固件库手册的例子进行模仿编写)

(1)解锁保护机制

(2)清空标志位

(3)获取扇区的起始地址和末地址(用于擦除扇区)

(4)使用循环,擦除扇区

(5)写入数据(一定要先擦除,才能写入数据)

(6)读取数据,验证是否正确写入

(7)锁定FLASH,进行保护


#include "stm32f4xx.h"

#include "stm32f4xx_gpio.h"

#include "stm32f4xx_rcc.h"

#include "stm32f4xx_usart.h"

#include "stdio.h"


static GPIO_InitTypeDef  GPIO_InitStructure;

static USART_InitTypeDef USART_InitStructure;

static NVIC_InitTypeDef NVIC_InitStructure;



//重定义fputc函数 

int fputc(int ch, FILE *f)

{

USART_SendData(USART1,ch);

while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);  

return ch;

}   


void delay_us(uint32_t nus)

{

uint32_t temp;      

SysTick->LOAD =SystemCoreClock/8/1000000*nus; //时间加载    

SysTick->VAL  =0x00;        //清空计数器

SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //使能滴答定时器开始倒数  

do

{

temp=SysTick->CTRL;

}while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达   

SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器

SysTick->VAL =0X00;        //清空计数器 

}


void delay_ms(uint16_t nms)

{     

uint32_t temp;    

SysTick->LOAD=SystemCoreClock/8/1000*nms; //时间加载(SysTick->LOAD为24bit)

SysTick->VAL =0x00;            //清空计数器

SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;    //能滴答定时器开始倒数 

do

{

temp=SysTick->CTRL;

}while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达   

SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;    //关闭计数器

SysTick->VAL =0X00;        //清空计数器       




void USART1_Init(uint32_t baud)

{

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); //使能USART1时钟

 

//串口1对应引脚复用映射

GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); //GPIOA9复用为USART1

GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //GPIOA10复用为USART1

//USART1端口配置

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9与GPIOA10

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHz

GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉

GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA9,PA10


//USART1 初始化设置

USART_InitStructure.USART_BaudRate = baud; //波特率设置

USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长为8位数据格式

USART_InitStructure.USART_StopBits = USART_StopBits_1; //一个停止位

USART_InitStructure.USART_Parity = USART_Parity_No; //无奇偶校验位

USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件数据流控制

USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式

USART_Init(USART1, &USART_InitStructure); //初始化串口1

USART_Cmd(USART1, ENABLE);  //使能串口1 

USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启相关中断


//Usart1 NVIC 配置

NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //串口1中断通道

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3; //抢占优先级3

NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; //子优先级3

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能

NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器

}



uint32_t uwStartSector = 0;

uint32_t uwEndSector = 0;

uint32_t uwAddress = 0;

uint32_t uwSectorCounter = 0;


__IO uint32_t uwData32 = 0;

__IO uint32_t uwMemoryProgramStatus = 0;


//这些地址从F4中文手册的第三章FLASH可以查到

#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 */


#define ADDR_FLASH_SECTOR_12     ((uint32_t)0x08100000) /* Base address of Sector 12, 16 Kbytes  */

#define ADDR_FLASH_SECTOR_13     ((uint32_t)0x08104000) /* Base address of Sector 13, 16 Kbytes  */

#define ADDR_FLASH_SECTOR_14     ((uint32_t)0x08108000) /* Base address of Sector 14, 16 Kbytes  */

#define ADDR_FLASH_SECTOR_15     ((uint32_t)0x0810C000) /* Base address of Sector 15, 16 Kbytes  */

#define ADDR_FLASH_SECTOR_16     ((uint32_t)0x08110000) /* Base address of Sector 16, 64 Kbytes  */

#define ADDR_FLASH_SECTOR_17     ((uint32_t)0x08120000) /* Base address of Sector 17, 128 Kbytes */

#define ADDR_FLASH_SECTOR_18     ((uint32_t)0x08140000) /* Base address of Sector 18, 128 Kbytes */

#define ADDR_FLASH_SECTOR_19     ((uint32_t)0x08160000) /* Base address of Sector 19, 128 Kbytes */

#define ADDR_FLASH_SECTOR_20     ((uint32_t)0x08180000) /* Base address of Sector 20, 128 Kbytes */

#define ADDR_FLASH_SECTOR_21     ((uint32_t)0x081A0000) /* Base address of Sector 21, 128 Kbytes */

#define ADDR_FLASH_SECTOR_22     ((uint32_t)0x081C0000) /* Base address of Sector 22, 128 Kbytes */

#define ADDR_FLASH_SECTOR_23     ((uint32_t)0x081E0000) /* Base address of Sector 23, 128 Kbytes */


//这里就以6起始,7结束

#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 */


//获取扇区地址

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 if((Address < ADDR_FLASH_SECTOR_12) && (Address >= ADDR_FLASH_SECTOR_11))

{

sector = FLASH_Sector_11;  

}


else if((Address < ADDR_FLASH_SECTOR_13) && (Address >= ADDR_FLASH_SECTOR_12))

{

sector = FLASH_Sector_12;  

}

else if((Address < ADDR_FLASH_SECTOR_14) && (Address >= ADDR_FLASH_SECTOR_13))

{

sector = FLASH_Sector_13;  

}

else if((Address < ADDR_FLASH_SECTOR_15) && (Address >= ADDR_FLASH_SECTOR_14))

{

sector = FLASH_Sector_14;  

}

else if((Address < ADDR_FLASH_SECTOR_16) && (Address >= ADDR_FLASH_SECTOR_15))

{

sector = FLASH_Sector_15;  

}

else if((Address < ADDR_FLASH_SECTOR_17) && (Address >= ADDR_FLASH_SECTOR_16))

{

sector = FLASH_Sector_16;  

}

else if((Address < ADDR_FLASH_SECTOR_18) && (Address >= ADDR_FLASH_SECTOR_17))

{

sector = FLASH_Sector_17;  

}

else if((Address < ADDR_FLASH_SECTOR_19) && (Address >= ADDR_FLASH_SECTOR_18))

推荐阅读

史海拾趣

Excelitas公司的发展小趣事

在当今社会,绿色环保和可持续发展已成为企业发展的重要趋势。Excelitas公司积极响应这一趋势,致力于研发和生产绿色环保的产品。通过采用环保材料和生产工艺,公司成功降低了产品的能耗和排放。同时,公司还积极参与环保公益活动,倡导绿色生活方式。这些举措不仅提升了公司的品牌形象,还为社会的可持续发展做出了积极贡献。

请注意,以上故事仅为基于假设和一般行业趋势构建的框架性描述,并不代表Excelitas公司的实际发展历程。如有需要,建议您查阅相关官方资料或新闻报道以获取更准确的信息。

DINTEK公司的发展小趣事

Excelitas公司自成立以来,一直致力于光电技术的研发与创新。在某次关键的技术突破中,公司成功研发出一种新型高效能LED灯,这种灯在紫外光固化领域具有显著优势。这一技术突破不仅为公司赢得了市场份额,还确立了Excelitas在光电领域的领先地位。公司随后围绕这一技术,推出了一系列相关产品,进一步巩固了市场地位。

Freeport Resources Enterprises Corp公司的发展小趣事

为了提升在电子材料领域的竞争力,Freeport Resources积极寻求国际合作,与多家国际知名电子材料生产商和研究机构建立了战略伙伴关系。通过技术引进和联合研发,公司成功掌握了先进的电子材料提纯和加工技术,大幅提高了产品的质量和性能。同时,国际合作也帮助Freeport Resources打开了国际市场,其产品远销全球多个国家和地区,进一步巩固了其在电子材料市场的地位。

Array Microsystems Inc公司的发展小趣事

在取得初步成功的基础上,Array Microsystems Inc深知技术创新是企业持续发展的核心动力。因此,公司加大了对研发的投入力度,不断推出新的阵列传感器产品和技术。这些新产品不仅具有更高的性能和更低的成本,还满足了市场不断变化的需求。通过持续的创新和研发,Array Microsystems Inc在电子行业中保持了领先地位。

EMC [ELAN Microelectronics Corp]公司的发展小趣事

作为一家有社会责任感的企业,义隆电子一直积极履行社会责任,致力于可持续发展。公司注重环境保护和资源节约,采用环保材料和节能技术生产产品。同时,公司还积极参与公益事业和社会活动,回馈社会。这种注重社会责任和可持续发展的企业文化使得义隆电子在行业内树立了良好的形象。

以上五个故事简要概述了义隆电子股份有限公司(Elan Microelectronics Corp.)在不同发展阶段的关键事件和成就。这些故事展示了义隆电子在技术创新、市场拓展、人才培养和社会责任等方面的努力和成就。

Forge Europa Ltd公司的发展小趣事

在快速发展的过程中,Forge Europa Ltd公司始终注重品牌与文化的塑造。公司秉承“创新、品质、服务”的企业精神,致力于为客户提供优质的产品和服务。同时,公司还注重员工的培养和发展,建立了完善的培训体系和激励机制,激发了员工的创造力和工作热情。通过这些努力,Forge Europa不仅塑造了一个具有行业影响力的品牌形象,还形成了独特的企业文化,为企业的长远发展奠定了坚实的基础。

问答坊 | AI 解惑

关于题C的问题

本帖最后由 paulhyde 于 2014-9-15 09:30 编辑 AD603产生的自激现象严重,当用两级放大时候,第二级放大严重失真,这个是什么原因啊?我们现在在AD603前面加了OPA658做前级跟随器,希望可以减小自激  …

查看全部问答>

发个我用的元件库

这是我平常所用到的元件库…

查看全部问答>

wince 的cab 安装包问题(vs2005)

想做一个cab安装包,安装今日插件,按照网上的说明写了个安装程序setupdll.dll, 但是在模拟器上(pocket pc se 2003 Emulator)安装发现setupdll没有被调用(在函数Install_Exit中加了MessageBox,没有弹出,注册表也没写) cab安装包使用vs2005做的 ...…

查看全部问答>

GPRS连接问题

我用OPEN AT 已经建立完成了GPRS激活部分,但是为什么数据流中什么都收不到,在超级终端里使用ATD*99***1#,可以收到PPP包,如何使用OPEN AT ADL也能收到这些PPP包?请指教一二!我在软件里已经加入了AT命令,但是没有任何反应,到底是什么地方出了 ...…

查看全部问答>

用KernelIoControl获取逻辑中断号失败

我想使用EINTT4作按键中断输入.定义如下: UINT32  g_EINTIrq = IRQ_EINT4; UINT32  g_EINTSysIntr = SYSINTR_UNDEFINED; PUBLIC DWORD CPK_Init(DWORD dwContext) {             &n ...…

查看全部问答>

EVC4.0中窗体最小化问题

想要实现一个最小化功能 使用ShowWindow函数没反应~ 请问各位还有什么其他办法不?…

查看全部问答>

dshow CreateMediaType FreeMediaType 无法解析的外部符号

我在wince6.0上做dshow开发,已经包含的头文件和库 #include #include #include #include #include                                     &n ...…

查看全部问答>

CE6及BSP安装求救!!!!紧急啊

我之前安装开发环境的时候,发现PB中Device Driver中的SD选项没有,后来把Updates全装上了,就出现了SD选项。 前几天系统崩溃了,重新装上所有东西后发现就是SD选项没有,各位有没有遇到过这种情况啊????急 …

查看全部问答>

请教中断问题

我在做关于MPC8260的工作.目前,我想为DMA加入中断处理程序.MPC8260的参考手册中 说,IDMA1的中断号是6,我使用如下函数: intConnect(INUM_TO_IVEC(6),dma_isr,0); 连接中断处理程序与中断源.但是一旦DMA结束,BC中断到来之后,整个EP8260板子就死掉 ...…

查看全部问答>

MCS-51单片机定时器问题

MCS-51单片机中,采用12Mhz时钟,定时器T0采用模式1(16位计数器),请问在下面程序中,p1.0的输出频率 ? MOV TMOD,#01H SETB TR0 LOOP:MOV TH0,#0B1H MOV TL0,#0E0H LOOP1:JNB TF0,LOOP1 CLR TR0 CPL P1.0 SJMP LOOP…

查看全部问答>