×
单片机 > 单片机程序设计 > 详情

STM32F4 内部flash存放配置(优化存储)

发布时间:2020-08-31 发布时间:
|

由于STM32F4系列内部flash的块非常大,因此擦除时间比较长,并且很浪费,我一般使用中间的64KB的块做存储,前面4个16KB为启动程序,后面的几个128KB为应用程序。


存储方案:


使用64KB的扇区,每次配置占用1KB,每次初始化的时候从后向前判断配置是否有效,如果最后一个为有效,则下次写入会擦除扇区,并将配置写入到第0个1KB,下次写入到第1个1KB,依次类推,这样可以保证写入64次配置才擦除一次扇区1来保证稳定性,二来降低每次擦除写入的时间。


这样可以有效的降低擦除次数,提高写入速度,如果配置有1KB大小,则写64次才会擦除一次,效率会高很多。


//Device_Config.c


/*************************************************************************************************************

 * 文件名: Device_Config.c

 * 功能: 设备配置相关

 * 作者: cp1300@139.com

 * 创建时间: 2018-01-13

 * 最后修改时间: 2018-01-13

 * 详细: 设备配置相关-由于使用了串口打印,一定要在串口初始化后再调用

基本思路: 使用64KB的扇区,每次配置占用1KB,每次初始化的时候从后向前判断配置是否有效,如果最后一个为有效,则下次写入

会擦除扇区,并将配置写入到第0个1KB,下次写入到第1个1KB,依次类推,这样可以保证写入64次配置才擦除一次扇区

1来保证稳定性,二来降低每次擦除写入的时间。


*************************************************************************************************************/

#include "system.h"

#include "usart.h"

#include "main.h"

#include "board.h"

#include "wdg.h"

#include "Device_Config.h"

#include "stm32f4_flash.h"

#include

 

 

//调试开关

#define CONFIG_DBUG 0

#if CONFIG_DBUG

#include "system.h"

#define config_debug(format,...) uart_printf(format,##__VA_ARGS__)

#else

#define config_debug(format,...) /\

/

#endif //CONFIG_DBUG

 

 

CONFIG_TYPE g_SYS_Config; //全局系统配置

static u16 gs_ConfigSaveIndex; //系统配置存储索引(用于记录当前存储在这64KB中的位置,每存储一次就会向后增长一次,碰到非FF的时候才进行擦除,循环存储,无需保存之前的数据)

 

#define STM32_CONFIG_PAGE_INDEX 4 //配置扇区索引:扇区4,64KB

#define STM32_CONFIG_PAGE_ADDR 0x08010000 //配置文件页地址(字节地址),0x0801 0000 - 0x0801 FFFF

#define STM32_CONFIG_PAGE_SIZE (64*1024) //配置文件页大小

#define CONFIG_MAX_SIZE 256 //配置文件最大大小

 

 

static bool CONFIG_SaveConfig(CONFIG_TYPE *pConfig); //存储配置数据到flash

 

 

/*************************************************************************************************************************

* 函数 : void CONFIG_Init(void)

* 功能 : 上电初始化配置

* 参数 : 无

* 返回 : 无

* 依赖 : flash操作函数

* 作者 : cp1300@139.com

* 时间 : 2014-10-18

* 最后修改时间 : 2017-03-22

* 说明 : 从配置页面中加载配置文件所在偏移,从后向前查找,会加载配置到全局:g_SYS_Config中

*************************************************************************************************************************/

void CONFIG_Init(void)

{

int index;

u32 addr;

u32 ConfigId;

u16 count;

STM32FLASH_STATUS status;


if(sizeof(CONFIG_TYPE)>CONFIG_MAX_SIZE)

{

DEBUG("错误,配置文件大小超出限制\r\n");

while(1);

}

 

count = STM32_CONFIG_PAGE_SIZE/CONFIG_MAX_SIZE; //计算配置扇区可以存放配置数据的条数

for(index = (count-1);index >= 0;index --) //索引从后向前寻找,索引最大的一次为最后的配置

{

addr = STM32_CONFIG_PAGE_ADDR+index*CONFIG_MAX_SIZE; //计算需要读取的地址

STM32FLASH_Read(addr, &ConfigId, 4/sizeof(u32)); //从指定地址开始读出指定长度的数据-读取配置区域最前面的4B,也就是配置id

if(ConfigId == DEVICE_BOARD_CONFIG_ID) //有效的ID,意味着找到了配置缓冲区索引位置

{

gs_ConfigSaveIndex = index;

uart_printf("找到了配置索引:%d\r\n",index);

break;

}

}

if(index < 0) //没有找到,那么加载默认的配置,格式化并将配置数据写入到第一个扇区中

{

//先擦除

status = STM32FLASH_EraseSector(STM32_CONFIG_PAGE_INDEX);   //擦除扇区

if(status == STM32FLASH_OK)

{

uart_printf("擦除配置扇区%d成功\r\n",STM32_CONFIG_PAGE_INDEX);

}

else

{

uart_printf("擦除配置扇区%d失败\r\n",STM32_CONFIG_PAGE_INDEX);

}

gs_ConfigSaveIndex = 0; //默认从索引0开始存储

uart_printf("系统未配置过,加载默认配置!\r\n");

CONFIG_Default(&g_SYS_Config, TRUE); //所有的配置恢复出厂配置

addr = STM32_CONFIG_PAGE_ADDR+gs_ConfigSaveIndex*CONFIG_MAX_SIZE; //计算需要写入的地址

status = STM32FLASH_Write_NoCheck(addr,(u32 *)&g_SYS_Config,sizeof(CONFIG_TYPE)/sizeof(u32)) ; //不检查的写入-写入配置到flash

if(status != STM32FLASH_OK)

{

DEBUG("写入配置扇区%d失败\r\n",STM32_CONFIG_PAGE_INDEX);

}

}

else //找到配置了,加载配置

{

addr = STM32_CONFIG_PAGE_ADDR+gs_ConfigSaveIndex*CONFIG_MAX_SIZE; //计算需要写入的地址

STM32FLASH_Read(addr, (u32 *)&g_SYS_Config,sizeof(CONFIG_TYPE)/sizeof(u32)); //加载配置

if(CONFIG_Check(&g_SYS_Config, TRUE) == FALSE)

{

uart_printf("加载配置文件失败,配置无效,重新加载默认配置\r\n");

CONFIG_Default(&g_SYS_Config, TRUE); //所有的配置恢复出厂配置

}

else

{

uart_printf("加载配置文件成功,配置大小:%dB\r\n",sizeof(CONFIG_TYPE));

}

}

CONFIG_Check(&g_SYS_Config,FALSE); //检查配置

if(CONFIG_CheckSN(g_SYS_Config.SN) == FALSE)

{

g_SYS_Config.SN[0] = 0;

DEBUG("警告,没有设置SN\r\n");

}

}

 

 

 

/*************************************************************************************************************************

* 函数 : bool CONFIG_Check(CONFIG_TYPE *pConfig,bool isCheckID)

* 功能 : 检查配置参数是否合法

* 参数 : isCheckID:是否检查配置ID,如果检查配置ID不正确直接返回错误,否则将会对错误配置进行限制,最终依旧会返回TRUE;pConfig:配置数据指针

* 返回 : 无

* 依赖 : flash操作函数

* 作者 : cp1300@139.com

* 时间 : 2014-10-18

* 最后修改时间 : 2017-03-22

* 说明 : 用于检查配置

*************************************************************************************************************************/

bool CONFIG_Check(CONFIG_TYPE *pConfig,bool isCheckID)

{

if(isCheckID) //需要检查配置ID

{

if(pConfig->ID != DEVICE_BOARD_CONFIG_ID) return FALSE; //配置ID无效

}

//为每一个配置进行检查

pConfig->SN[15]  = 0; //唯一序列号-不能进行随意修改

/*********************************************************************************************************************************************************************/

if(pConfig->HorizAngle > (90*1000)) pConfig->HorizAngle = 90*1000; //设备安装的水平夹角,保留3位小数

if(pConfig->ThresholdEnergy > 100000) pConfig->ThresholdEnergy = 100000; //阈值能量,低于阈值的将会进行过滤

if(pConfig->WaterLevelHeight > 9999999) pConfig->WaterLevelHeight= 999999; //水位计安装高度

if(pConfig->WaterCorrParame > 999999) pConfig->WaterCorrParame = 999999; //水位计线性修正值,4位小数点

if(pConfig->WaterCorrectionLe > 9999999) pConfig->WaterCorrectionLe = 9999999; //水位修正值,有符号,单位mm

if(pConfig->WaterCorrectionLe < -9999999) pConfig->WaterCorrectionLe = -9999999; //水位修正值,有符号,单位mm

if(pConfig->WarmTime > 999) pConfig->WarmTime = 999; //预热时间,单位S,0-999

if(pConfig->FlowSpeedCorrParame < 1) pConfig->FlowSpeedCorrParame = 1; //流速线性修正值,4位小数点

if(pConfig->FlowSpeedCorrectionLe > 29999) pConfig->FlowSpeedCorrectionLe = 29999; //流速修正值,有符号,单位mm/s

if(pConfig->FlowSpeedCorrectionLe < -29999) pConfig->FlowSpeedCorrectionLe = -29999;//流速修正值,有符号,单位mm/s

//u16 AcqCycle; //采集周期,单位秒

//u16 Filter[16][2]; //滤波器,预留16个滤波器,可以进行干扰频率过滤

//u8 SlaveAddr; //设备通信地址

//u8 WaterLevelAddr; //水位计通信地址

//u8 WaterLevelSelectIndex; //水位计选择


if(pConfig->FreqFilter < 20) pConfig->FreqFilter = 20; //频率差值滤波,IQ通道的频率差值超出范围后进行滤波

if(pConfig->FlowSpeedFilterCnt > 100) pConfig->FlowSpeedFilterCnt = 100; //流速滤波次数

if(pConfig->FlowRateFilterCnt > 100) pConfig->FlowRateFilterCnt = 100; //流量滤波次数

if(pConfig->FlowDireFilterCnt > 100) pConfig->FlowDireFilterCnt = 100; //流量方向滤波次数

if(pConfig->ProtectTempL < -99) pConfig->ProtectTempL = 99; //设备保护温度低温度值

if(pConfig->ProtectTempL > 0) pConfig->ProtectTempL = 0; //设备保护温度低温度值

if(pConfig->ProtectTempH < 20) pConfig->ProtectTempH = 20; //设备保护温度高温度值

if(pConfig->ProtectTempH > 99) pConfig->ProtectTempH = 99; //设备保护温度高温度值


return TRUE;

}



/*************************************************************************************************************************

* 函数 : void CONFIG_Default(CONFIG_TYPE *pConfig, bool isAdmin)

* 功能 : 恢复配置为出厂模式

* 参数 : isAdmin:是否为管理员模式

* 返回 : 无

* 依赖 : flash操作函数

* 作者 : cp1300@139.com

* 时间 : 2014-10-18

* 最后修改时间 : 2017-03-21

* 说明 : 不会进行存储

*************************************************************************************************************************/

void CONFIG_Default(CONFIG_TYPE *pConfig, bool isAdmin)

{

int i;


pConfig->ID = DEVICE_BOARD_CONFIG_ID; //首先设置配置ID

if(isAdmin == TRUE) 

{

pConfig->SN[0] = 0; //清除SN

}

else

{

pConfig->SN[15] = 0; //唯一序列号-不能进行随意修改

}


/*********************************************************************************************************************************************************************/

pConfig->HorizAngle = 0; //设备安装的水平夹角,保留3位小数-0为自动

pConfig->ThresholdEnergy = 12000; //阈值能量,低于阈值的将会进行过滤

pConfig->WaterLevelHeight = 0; //水位计安装高度

pConfig->WaterCorrParame = 1.0*10000; //水位计线性修正值,4位小数点

pConfig->WaterCorrectionLe = 0; //水位修正值,有符号,单位mm


pConfig->WarmTime = 5; //预热时间,单位S,0-999

pConfig->FlowSpeedCorrParame = 1.0*10000; //流速线性修正值,4位小数点

pConfig->FlowSpeedCorrectionLe = 0; //流速修正值,有符号,单位mm/s

pConfig->AcqCycle = 0; //采集周期,单位秒0:连续采集

//滤波器,预留16个滤波器,可以进行干扰频率过滤

for(i = 0;i < 16;i ++)

{

pConfig->Filter[i][0] = 0;

pConfig->Filter[i][1] = 0;

}

pConfig->SlaveAddr = 1; //设备默认通信地址

pConfig->WaterLevelAddr = 1; //水位计通信地址

pConfig->WaterLevelSelectIndex = 0; //水位计选择

pConfig->FreqFilter = 60; //频率差值滤波,IQ通道的频率差值超出范围后进行滤波

pConfig->FlowSpeedFilterCnt = 20; //流速滤波次数

pConfig->FlowRateFilterCnt = 20; //流量滤波次数

pConfig->FlowDireFilterCnt = 10; //流量方向滤波次数

pConfig->ProtectTempH = 90; //设备保护温度高温度值

pConfig->ProtectTempL = -30; //设备保护温度低温度值

}

 

 

 

/*************************************************************************************************************************

* 函数 : bool CONFIG_SaveConfig(CONFIG_TYPE *pConfig)

* 功能 : 存储配置数据到flash

* 参数 : pConfig:配置存储缓冲区

* 返回 : FALSE:失败;TRUE:成功

* 依赖 : flash操作函数

* 作者 : cp1300@139.com

* 时间 : 2013-10-22

* 最后修改时间 : 2018-01-17

* 说明 : 只能一次存储所有的配置数据

配置数据应该小于1个页大小

STM32F407配置写入基本原理:将一个64KB的扇区分为多个写入区域,比如64个,索引为0-63,如果当前存储的索引为63,则直接擦除扇区,索引变为0

下次写入时,索引+1,同时检查待写入区域是否全部为FF,否则执行擦除,并将索引变为0,重复此循环,理论上可以写64次配置才擦除一次,可以有效的提高扇区利用率

以及降低flash擦除次数,提高flash寿命。

*************************************************************************************************************************/

static bool CONFIG_SaveConfig(CONFIG_TYPE *pConfig)

{

u32 addr;

u16 count;

STM32FLASH_STATUS status;

u32 temp;

bool isFistIndex = FALSE; //是否需要从索引0开始,并擦除当前扇区

int i;


count = STM32_CONFIG_PAGE_SIZE/CONFIG_MAX_SIZE; //计算配置扇区可以存放配置数据的条数

if(gs_ConfigSaveIndex == (count-1)) //当前存储为最后一个索引了,从0开始存储

{

isFistIndex = TRUE; //需要写入到首个扇区

}

else //需要判断是否为FF

{

gs_ConfigSaveIndex ++; //存储索引位置自增

for(i = 0;i < (sizeof(CONFIG_TYPE)/sizeof(u32));i ++)

{

addr = STM32_CONFIG_PAGE_ADDR+gs_ConfigSaveIndex*CONFIG_MAX_SIZE+i*4; //计算需要读取的地址

STM32FLASH_Read(addr, &temp, 4/sizeof(u32));

if(temp != 0xFFFFFFFF)

{

uart_printf("存储区域发现非0部分,需要擦除,当前索引:%d\r\n",gs_ConfigSaveIndex);

gs_ConfigSaveIndex = 0; //索引变为0

break;

}

}

if(gs_ConfigSaveIndex == 0) //需要擦除

{

isFistIndex = TRUE; //需要写入到首个扇区

}

}


if(isFistIndex== TRUE) //需要写入到首个扇区

{

//先擦除

status = STM32FLASH_EraseSector(STM32_CONFIG_PAGE_INDEX);   //擦除扇区

if(status == STM32FLASH_OK)

{

uart_printf("擦除配置扇区%d成功\r\n",STM32_CONFIG_PAGE_INDEX);

}

else

{

uart_printf("擦除配置扇区%d失败\r\n",STM32_CONFIG_PAGE_INDEX);

}

//写入数据

addr = STM32_CONFIG_PAGE_ADDR+gs_ConfigSaveIndex*CONFIG_MAX_SIZE; //计算需要写入的地址

status = STM32FLASH_Write_NoCheck(addr,(u32 *)&g_SYS_Config,sizeof(CONFIG_TYPE)/sizeof(u32)) ; //不检查的写入-写入配置到flash

gs_ConfigSaveIndex = 0; //索引变为0

}

else //非首个扇区写入-并且无需擦除,前面已经做好了检查,直接写入即可

{

addr = STM32_CONFIG_PAGE_ADDR+gs_ConfigSaveIndex*CONFIG_MAX_SIZE; //计算需要写入的地址

status = STM32FLASH_Write_NoCheck(addr,(u32 *)&g_SYS_Config,sizeof(CONFIG_TYPE)/sizeof(u32)) ; //不检查的写入-写入配置到flash

}

//判断是否写入成功

if(status == STM32FLASH_OK)

{

uart_printf("存储配置成功,索引:%d\r\n",gs_ConfigSaveIndex);

return TRUE;

}

else

{

uart_printf("存储配置失败,索引:%d(错误:%d)\r\n",gs_ConfigSaveIndex, status);

return FALSE;

}

}

 

 

 

 

 

/*************************************************************************************************************************

* 函数 : bool CONFIG_WriteConfig(CONFIG_TYPE *pConfig)

* 功能 : 更新写入配置(不会修改SN)

* 参数 : pConfig:配置存储缓冲区

* 返回 : FALSE:失败;TRUE:成功

* 依赖 : flash操作函数

* 作者 : cp1300@139.com

* 时间 : 2017-04-05

* 最后修改时间 : 2017-04-05

* 说明 : 用于更新系统配置,并且写入配置到flash,不检查配置,需要提前进行验证配置

*************************************************************************************************************************/

bool CONFIG_WriteConfig(CONFIG_TYPE *pConfig)

{

int i;


/****************************************头部的注册相关信息,不管什么设备的配置开头必须是以下格式************************************************************************************/

g_SYS_Config.ID = DEVICE_BOARD_CONFIG_ID; //ID,标记是否进行过配置

g_SYS_Config.SN[15] = 0; //唯一序列号-不能进行随意修改

/*********************************************************************************************************************************************************************/

g_SYS_Config.HorizAngle = pConfig->HorizAngle ; //设备安装的水平夹角,保留3位小数

g_SYS_Config.ThresholdEnergy = pConfig->ThresholdEnergy; //阈值能量,低于阈值的将会进行过滤

g_SYS_Config.WaterLevelHeight = pConfig->WaterLevelHeight; //水位计安装高度

g_SYS_Config.WaterCorrParame = pConfig->WaterCorrParame; //水位计线性修正值,4位小数点

g_SYS_Config.WaterCorrectionLe = pConfig->WaterCorrectionLe; //水位修正值,有符号,单位mm


g_SYS_Config.WarmTime = pConfig->WarmTime; //预热时间,单位S,0-999

g_SYS_Config.FlowSpeedCorrParame = pConfig->FlowSpeedCorrParame; //流速线性修正值,4位小数点

g_SYS_Config.FlowSpeedCorrectionLe = pConfig->FlowSpeedCorrectionLe; //流速修正值,有符号,单位mm

g_SYS_Config.AcqCycle = pConfig->AcqCycle; //采集周期,单位秒

for(i = 0;i < 16;i ++)

{

g_SYS_Config.Filter[i][0] = pConfig->Filter[i][0]; //滤波器,预留16个滤波器,可以进行干扰频率过滤

g_SYS_Config.Filter[i][1] = pConfig->Filter[i][1]; //滤波器,预留16个滤波器,可以进行干扰频率过滤

}



g_SYS_Config.SlaveAddr = pConfig->SlaveAddr; //设备通信地址

g_SYS_Config.WaterLevelAddr = pConfig->WaterLevelAddr; //水位计通信地址

g_SYS_Config.WaterLevelSelectIndex = pConfig->WaterLevelSelectIndex; //水位计选择

g_SYS_Config.FreqFilter = pConfig->FreqFilter; //频率差值滤波,IQ通道的频率差值超出范围后进行滤波

g_SYS_Config.FlowSpeedFilterCnt = pConfig->FlowSpeedFilterCnt; //流速滤波次数

g_SYS_Config.FlowRateFilterCnt = pConfig->FlowRateFilterCnt; //流量滤波次数

g_SYS_Config.FlowDireFilterCnt = pConfig->FlowDireFilterCnt; //流量方向滤波次数

g_SYS_Config.ProtectTempH = pConfig->ProtectTempH; //设备保护温度高温度值

g_SYS_Config.ProtectTempL = pConfig->ProtectTempL; //设备保护温度低温度值


 

return CONFIG_SaveConfig(&g_SYS_Config);

}

 

 

 

/*************************************************************************************************************************

* 函数 : bool CONFIG_WriteSN(char pSN[16])

* 功能 : 修改SN

* 参数 : pSN:SN

* 返回 : FALSE:失败;TRUE:成功

* 依赖 : flash操作函数

* 作者 : cp1300@139.com

* 时间 : 2017-04-05

* 最后修改时间 : 2018-01-31

* 说明 : 不会检查SN合法性

*************************************************************************************************************************/

bool CONFIG_WriteSN(char pSN[16])

{

g_SYS_Config.ID = DEVICE_BOARD_CONFIG_ID; //ID,标记是否进行过配置

pSN[15] = 0;

strcpy(g_SYS_Config.SN, pSN); //唯一序列号-不能进行随意修改


return CONFIG_SaveConfig(&g_SYS_Config);

}

 

 

 

 

/*************************************************************************************************************************

* 函数 : bool CONFIG_CheckSN(char pSN[16])

* 功能 : 检查SN的有效性

* 参数 : pSN:序列号存储缓冲区

* 返回 : TRUE:有效;FALSE:无效,没有配置SN

* 依赖 : flash操作函数

* 作者 : cp1300@139.com

* 时间 : 2014-10-18

* 最后修改时间 : 2018-01-17

* 说明 : 检查SN的有效性

*************************************************************************************************************************/

bool CONFIG_CheckSN(char pSN[16])

{

u8 i;


pSN[15] = '\0';

if(strlen(pSN) != 15) return FALSE;

for(i = 5;i < 15;i ++)

{

if((pSN[i] < '0') || (pSN[i] > '9'))

{

return FALSE;

}

}

return TRUE;

}

 

 

//Device_Config.h


/*************************************************************************************************************

 * 文件名: Device_Config.h

 * 功能: 设备配置相关

 * 作者: cp1300@139.com

 * 创建时间: 2018-01-13

 * 最后修改时间: 2018-01-13

 * 详细: 设备配置相关

*************************************************************************************************************/

#ifndef _DEVICE_CONFIG_H_

#define _DEVICE_CONFIG_H_

#include "system.h"

#include "rtc.h"

#include "board.h"

 

//配置相关,用于内部flash

//必须保证为4字节对其,并且大小必须是4的整数倍

#define DEVICE_BOARD_CONFIG_ID 0xA5A87A6E //标记ID

typedef struct

{

/****************************************头部的注册相关信息,不管什么设备的配置开头必须是以下格式************************************************************************************/

u32 ID; //ID,标记是否进行过配置

char SN[16]; //唯一序列号-不能进行随意修改

/*********************************************************************************************************************************************************************/

u32 HorizAngle; //设备安装的水平夹角,保留3位小数

u32 ThresholdEnergy; //阈值能量,低于阈值的将会进行过滤

u32 WaterLevelHeight; //水位计安装高度

u32 WaterCorrParame; //水位计线性修正值,4位小数点

s32 WaterCorrectionLe; //水位修正值,有符号,单位mm

u32 Reserved32[4]; //预留

u16  WarmTime; //预热时间,单位S,0-999

u16 FlowSpeedCorrParame; //流速线性修正值,4位小数点

s16 FlowSpeedCorrectionLe; //流速修正值,有符号,单位mm/s

u16 AcqCycle; //采集周期,单位秒

u16 Filter[16][2]; //滤波器,预留16个滤波器,可以进行干扰频率过滤

u16 Reserved16[4]; //预留

u8 SlaveAddr; //设备通信地址

u8 WaterLevelAddr; //水位计通信地址

u8 WaterLevelSelectIndex; //水位计选择

u8 FreqFilter; //频率差值滤波,IQ通道的频率差值超出范围后进行滤波

u8 FlowSpeedFilterCnt; //流速滤波次数

u8 FlowRateFilterCnt; //流量滤波次数

u8 FlowDireFilterCnt; //流量方向滤波次数

s8 ProtectTempH; //设备保护温度高温度值

s8 ProtectTempL; //设备保护温度低温度值

u8 Reserve8[2]; //保留

/////////////////////////////////////////////////////////////////////////////////////

}CONFIG_TYPE;

extern CONFIG_TYPE g_SYS_Config; //系统配置

 

bool CONFIG_WriteSN(char pSN[16]); //修改SN;

void CONFIG_Default(CONFIG_TYPE *pConfig, bool isAdmin); //恢复配置为出厂模式

bool CONFIG_Check(CONFIG_TYPE *pConfig,bool isCheckID); //检查配置参数是否合法

void CONFIG_Init(void); //初始化配置

bool CONFIG_WriteConfig(CONFIG_TYPE *pConfig); //写入配置,用于远程或上位机更新配置

bool CONFIG_CheckSN(char pSN[16]); //检查SN的有效性

 

 

 

#endif /*_DEVICE_CONFIG_H_*/




『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
ARM 汇编的必知必会