STM32C011开发----3.Flash操作
- 概述
- 硬件准备
- 视频教学
- 样品申请
- 源码下载
- 参考程序
- 生成STM32CUBEMX
- 串口配置
- 堆栈设置
- 串口重定向
- FLASH
- 数据初始化
- FLASH 读写
- 演示
概述
STM32C011 系列微控制器内置 Flash 存储器,支持程序存储与数据保存,具备页面擦除、双字写入、读写保护等功能。本文将简要介绍 STM32C011 的 Flash 结构与特性,并通过实际代码示例,讲解 Flash 的擦除、写入与读取等基本操作。
最近在弄ST的教程,需要样片的可以加群申请:615061293/925643491 。
硬件准备
首先需要准备一个开发板,这里我准备的是自己绘制的开发板,需要的可以进行申请。
主控为STM32C011F4P6
视频教学
https://www.bilibili.com/video/BV1KTBtY4EpD
STM32C011开发(3)----Flash操作
样品申请
https://www.wjx.top/vm/OhcKxJk.aspx#
源码下载
参考程序
https://github.com/CoreMaker-lab/STM32C011_TSSOP20
https://gitee.com/CoreMaker/STM32C011_TSSOP20
生成STM32CUBEMX
用STM32CUBEMX生成例程,这里使用MCU为STM32C011F4P6。
配置时钟树,配置时钟为48M。
串口配置
查看原理图,PA0和PA1设置为开发板的串口。
配置串口,速率为115200。
堆栈设置
若无法正常运行需要修改优化等级。
串口重定向
打开魔术棒,勾选MicroLIB
在main.c中,添加头文件,若不添加会出现 identifier “FILE” is undefined报错。
/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes */
函数声明和串口重定向:
/* USER CODE BEGIN PFP */
int fputc(int ch, FILE *f){HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);return ch;
}
/* USER CODE END PFP */
FLASH
STM32C011 的嵌入式 Flash 通过 AHB 总线与 Cortex-M0+ CPU 连接,支持访问、擦除和编程操作。
Flash 构成:
● 存储单元:Flash 单元为 64 位宽,用于存储代码及数据。
● 主存储器结构:
○ 共 16 页,每页大小为 2 KB,总计 32 KB。
● 信息块区域:
○ 包括选项字节(2 KB)、工程字节(1 KB)、OTP(1 KB)及系统存储器(6 KB)。
要向 FLASH 写入数据,需要依次完成以下四个步骤:
- 解锁 FLASH
- 擦除 FLASH
- 写入 FLASH
- 锁定 FLASH
需要注意,FLASH 的擦除只能按页或整块进行。
STM32C011F4P6 的 FLASH 容量为 16 KB,共分为 8 页,每页大小为 2 KB。
我们可以将数据写入第 7 页,其地址范围为 0x08003800 - 0x08003FFF。
单次写入的单位为 64 位(8 字节)。
数据初始化
● WriteFlashData:
○ 这是一个待写入的 64 位数据数组,包含 3 个双字(64 位)数据。
○ 每个元素的大小是 8 字节,总计 24 字节的数据。
● addr 和 Page:
○ addr 是目标地址,表示从 Flash 的第 7 页(Page 7)开始写入。
○ STM32 的 Flash 以 2 KB 为一页,因此第 7 页的起始地址是 0x08003800。
/* USER CODE BEGIN 0 */
uint64_t WriteFlashData[3] = {0x1111222233334444,0x5555666677778888,0x9999AAAABBBBCCCC};//数据uint32_t addr = 0x08003800;//page 7
uint32_t Page = 7;void PrintFlashTest(uint32_t L,uint32_t Page);
void WriteFlashTest(uint32_t L,uint64_t Data[],uint32_t Page,uint32_t addr);/* USER CODE END 0 */
FLASH 读写
/* USER CODE BEGIN 4 */
/* FLASH 写入程序 */
void WriteFlashTest(uint32_t L, uint64_t Data[], uint32_t Page, uint32_t addr)
{uint32_t i = 0;uint32_t PageError = 0;// 1/4 解锁 FLASHif (HAL_FLASH_Unlock() != HAL_OK){printf("Error: Failed to unlock FLASH.\n");return;}// 2/4 初始化擦除结构体并擦除指定页FLASH_EraseInitTypeDef FlashSet;FlashSet.TypeErase = FLASH_TYPEERASE_PAGES; // 擦除类型:页擦除FlashSet.Page = Page; // 页索引FlashSet.NbPages = 1; // 一次擦除 1 页if (HAL_FLASHEx_Erase(&FlashSet, &PageError) != HAL_OK){printf("Error: Failed to erase FLASH. PageError: %d\n", PageError);HAL_FLASH_Lock();return;}printf("FLASH Page %u erased successfully.\n", Page);// 3/4 将数据写入指定地址for (i = 0; i < L; i++){if (HAL_FLASH_Program(TYPEPROGRAM_DOUBLEWORD, addr + 8 * i, Data[i]) != HAL_OK){printf("Error: FLASH program failed at address 0x%08X.\n", addr + 8 * i);HAL_FLASH_Lock();return;}}printf("FLASH programming completed successfully.\n");// 4/4 锁住 FLASHHAL_FLASH_Lock();
}/* FLASH 读取并打印程序 */
void PrintFlashTest(uint32_t L, uint32_t addr)
{uint32_t i = 0;uint64_t data = 0;printf("Reading FLASH data from address 0x%08X:\n", addr);for (i = 0; i < L; i++){data = *(__IO uint64_t *)(addr + i * 8); // 按 64 位读取数据printf("Address: 0x%08X, Data: 0x%016llX\n", addr + i * 8, data);}printf("FLASH read completed.\n");
}
/* USER CODE END 4 */
测试 FLASH 写入和读取功能,分为两次写入操作,并在每次写入后进行验证。
● 两次写入操作,分别测试不同数据的写入和读取。
● 验证写入是否正确,通过读取打印结果进行比对。
/* USER CODE BEGIN 2 */printf("=== First Write and Read ===\n");WriteFlashTest(3,WriteFlashData,Page,addr);PrintFlashTest(3,addr);//WriteFlashData[3] = {0x1111222233334444,0x5555666677778888,0x9999AAAABBBBCCCC};//数据printf("\n=== Modify Data and Rewrite ===\n");WriteFlashData[0]=0x9999;WriteFlashData[1]=0x8888;WriteFlashData[2]=0x7777;WriteFlashTest(3,WriteFlashData,Page,addr);PrintFlashTest(3,addr);/* USER CODE END 2 */
演示
测试结果如下所示。
第一次写入。
第二次写入。
STM32CubeProgrammer读取。