qzc0927 发表于 2024-3-5 17:57

ST NUCLEO-C031C6开发板学习笔记08(FLASH读写)

<div class='showpostmsg'>## 11:FLASH读写

### 11.1:硬件设计

先看数据手册说明:

!(https://boreyun.oss-cn-shanghai.aliyuncs.com/image-20240305174518991.png)

FLASH空间大小为32KB。

在看下FLASH的特性:

!(https://boreyun.oss-cn-shanghai.aliyuncs.com/image-20240305174637960.png)

### 11.2:软件设计

读写FLASH操作步骤

(1)写数据操作
1.解除写保护

```C
HAL_FLASH_Unlock();
```

2.清除状态位,确认未在执行任何FLASH操作,

```C
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR);
```

3.擦除扇区HAL_FLASHEx_Erase

```C
HAL_FLASHEx_Erase(&EraseInitStruct, &PageError)
```

4.写入双字64位数据

```C
HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, Address, DATA_64)
```

5.锁定写保护

```
HAL_FLASH_Lock();
```

(2)读数据操作
直接读取地址数据即可。

```C
data32 = *(__IO uint32_t *)Address;
```

具体实现代码为:

首先设置FLASH空间地址:

```C
#define ADDR_FLASH_PAGE_0   ((uint32_t)0x08000000) /* Base @ of Page 0, 2 Kbytes */
#define ADDR_FLASH_PAGE_1   ((uint32_t)0x08000800) /* Base @ of Page 1, 2 Kbytes */
#define ADDR_FLASH_PAGE_2   ((uint32_t)0x08001000) /* Base @ of Page 2, 2 Kbytes */
#define ADDR_FLASH_PAGE_3   ((uint32_t)0x08001800) /* Base @ of Page 3, 2 Kbytes */
#define ADDR_FLASH_PAGE_4   ((uint32_t)0x08002000) /* Base @ of Page 4, 2 Kbytes */
#define ADDR_FLASH_PAGE_5   ((uint32_t)0x08002800) /* Base @ of Page 5, 2 Kbytes */
#define ADDR_FLASH_PAGE_6   ((uint32_t)0x08003000) /* Base @ of Page 6, 2 Kbytes */
#define ADDR_FLASH_PAGE_7   ((uint32_t)0x08003800) /* Base @ of Page 7, 2 Kbytes */
#define ADDR_FLASH_PAGE_8   ((uint32_t)0x08004000) /* Base @ of Page 8, 2 Kbytes */
#define ADDR_FLASH_PAGE_9   ((uint32_t)0x08004800) /* Base @ of Page 9, 2 Kbytes */
#define ADDR_FLASH_PAGE_10    ((uint32_t)0x08005000) /* Base @ of Page 10, 2 Kbytes */
#define ADDR_FLASH_PAGE_11    ((uint32_t)0x08005800) /* Base @ of Page 11, 2 Kbytes */
#define ADDR_FLASH_PAGE_12    ((uint32_t)0x08006000) /* Base @ of Page 12, 2 Kbytes */
#define ADDR_FLASH_PAGE_13    ((uint32_t)0x08006800) /* Base @ of Page 13, 2 Kbytes */
#define ADDR_FLASH_PAGE_14    ((uint32_t)0x08007000) /* Base @ of Page 14, 2 Kbytes */
#define ADDR_FLASH_PAGE_15    ((uint32_t)0x08007800) /* Base @ of Page 15, 2 Kbytes */
```

编写FLASH读写函数

```C
void Flash_WR_Task(void)
{

    HAL_FLASH_Unlock();

    /* Clear OPTVERR bit set on virgin samples */
    __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR);

    /* Erase the user Flash area
      (area defined by FLASH_USER_START_ADDR and FLASH_USER_END_ADDR) ***********/

    /* Get the 1st page to erase */
    FirstPage = GetPage(FLASH_USER_START_ADDR);

    /* Get the number of pages to erase from 1st page */
    NbOfPages = GetPage(FLASH_USER_END_ADDR) - FirstPage + 1;

    /* Fill EraseInit structure*/
    EraseInitStruct.TypeErase   = FLASH_TYPEERASE_PAGES;
    EraseInitStruct.Page      = FirstPage;
    EraseInitStruct.NbPages   = NbOfPages;
    if (HAL_FLASHEx_Erase(&EraseInitStruct, &PageError) != HAL_OK)
    {
      /*如果擦除失败,就一直再闪烁LED*/
      while (1)
      {
            HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_5);
            HAL_Delay(500);
      }
    }

    Address = FLASH_USER_START_ADDR;

    while (Address < FLASH_USER_END_ADDR)
    {
      if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, Address, DATA_64) == HAL_OK)
      {
            Address = Address + 8;
      }
    }

    HAL_FLASH_Lock();
    DEBUG_LOG("Flash写入数据成功");


    Address = FLASH_USER_START_ADDR;
    MemoryProgramStatus = 0x0;

    while (Address < FLASH_USER_END_ADDR)
    {
      data32 = *(__IO uint32_t *)Address;

      if (data32 != DATA_32)
      {
            MemoryProgramStatus++;

      }
      Address = Address + 4;
      DEBUG_LOG("%08x",data32);
    }

}
```

### 11.3:FLASH读写单元测试

将FLASH的最后两页不断写入0x11223344,然后读取数据。

!(https://boreyun.oss-cn-shanghai.aliyuncs.com/image-20240305175440799.png)

写入成功。

!(https://boreyun.oss-cn-shanghai.aliyuncs.com/image-20240305175537978.png)

读取成功。</div><script>                                        var loginstr = '<div class="locked">查看本帖全部内容,请<a href="javascript:;"   style="color:#e60000" class="loginf">登录</a>或者<a href="https://bbs.eeworld.com.cn/member.php?mod=register_eeworld.php&action=wechat" style="color:#e60000" target="_blank">注册</a></div>';
                                       
                                        if(parseInt(discuz_uid)==0){
                                               
                                        }                </script><script type="text/javascript">(function(d,c){var a=d.createElement("script"),m=d.getElementsByTagName("script"),eewurl="//counter.eeworld.com.cn/pv/count/";a.src=eewurl+c;m.parentNode.insertBefore(a,m)})(document,523)</script>

hjl2832 发表于 2024-3-6 08:34

<p>拿这个模拟EEPROM</p>

秦天qintian0303 发表于 2024-3-7 17:29

<p>没有读保护吗?这个应该和保护等级有关&nbsp;&nbsp;</p>

qzc0927 发表于 2024-3-8 08:04

秦天qintian0303 发表于 2024-3-7 17:29
没有读保护吗?这个应该和保护等级有关&nbsp;&nbsp;

<p>讀4的話,可以直接讀的</p>

chejm 发表于 2024-3-9 08:01

<p>楼主分享的技术内容非常详细,值得收藏学习,非常感谢</p>
页: [1]
查看完整版本: ST NUCLEO-C031C6开发板学习笔记08(FLASH读写)