完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
嵌入式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)) { sector = FLASH_Sector_18; } else if((Address 《 ADDR_FLASH_SECTOR_20) && (Address 》= ADDR_FLASH_SECTOR_19)) { sector = FLASH_Sector_19; } else if((Address 《 ADDR_FLASH_SECTOR_21) && (Address 》= ADDR_FLASH_SECTOR_20)) { sector = FLASH_Sector_20; } else if((Address 《 ADDR_FLASH_SECTOR_22) && (Address 》= ADDR_FLASH_SECTOR_21)) { sector = FLASH_Sector_21; } else if((Address 《 ADDR_FLASH_SECTOR_23) && (Address 》= ADDR_FLASH_SECTOR_22)) { sector = FLASH_Sector_22; } else/*(Address 《 FLASH_END_ADDR) && (Address 》= ADDR_FLASH_SECTOR_23))*/ { sector = FLASH_Sector_23; } return sector; } int main(void) { char buf[128]={0}; //使能GPIOG的硬件时钟 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE); //系统定时器初始化,时钟源来自HCLK,且进行8分频, //系统定时器时钟频率=168MHz/8=21MHz SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //设置中断优先级分组2 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //串口1,波特率115200bps,开启接收中断 USART1_Init(115200); /* Enable the flash control register access ,使能FLASH寄存器的访问,解除保护机制*/ 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); #if 1 /* 通过扇区地址转换为扇区号,因为进行扇区擦除的时候,需要填写扇区的编号*/ uwStartSector = GetSector(FLASH_USER_START_ADDR); uwEndSector = GetSector(FLASH_USER_END_ADDR); /* Strat 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 */ if (FLASH_EraseSector(uwSectorCounter, VoltageRange_3) != FLASH_COMPLETE) { /* Error occurred while sector erase. ,擦除错误 User can add here some code to deal with this error */ while (1) { printf(“Erase errorrn”); delay_ms(500); } } /* jump to the next sector */ if (uwSectorCounter == FLASH_Sector_11) { uwSectorCounter += 40; } else { uwSectorCounter += 8; } } //添加读取数据的代码,测试擦除完之后读到的值是? uwAddress = FLASH_USER_START_ADDR; //扇区6的起始地址 while (uwAddress 《 FLASH_USER_END_ADDR) { //指向扇区地址并取指就等同于读取数据 uwData32 = *(__IO uint32_t*)uwAddress; //因为每次读取是4个字节,所以每次地址偏移4个字节 uwAddress = uwAddress + 4; //[可选]打印一些调试信息,每偏移1000地址就打印一次数据 if(uwAddress % 1000 ==0) printf(“%8X rn”,uwData32); } #endif /* Program the user Flash area word by word ,开始写入数据*/ /* area defined by FLASH_USER_START_ADDR and FLASH_USER_END_ADDR */ uwAddress = FLASH_USER_START_ADDR; //扇区6的起始地址 while (uwAddress 《 FLASH_USER_END_ADDR) //以扇区7的起始地址作为结束地址 { //每次写入数据为0x12345678的时候以4字节也就是以字为单位 if (FLASH_ProgramWord(uwAddress, 0x12345678) == FLASH_COMPLETE) { //每写完一次,地址偏移4个字节 uwAddress = uwAddress + 4; } else { /* Error occurred while writing data in Flash memory,写入失败 User can add here some code to deal with this error */ while (1) { printf(“Program error at addr %8X rn”,uwAddress); delay_ms(500); } } } /* Lock the Flash to disable the flash control register access ,写入后,锁定FLASH*/ FLASH_Lock(); /* Check if the programmed data is OK ,读取FLASH数据并进行校验*/ /* MemoryProgramStatus = 0: data programmed correctly MemoryProgramStatus != 0: number of words not programmed correctly */ uwAddress = FLASH_USER_START_ADDR; uwMemoryProgramStatus = 0; while (uwAddress 《 FLASH_USER_END_ADDR) { //指向扇区地址并取指就等同于读取数据!!!!!!!!!!!!!!!!!!!!!!!! uwData32 = *(__IO uint32_t*)uwAddress; //读取到的数据不等于0x12345678的时候,就进行错误的计数 if (uwData32 != 0x12345678) { uwMemoryProgramStatus++; } //因为每次读取是4个字节,所以每次地址偏移4个字节 uwAddress = uwAddress + 4; //[可选]打印一些调试信息,每偏移1000地址就打印一次数据 if(uwAddress % 1000 ==0) printf(“%8X rn”,uwData32); } /* Check Data correctness ,最后进行数据错误计数输出*/ if(uwMemoryProgramStatus) { printf(“Read check is not correctrn”); } else { printf(“Read check is correctrn”); } while(1) { } } 如何知道当前保存数据的数目﹖ 方法1:将数据的数目保存到其他扇区或者其他地址。 方法2:当读取到数据为0xFF的时候,就是该区域没有被改写过。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1777 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1621 浏览 1 评论
1080 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
728 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1678 浏览 2 评论
1938浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
731浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
570浏览 3评论
595浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
554浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-23 04:26 , Processed in 0.955086 second(s), Total 76, Slave 59 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号