STM32C011开发(3)—-Flash操作

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 写入数据,需要依次完成以下四个步骤:

    1. 解锁 FLASH
    2. 擦除 FLASH
    3. 写入 FLASH
    4. 锁定 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 解锁 FLASH
        if (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 锁住 FLASH
        HAL_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读取。

    作者:记帖

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32C011开发(3)—-Flash操作

    发表回复