当前位置: 首页 > article >正文

stm32f103使用hal库函数读写内部flash


文章目录

  • 一、写内部flash
  • 二、读内部flash
  • 三、代码


本次使用RT-Thread studio编写,使用为5.02完整版,直接编写函数使用hal库函数读写内部flash。

一、写内部flash

在写数据的逻辑上是比较简单的,因为hal库将底层已经进行了封装,步骤就是解锁flash->擦除要写入的扇区->清除CR寄存器的PER位(这个本来应该在擦除里面的,基础库就是这样做的,但HAL库里面没写)->写入数据->上锁flash。
代码:

void Flash_Write(uint32_t TypeProgram, uint32_t Address, uint64_t (*Data), uint32_t len)
{

    HAL_FLASH_Unlock();

    FLASH_PageErase(Address);  //擦除这个扇区
    CLEAR_BIT(FLASH->CR, FLASH_CR_PER);                         //清除CR寄存器的PER位,此操作应该在FLASH_PageErase()中完成!
                                                                            //但是HAL库里面并没有做,应该是HAL库bug!
    if (TypeProgram==TYPEPROGRAM_CHAR) {
        for (int var = 0; var < len/2; var++) {
            uint8_t data1=(uint8_t)*Data;
            uint8_t data2=(uint8_t)*(Data+1);
            uint64_t datar = data2<<8|data1;
            HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, Address,datar);
            Address+=2;
            Data+=2;
        }
    } else {
        for (int var = 0; var < len; var++) {
            HAL_FLASH_Program(TypeProgram, Address, *Data);
            Address+=(1<<TypeProgram);
            Data+=1;
        }
    }
    HAL_FLASH_Lock();
}

这里面我想要8位,16位,32位,64位的数据都能写入,所以定义了一个写入类型的参数,由于库函数至少是按半字处理的,所以8位需要特殊处理,而且要进行兼容,传入的数据就只能是64位的,这点比较麻烦,就是说传入的数组必须是64位,不然写入的结果会不对,已经测试过。

二、读内部flash

读内部就比较简单了,只需要按照类型返回不同指针强转和不同地址增加就行了,但是同样传入的指针是64位,使用数据时还的强转为自己想要的类型:

void Flash_Read(uint32_t TypeProgram, uint32_t Address, uint64_t (*Data), uint32_t len)
{
    int32_t i=0;
    if (TypeProgram==TYPEPROGRAM_CHAR) {
       for (i = 0; i < len; i++, Address+=1, Data++)
       {
           *Data = *(uint8_t *) Address;
       }
    }else if (TypeProgram==TYPEPROGRAM_HALFWORD) {
       for (i = 0; i < len; i++, Address+=2, Data++)
       {
           *Data = *(uint16_t *) Address;
       }
    }else if (TypeProgram==TYPEPROGRAM_WORD) {
      for (i = 0; i < len; i++, Address+=4, Data++)
      {
          *Data = *(uint32_t *) Address;
      }
    }else if (TypeProgram==TYPEPROGRAM_DOUBLEWORD) {
      for (i = 0; i < len; i++, Address+=8, Data++)
      {
          *Data = *(uint64_t *) Address;
      }
    }
}

三、代码

.c文件:

/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2023-12-07     Windows       the first version
 */

#include "flash.h"
extern void    FLASH_PageErase(uint32_t PageAddress);
extern HAL_StatusTypeDef FLASH_WaitForLastOperation(uint32_t Timeout);
//#define TYPEPROGRAM_CHAR                 0x00U  /*!<Program a char (8-bit) at a specified address.*/
//#define TYPEPROGRAM_HALFWORD             0x01U  /*!<Program a half-word (16-bit) at a specified address.*/
//#define TYPEPROGRAM_WORD                 0x02U  /*!<Program a word (32-bit) at a specified address.*/
//#define TYPEPROGRAM_DOUBLEWORD           0x03U  /*!<Program a double word (64-bit) at a specified address*/
void Flash_Write(uint32_t TypeProgram, uint32_t Address, uint64_t (*Data), uint32_t len)
{

    HAL_FLASH_Unlock();

    FLASH_PageErase(Address);  //擦除这个扇区
    CLEAR_BIT(FLASH->CR, FLASH_CR_PER);                         //清除CR寄存器的PER位,此操作应该在FLASH_PageErase()中完成!
                                                                            //但是HAL库里面并没有做,应该是HAL库bug!
    if (TypeProgram==TYPEPROGRAM_CHAR) {
        for (int var = 0; var < len/2; var++) {
            uint8_t data1=(uint8_t)*Data;
            uint8_t data2=(uint8_t)*(Data+1);
            uint64_t datar = data2<<8|data1;
            HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, Address,datar);
            Address+=2;
            Data+=2;
        }
    } else {
        for (int var = 0; var < len; var++) {
            HAL_FLASH_Program(TypeProgram, Address, *Data);
            Address+=(1<<TypeProgram);
            Data+=1;
        }
    }
    HAL_FLASH_Lock();
}

void Flash_Read(uint32_t TypeProgram, uint32_t Address, uint64_t (*Data), uint32_t len)
{
    int32_t i=0;
    if (TypeProgram==TYPEPROGRAM_CHAR) {
       for (i = 0; i < len; i++, Address+=1, Data++)
       {
           *Data = *(uint8_t *) Address;
       }
    }else if (TypeProgram==TYPEPROGRAM_HALFWORD) {
       for (i = 0; i < len; i++, Address+=2, Data++)
       {
           *Data = *(uint16_t *) Address;
       }
    }else if (TypeProgram==TYPEPROGRAM_WORD) {
      for (i = 0; i < len; i++, Address+=4, Data++)
      {
          *Data = *(uint32_t *) Address;
      }
    }else if (TypeProgram==TYPEPROGRAM_DOUBLEWORD) {
      for (i = 0; i < len; i++, Address+=8, Data++)
      {
          *Data = *(uint64_t *) Address;
      }
    }
}

.h文件

/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2023-12-07     Windows       the first version
 */
#ifndef APPLICATIONS_FLASH_H_
#define APPLICATIONS_FLASH_H_

#include "main.h"
#include "stm32f1xx_hal_flash.h"

#define TYPEPROGRAM_CHAR                 0x00U  /*!<Program a char (8-bit) at a specified address.*/
#define TYPEPROGRAM_HALFWORD             0x01U  /*!<Program a half-word (16-bit) at a specified address.*/
#define TYPEPROGRAM_WORD                 0x02U  /*!<Program a word (32-bit) at a specified address.*/
#define TYPEPROGRAM_DOUBLEWORD           0x03U  /*!<Program a double word (64-bit) at a specified address*/
void Flash_Write(uint32_t TypeProgram, uint32_t Address, uint64_t (*Data), uint32_t len);
void Flash_Read(uint32_t TypeProgram, uint32_t Address, uint64_t (*Data), uint32_t len);

#endif /* APPLICATIONS_FLASH_H_ */

main函数测试:

uint64_t flash_buf[] = {2,3,31,45};

    Flash_Write(TYPEPROGRAM_HALFWORD,FLASH_DATA_ADDR,flash_buf,4);

    uint64_t data_buf[4];
    rt_kprintf("FLASH_DATA_ADDR:%x\n",(FLASH_DATA_ADDR));
    Flash_Read(TYPEPROGRAM_HALFWORD,FLASH_DATA_ADDR,data_buf,4);
    rt_kprintf("flash_buf:%d\n",(uint16_t)data_buf[0]);
    rt_kprintf("flash_buf:%d\n",(uint16_t)data_buf[1]);
    rt_kprintf("flash_buf:%d\n",(uint16_t)data_buf[2]);
    rt_kprintf("flash_buf:%d\n",(uint16_t)data_buf[3]);
    data_buf[0]=0x123456789abcdef0;
    rt_kprintf("(uint8_t)data_buf[0]:%x\n",(uint8_t)data_buf[0]);
    rt_kprintf("(uint16_t)data_buf[0]:%x\n",(uint16_t)data_buf[0]);
    rt_kprintf("(uint32_t)data_buf[0]:%x\n",(uint32_t)data_buf[0]);
    rt_kprintf("(uint64_t)data_buf[0]:%x\n",(uint64_t)data_buf[0]);
    rt_kprintf("(uint64_t)data_buf[0]:%x\n",(uint32_t)(data_buf[0]>>32));

测试结果:
在这里插入图片描述


http://www.kler.cn/a/161566.html

相关文章:

  • 【前端】Vue中如何避免出现内存泄漏
  • 28.医院管理系统(基于springboot和vue)
  • 监控录音如何消除杂音?降低录音噪音的五个技巧
  • Java复习42(PTA)
  • Node.Js+Knex+MySQL增删改查的简单示例(Typescript)
  • 微服务架构面试内容整理-SpringCloud Netflix‌与Spring Cloud Alibaba比较
  • 【分布式微服务专题】从单体到分布式(二、SpringCloud整合Nacos)
  • TR转发路由器测评—云企业网实现跨地域跨VPC的网络互通测评实战【阿里云产品测评】
  • tomcat环境搭建
  • 深入理解Dubbo-1.初识Dubbo
  • Csharp(C#)无标题栏窗体拖动代码
  • 推荐5款很牛的Paas平台编译构建工具
  • .netcore 操作aspose.words导出pdf
  • selenium 执行js后拿不到返回值的原因
  • IT基础监控方案:5台服务器和20台网络设备监控
  • UnityShader自定义cginc文件
  • Intellij idea 快速定位到文件的开头或者结尾的几种方式
  • 预测:2024年的安防监控行业将迎来怎样的变化?
  • 使用postman请求x5接口
  • C语言指针详解上
  • 【推荐系统】了解推荐系统的生态(重点:推荐算法的主要分类)
  • 【Java基础篇 | 面向对象】—— 聊聊什么是接口(上篇)
  • 智能优化算法应用:基于鹰栖息算法无线传感器网络(WSN)覆盖优化 - 附代码
  • 2.HTML进阶
  • 为什么伦敦银交易中支撑和阻力位这么重要?
  • 展开说说:Android之广播接收者