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

发布者:breakthrough2最新更新时间:2018-12-25 来源: eefocus关键字:STM32F4  内部flash  存放配置  优化存储 手机看文章 扫描二维码
随时随地手机看文章

由于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_*/



关键字:STM32F4  内部flash  存放配置  优化存储 引用地址:STM32F4 内部flash存放配置(优化存储)

上一篇:stm32f207/stm32f407擦除内部flash讲解
下一篇:STM32F407.FLASH 读写经验

推荐阅读最新更新时间:2024-03-16 16:21

STM32F401+nRF24L01无线传输音频(对讲机原型)
尝试结合STM32F401的ADC, PWM, SPI(NRF24L01)和TIM, 试验了一下音频的无线传输(对讲机原型) 工作机制 音频采样 因为硬件的限制, 包括STM32F401片内存储, 内存大小, PWM频率, 以及之前实际测试NRF24L01得到的经验数据, 采样使用了最基础的8bit分辨率, 采样频率为16KHz附近 SYSCLK使用25MHz, APB2CLK使用一半频率, 即12.5MHz ADC在APB2CLK基础上8分频, 所以ADC时钟为12.5MHz/8 ADC使用8bit分辨率, 对应11个ADC时钟, 采样周期设置为84, 所以每次采样为95个ADC周期, 这样实际采样频率为 1250000
[单片机]
<font color='red'>STM32F4</font>01+nRF24L01无线传输音频(对讲机原型)
stm32f407之CAN控制器(操作寄存器)
CAN控制器 首先简单介绍一下CAN总线,关于CAN总线是谁发明的,CAN总线的历史,CAN总线的发展,CAN总线的应用场合,这些,通通不说。这里只是以我个人理解,简单说说CAN通信。CAN总线的端点没有地址(除非自己在帧里定义地址),CAN总线通信不用地址,用标识符,不是单独的谁发给谁,而是,你总是发送给整个网络。然后每个节点都有过滤器,对网络上的传播的帧的标识符进行过滤,自己想要什么样的帧,可以设置自己的过滤器,接收相关的帧信息。如果两个节点同时发送怎么办?这个不用我们担心,CAN控制器会自己仲裁,让高优先级的帧先发。 然后我们可以了解一下stm32的CAN控制器。 如上图所示,stm32有
[单片机]
<font color='red'>stm32f4</font>07之CAN控制器(操作寄存器)
stm32f407之DMA(操作寄存器)
八、DMA 直接内存访问(DMA)是用来以提供外设和内存、内存和内存之间的高速数据传输的。数据可以在没有任何CPU干预下通过的DMA进行传输。这使得CPU资源更倾重与其他操作。 DMA控制器基于一个复杂的总线矩阵架构,结合了功能强大的双AHB主总线架构与独立的FIFO,以优化系统带宽。 两个DMA控制器共有16个数据流(stream),每个数据流可以编程与规定的通道中的一个搭配。 DMA的工作模式 1. 单次传输 2. 多次传输(burst):把数据分成多次传输 DMA的工作模式 1. 循环模式:循环模式是可用来处理循环缓冲区和连续的数据流(如ADC扫描模式)。启此功能可以设置DMA_SxC
[单片机]
<font color='red'>stm32f4</font>07之DMA(操作寄存器)
STM32F407-用TB6600驱动器驱动57步进电机
一、硬件 1.硬件准备 57步进电机(型号57CM18),驱动器TB6600,开发板STM32F407ZGT6 2.电气特性 3.连线 驱动器右边分有两个区域 Signal:用于驱动器与开发板连接,进行电机的控制驱动。 ENA接口:当此信号有效时,驱动器将自动切断电机绕组电流,使电机处于自由状态(无保持转矩)。当此信号不连接时默认为无效状态,这时电机绕组通以电流,可正常工作。 DIR接口:控制电机旋转方向,信号有效时电机顺时针旋转,无效时逆时针旋转。 PUL接口:步进电机驱动器把控制器发出的脉冲信号转化为步进电机的角位移,驱动器每接受一个脉冲信号 PUL,就驱动步进电机旋转一个步距角,PUL 的频率和步进电机的转速
[单片机]
<font color='red'>STM32F4</font>07-用TB6600驱动器驱动57步进电机
STM32F407的定时器1之7路PWM输出
实验现象:输出频率为10K /**************************************************************************************** *函 数 名:bsp_InitTimer1GPIO *函数功能:初始化定时器1相关IO *形 参:无 *返 回 值:无 *****************************************************************************************/ void bsp_InitTimer1GPIO(void) { GPIO_InitTypeDef GPIO_InitStru
[单片机]
关于STM32F4中的时钟树
很多同学在学习单片机的时候都有遇到过一个东西,那就是晶振。其实这个所谓的晶振全名叫做晶体振荡器,其作用是用于产生原始的时钟频率,晶振产生的频率经过频率发生器的放大或缩小后就成了计算机中各种不同的总线频率 ,用于计算机中各个不同的外设工作,常用晶振的模样如下图所示: 一、什么是时钟频率 计算机是一个由各种集成电路和电子器件组成,每一块集成电路中都集成了数以万计的晶体管和其他电子元件。这样一个十分庞大的系统,要使它能够正常地工作,就必须有一个指挥者,对各部分的工作进行协调。各个元件的动作就是在这个指挥下按不同的先后顺序完成自己的操作的,这个先后顺序我们称为时序。时序是计算机中一个非常重要的概念,如果时序出现错误,就会使系统发
[单片机]
关于<font color='red'>STM32F4</font>中的时钟树
STM32F40x 内部温度获取
#include ADC.h //user guide // in board init, call function: adc_init(); // get_internal_temperture(); get tempertare, uinit℃ static void AdcPinComInit(void) { ADC_CommonInitTypeDef ADC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 , ENABLE); ADC_InitStructure.ADC_Mode = ADC_DualMode_RegSimult; A
[单片机]
e络盟使STM32F4 Discovery MCU开发套件实现无线网络连接
e络盟近日宣布提供用于意法半导体(ST)STM32F4 Discovery微控制器开发套件的Discover Wi-Fi开发板,以实现无线连接。Discover Wi-Fi开发板采用Murata SN8200无线网络控制器模块,可提供板载Wi-Fi功能及网络软件栈,是各种高性能、低功耗无线解决方案的完美选择。 Discover Wi-Fi开发板插入意法半导体的STM32F4 Discovery套件后,借助UART和SPI命令接口以及工作频段在2.4 GHz的 IEEE802.11b/g/n标准可提供一系列的广泛功能。Discover Wi-Fi开发板还配备源代码、文档及软件演示,有利于快速启动无线网络项目。 亚太区用户现可
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved