GD32片内flash读写数据

介绍如何在GD32单片机的Flash中存储配置参数,包括读取、保存及验证参数有效性等核心功能。适用于需要掉电保存配置信息的应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        GD32现在越来越火,应用也越来越广泛。我们在开发项目的时候,总会有需要掉电存储一些配置信息的时候,但是使用外挂flash、或者EEPROM,或多或少都会占用一些外围接口或增加一定的成本。于是,直接将配置参数存储到片内flash上还是会更香一些。一般flash的擦写次数能够达到10万次,若擦写操作不太频繁,完全是够用的。

        刚好最近做了个项目,用到了这个功能,掉电存储一些必要的参数配置。在GD32中,Flash模块的名称为FMC。

其实要实现的主要功能就只有三个:读取存在flash中的参数信息、报存参数信息到flash中、获取读出来的参数信息。

        而参数信息可以是自行定义的任意结构体,但是值得注意的是Flash是按页(1Kb)擦除的。需要自行修改FLASH写入的开始地址和结束地址。我这款单片机Flash大小是用的64K的,数据存储在最后1KB的位置。

        由于数据写入以四个直接为单位,所以创建了一个联合体,方便通过指针来将参数数据写入。

注意:以下程序只支持大小小于1KB的参数读写,如果超过1KB,需要加入对页的判断,自行修改数据读、写过程。

程序源码示例:

params_manage.h

#ifndef __PARAMS_MANAGE_H__
#define __PARAMS_MANAGE_H__

#include <stdint.h>

#ifdef __cplusplus
extern "C"{
#endif /* __cplusplus */


#define FMC_PAGE_SIZE           ((uint16_t)0x400U)
#define FMC_WRITE_START_ADDR    ((uint32_t)0x0800FC00U)
#define FMC_WRITE_END_ADDR			((uint32_t)0x0800FFFFU)

/* 需要保存的参数 */
typedef struct _CONFIG_PARAMS
{
		unsigned char data_valid_flag;				//数据有效标志  0xF1:有效  其它:无效
		unsigned char sleep_flag;             //是否进入休眠标志  0:不进入 1:进入
		unsigned char open_direction;					//开门方向   		0:左开门 1:右开门
		int16_t x_value;											//地磁X轴方向值
		int16_t y_value;											//地磁Y轴方向值
		int16_t z_value;											//地磁Z轴方向值
		uint32_t tmp_password_flag;						//临时密码使用标志
		unsigned char user_flag[50];					//当前有效用户标记
		unsigned char password_table[50][7];	//用户密码数组
}CONFIG_PARAMS;


/* 系统状态信息 */
typedef struct _SYS_STATUS
{
		unsigned char door_state;				//门磁状态    0:关门  1:开门
		unsigned char auto_anti_lock;		//自动反锁配置 0:不自动反锁    1:自动反锁
		unsigned char quiet_flag;				//自动反锁配置 0:音频正常播放  1:部分音频静音
		unsigned char opto1_state;			//光耦1状态
		unsigned char opto2_state;			//光耦2状态
		unsigned char opto3_state;			//光耦3状态
		float battery_volatage;					//电池电压		0-5V
}SYS_STATUS;


typedef union _CONFIG_PARAMS_UNION
{
		CONFIG_PARAMS config_params;  // 360字节
		uint32_t data[104];						//用于通过联合体字节对齐,方便数据存储 104*4=416字节
}CONFIG_PARAMS_UNION;


extern int load_config_params(void);

extern CONFIG_PARAMS *get_config_params(void);

extern int is_config_params_avaliable(void);

extern int save_config_params(CONFIG_PARAMS *params);


#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif

params_manage.c

#include <stdio.h>
#include <string.h>
#include "gd32e230.h"
#include "params_manage.h"

static CONFIG_PARAMS g_config_params = {0};

static void fmc_erase_pages(void)
{
    /* unlock the flash program/erase controller */
    fmc_unlock();
    /* clear all pending flags */
    fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_WPERR | FMC_FLAG_PGERR);
    /* erase the flash pages */
    fmc_page_erase(FMC_WRITE_START_ADDR);
	fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_WPERR | FMC_FLAG_PGERR);
    /* lock the main FMC after the erase operation */
    fmc_lock();
}

static void fmc_program(uint32_t *data, int data_len)
{
    /* unlock the flash program/erase controller */
    fmc_unlock();

    uint32_t address = FMC_WRITE_START_ADDR;
    /* program flash */
    while(address <= FMC_WRITE_END_ADDR) {
        if(data_len <= 0)
            break;
        fmc_word_program(address, *data);
        address += 4U;
		data++;
        fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_WPERR | FMC_FLAG_PGERR);
        data_len-=4;
    }
    /* lock the main FMC after the program operation */
    fmc_lock();
}

//参数是否有效
int is_config_params_avaliable()
{
		return (g_config_params.data_valid_flag == 0xF1)?1:0;
}

//加载配置参数
int load_config_params()
{	
		CONFIG_PARAMS_UNION config_params_union;
	  unsigned char *ptr = (unsigned char *)FMC_WRITE_START_ADDR;													 //将指针指向存储区首地址
		if(*ptr == 0xF1)
		{
				//从Flash中读取到有效的配置数据
				memcpy(&config_params_union, ptr, sizeof(CONFIG_PARAMS_UNION));						 
				memcpy(&g_config_params, &config_params_union.config_params, sizeof(CONFIG_PARAMS)); //拷贝数据
				return 0;
		}
		return -1;
}

//获取参数配置
CONFIG_PARAMS *get_config_params()
{
		return &g_config_params;
}


//保存配置参数
int save_config_params(CONFIG_PARAMS *params)
{
		if(params == NULL)
				return -1;
		
		CONFIG_PARAMS_UNION config_params_union;
		memset(&config_params_union, 0, sizeof(CONFIG_PARAMS_UNION));	//清空数据
		memcpy(&config_params_union.config_params, params, sizeof(CONFIG_PARAMS)); //拷贝数据
		//擦除FLASH
		fmc_erase_pages();
		//保存配置数据到Flash中
		fmc_program((uint32_t *)&config_params_union, sizeof(CONFIG_PARAMS_UNION));
		
		return 0;
}

评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值