软件设计
略
使用说明
参数表定义
复制
typedef struct
{
uint16_t usValue;
uint8_t ucValue;
uint32_t uiValue;
float fValue;
char szString_1[12];
double dValue;
int16_t sValue;
int8_t cValue;
int32_t iValue;
char szString_2[10];
}ParamDemo_t;
ParamDemo_t g_tTestVal = {
.usValue = 20,
.ucValue = 10,
.uiValue = 1000,
.fValue = 3.14,
.szString_1 = "abcd",
.dValue = 5.12,
.sValue = -100,
.cValue = -2,
.iValue = 300,
.szString_2 = "12234",
};
int8_t g_cTest = 50;
char g_szString[10] = "qwer";
static int CheckSValue(const void *pCurParam);
cotParamInfo_t sg_ParamTable[] = {
COT_PARAM_ITEM_BIND(1, g_tTestVal.usValue, COT_PARAM_UINT16, COT_PARAM_ATTR_WR),
COT_PARAM_ITEM_BIND(2, g_tTestVal.ucValue, COT_PARAM_UINT8, COT_PARAM_ATTR_WR, 20),
COT_PARAM_ITEM_BIND(3, g_tTestVal.uiValue, COT_PARAM_UINT32, COT_PARAM_ATTR_WR, 1000, 1000, 10000),
COT_PARAM_ITEM_BIND(4, g_tTestVal.fValue, COT_PARAM_FLOAT, COT_PARAM_ATTR_WR, 10, -10.5, 10.5),
COT_PARAM_ITEM_BIND(5, g_tTestVal.szString_1, COT_PARAM_STRING, COT_PARAM_ATTR_WR, "abcd", 3, sizeof(g_tTestVal.szString_1)),
COT_PARAM_ITEM_BIND(6, g_tTestVal.dValue, COT_PARAM_DOUBLE, COT_PARAM_ATTR_WR, 0, -90.10, 100.10),
COT_PARAM_ITEM_BIND(7, g_tTestVal.sValue, COT_PARAM_INT16, COT_PARAM_ATTR_WR, 100, -200, 200, CheckSValue), // 添加自定义校验
COT_PARAM_ITEM_BIND_WITH_NAME(8, "g_cTest", g_cTest, COT_PARAM_INT8, COT_PARAM_ATTR_WR, 50, -100, 100), // 另取参数名
COT_PARAM_ITEM_BIND(9, g_szString, COT_PARAM_STRING, COT_PARAM_ATTR_WR, "XXX", 3, 6),
};
static int CheckSValue(const void *pCurParam)
{
const int16_t *p_sValue = (const int16_t *)pCurParam;
if ((*p_sValue) % 2 != 0)
{
return -1;
}
return 0;
}
int mian()
{
cotParam_Init(&sg_tParamManager, sg_ParamTable, COT_PARAM_TABLE_SIZE(sg_ParamTable));
}
参数保存/加载
将参数表的部分信息(包括当前值)进行序列化,方便进行数据保存,等下次开机再读取数据后反序列化,还原成参数表的这部分信息。
甚至将这部分数据传输给另一台设备,进行参数数据备份或同步等功能
将参数表序列化完成后,可以对数据进行二次封装,比如可以增加头信息,crc校验等再进行数据保存,同样在加载时也需要解析,将额外添加的信息去除后才能进行反序列化。
第一种
提供参数数据保存/加载的回调函数,调用相关接口函数完成参数的序列化保存和反序列化加载;该方式会多次触发回调函数保存数据和读取数据,适用于小内存的平台使用(不需要额外申请内存)
复制
// 所有参数校验出错时恢复默认处理
int OnCheckErrorResetHandle(const cotParamInfo_t *pParamInfo, cotParamCheckRet_e eCheckResult)
{
cotParam_SingleParamResetDefValue(pParamInfo);
return 0;
}
// 从储存空间读取数据
int OnLoadCallback(uint8_t *pBuf, uint16_t bufSize, uint16_t *pLength)
{
uint16_t length;
static uint32_t s_offset = 0;
if (s_offset < sg_length)
{
if (s_offset + bufSize <= sg_length)
{
length = bufSize;
memcpy(pBuf, &sg_buf[s_offset], length);
s_offset += length;
}
else
{
length = sg_length - s_offset;
memcpy(pBuf, &sg_buf[s_offset], length);
s_offset += length;
}
}
else
{
length = 0;
s_offset = 0;
}
*pLength = length;
return 0;
}
// 写数据至储存空间
int OnSaveCallback(const uint8_t *pBuf, uint16_t len)
{
static uint32_t s_offset = 0;
if (len > 0)
{
memcpy(&sg_buf[s_offset], pBuf, len);
s_offset += len;
sg_length = s_offset;
}
else
{
s_offset = 0;
}
return 0;
}
// 加载参数
void LoadParam(void)
{
cotParam_Load(&sg_tParamManager, OnLoadCallback);
// 加载后全部参数进行校验(可选)
cotParam_Check(&sg_tParamManager, OnCheckErrorResetHandle);
}
// 保存参数
void SaveParam(void)
{
// 保存前全部参数进行校验(可选)
cotParam_Check(&sg_tParamManager, OnCheckErrorResetHandle);
cotParam_Save(&sg_tParamManager, OnSaveCallback);
}
第二种
需要提前申请内存用来保存参数表序列化的数据或者读取即将反序列化的数据。
定义buf
复制
// 加载参数
void LoadParam(void)
{
uint8_t buf[500];
uint32_t length;
length = read(buf);
cotParam_Deserialization(&sg_tParamManager, buf, length);
// 加载后全部参数进行校验(可选)
cotParam_Check(&sg_tParamManager, OnCheckErrorResetHandle);
}
// 保存参数
void SaveParam(void)
{
uint8_t buf[500];
uint32_t length;
// 保存前全部参数进行校验(可选)
cotParam_Check(&sg_tParamManager, OnCheckErrorResetHandle);
length = cotParam_Serialize(&sg_tParamManager, buf);
write(buf, length);
}
buf通过内存申请
复制
// 加载参数
void LoadParam(void)
{
uint8_t pBuf = (uint8_t *)malloc(500); // 申请足够大的内存
uint32_t length;
length = read(pBuf, length); // 获取数据的实际长度
cotParam_Deserialization(&sg_tParamManager, pBuf, length);
// 加载后全部参数进行校验(可选)
cotParam_Check(&sg_tParamManager, OnCheckErrorResetHandle);
}
// 保存参数
void SaveParam(void)
{
uint8_t pBuf = (uint8_t *)malloc(cotParam_GetSerializeSize(&sg_tParamManager));
uint32_t length;
// 保存前全部参数进行校验(可选)
cotParam_Check(&sg_tParamManager, OnCheckErrorResetHandle);
length = cotParam_Serialize(&sg_tParamManager, pBuf);
write(buf, length);
}
int main()
{
// 保存
uint8_t *p_wbuf = (uint8_t *)malloc(cotParam_GetSerializeSize(&sg_tParamManager));
uint32_t length = cotParam_Serialize(&sg_tParamManager, p_wbuf);
write(p_wbuf, length);
free(p_wbuf);
p_wbuf = NULL;
// 加载
uint8_t *p_rbuf = (uint8_t *)malloc(cotParam_GetSerializeSize(&sg_tParamManager));
uint32_t length = read(r_buf);
cotParam_Deserialization(&sg_tParamManager, p_rbuf, length);
write(p_rbuf, length);
free(p_rbuf);
p_rbuf = NULL;
}
校验方式
校验需要提前在参数表中设置缺省值,最小值和最大值后才有效。 |