文章目录
1、STM32内部Flash
1.1 Flash介绍
在STM32芯片内部有一个 FLASH 存储器,它主要用于存储代码,我们在电脑上编写好应用程序后,使用下载器把编译后的代码文件烧录到该内部 FLASH 中,由于 FLASH 存储器的内容在掉电后不会丢失,芯片重新上电复位后,内核可从内部 FLASH 中加载代码并运行。
1.2 STM32内部Flash详解
STM32 的内部 FLASH 包含主存储器、系统存储器以及选项字节区域,它们的地址分布及大小见下表:
1.2.1 主存储器
一般我们说 STM32 内部 FLASH 的时候,都是指这个主存储器区域,它是存储用户应用程序的空间,芯片型号说明中的 256K FLASH、512K FLASH 都是指这个区域的大小。
主存储器分为 256 页,每页大小为 2KB,共 512KB。这个分页的概念,实质就是 FLASH 存储器的扇区,与其它 FLASH 一样,在写入数据前,要先按页(扇区)擦除。
注意上表中的主存储器是本实验板使用的 STM32VET6 型号芯片的参数,即 STM32F1 大容量产品。若使用超大容量、中容量或小容量产品,它们主存储器的页数量、页大小均有不同,使用的时候要注意区分。
主存储器是以页为单位划分的。stm32根据FLASH主存储块容量、页面的不同,系统存储器的不同,分为小容量、中容量、大容量、互联型,共四类产品。
- 小容量产品:主存储块1-32KB, 每页1KB。系统存储器2KB
- 中容量产品:主存储块64-128KB, 每页1KB。系统存储器2KB
- 大容量产品:主存储块256KB以上, 每页2KB。系统存储器2KB
- 互联型产品:主存储块256KB以上, 每页2KB。系统存储器18KB
1.2.2 系统存储区
系统存储区是用户不能访问的区域,它在芯片出厂时已经固化了启动代码,它负责实现串口、USB 以及 CAN 等 ISP 烧录功能。
1.2.3 选型字节
选项字节用于配置 FLASH 的读写保护、待机/停机复位、软件/硬件看门狗等功能,这部分共 16 字节。可以通过修改 FLASH 的选项控制寄存器修改。
2、STM32CUBEMX配置
本工程采用的芯片型号是STM32F103C8T6,CUBEMX的配置按照这个行骗型号进行配置。
2.1 时钟源配置
2.2 调试接口配置
2.3 工程配置
2.4 工程文件配置
2.5 时钟配置
3、代码讲解
3.1 flash读写代码的.h文件
#ifndef __FLASH_H__
#define __FLASH_H__
#include "main.h"
#include "string.h"
#define STM32_FLASH_SIZE 64 //所选STM32的FLASH容量大小(单位为K);本产品选用的型号为:STM32F103C8T6;FALSH大小为64K
#if STM32_FLASH_SIZE < 256
#define STM32_SECTOR_SIZE 1024 //一页为1K
#else
#define STM32_SECTOR_SIZE 2048 //一页为2K
#endif
#define STM32_FLASH_BASE 0x08000000 //STM32 FLASH起始地址
//写入的FLASH地址,这里为从倒数第一个扇区地址(0x807f800)开始写
//STM32_FLASH_BASE + STM32_SECTOR_SIZE*255 = 0x08000000 + (2048*255) = 0x0807f800
#define FLASH_SAVE_ADDR STM32_FLASH_BASE+STM32_SECTOR_SIZE*255
void FLASH_WriteData(uint32_t FLASH_Addr, uint16_t *FLASH_Data, uint16_t Size);
uint16_t FLASH_ReadHalfWord(uint32_t faddr);
void FLASH_ReadData(uint32_t ReadAddr,uint16_t *pBuffer,uint16_t NumToRead);
#endif
3.2 flash读写代码的.c文件
#include "flash.h"
/*从指定地址开始写入数据*/
//FLASH_Addr:起始地址
//FLASH_Data:写入数据指针(写入的数据为16位,至少都要16位)
//Size:写入数据长度
void FLASH_WriteData(uint32_t FLASH_Addr, uint16_t *FLASH_Data, uint16_t Size)
{
/*内部FLASH测试*/
//1.解锁FLASH
HAL_FLASH_Unlock();
//2.擦除FALSH
//初始化FLASH_EraseInitTypeDef
FLASH_EraseInitTypeDef FLASH_Init;
FLASH_Init.TypeErase = FLASH_TYPEERASE_PAGES;
FLASH_Init.PageAddress = FLASH_Addr;
FLASH_Init.NbPages = 1;
uint32_t PageError = 0;
//3.调用擦除函数
HAL_FLASHEx_Erase(&FLASH_Init,&PageError);
//4.对FLASH烧写
uint16_t TempBuf = 0;
for(uint16_t i=0;i<Size;i++)
{
TempBuf = *(FLASH_Data+i);
HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD,(FLASH_Addr + (i*2)),TempBuf);
}
//5.锁住FLASH
HAL_FLASH_Lock();
}
//从指定地址读出数据
//faddr:地址
uint16_t FLASH_ReadHalfWord(uint32_t faddr)
{
return *(__IO uint16_t*)faddr;
}
//从指定地址开始读出指定长度的数据
//ReadAddr:起始指针
//pBuffer:数据指针
//NumToRead:大小(至少半字(16位)数)
void FLASH_ReadData(uint32_t ReadAddr,uint16_t *pBuffer,uint16_t NumToRead)
{
for(uint16_t i=0;i<NumToRead;i++)
{
pBuffer[i] = FLASH_ReadHalfWord(ReadAddr);
ReadAddr+=2;
}
}
3.3 代码的主函数(main)
int main(void)
{
/* USER CODE BEGIN 1 */
char Write_Data[10]="0123456789";
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
/*将Write_Data数据的内容写进FLASH*/
FLASH_WriteData(FLASH_SAVE_ADDR,(uint16_t *)&Write_Data,10);
/*从STM32 FLASH中读出写入的数据,将数据储存在Read_Data中*/
FLASH_ReadData(FLASH_SAVE_ADDR,(uint16_t *)&Read_Data,10);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
printf("FALSH = %s\r\n",Read_Data);
HAL_Delay(1000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}