第三章 核心模块源码逐行解析:从 “初始化” 到 “FOC 控制”
3.5 参数管理模块:“电调的‘记忆大脑’”
3.5.3 参数管理源码实现
c
运行
case PARAM_OVERVOLTAGE_LIMIT:
case PARAM_UNDERVOLTAGE_LIMIT:
flash_read_data(param_addr + 1, buf, 2); // 2字节参数
default_val = (buf[1] << 8) | buf[0]; // 高字节在后,低字节在前
found = 1;
break;
default:
break;
}
break;
}
// 移动到下一个参数(1字节ID + 数据长度)
switch (id)
{
case PARAM_MOTOR_POLES:
case PARAM_OVERTEMP_LIMIT:
case PARAM_START_POWER:
param_addr += 2; // 1字节ID + 1字节数据
break;
case PARAM_IQ_KP:
case PARAM_IQ_KI:
case PARAM_IQ_KD:
case PARAM_OVERCURRENT_LIMIT:
case PARAM_OVERVOLTAGE_LIMIT:
case PARAM_UNDERVOLTAGE_LIMIT:
param_addr += 3; // 1字节ID + 2字节数据
break;
default:
param_addr += 1; // 未知参数,跳过1字节
break;
}
}
// 未找到参数,返回默认值
if (!found)
{
// 从默认值表中查找更精准的默认值
for (uint8_t i = 0; param_defaults[i].id != PARAM_END; i++)
{
if (param_defaults[i].id == param_id)
{
default_val = param_defaults[i].default_val;
break;
}
}
}
return default_val;
}
/**
* @brief 参数保存:将参数写入Flash参数区
* @param param_id:参数ID
* @param value:参数值
* @return 0=成功,1=失败
*/
uint8_t param_save(uint8_t param_id, uint32_t value)
{
// 1. 读取当前参数区所有参数(除了要更新的参数)
uint8_t old_params[PARAM_FLASH_PAGE_SIZE] = {0};
uint16_t old_params_len = 0;
uint32_t param_addr = PARAM_FLASH_PAGE_ADDR;
while (param_addr < PARAM_FLASH_PAGE_ADDR + PARAM_FLASH_PAGE_SIZE)
{
uint8_t id;
flash_read_data(param_addr, &id, 1);
if (id == PARAM_END) break; // 到达参数表末尾
if (id == param_id)
{
// 跳过要更新的参数
switch (id)
{
case PARAM_MOTOR_POLES:
case PARAM_OVERTEMP_LIMIT:
case PARAM_START_POWER:
param_addr += 2;
break;
case PARAM_IQ_KP:
case PARAM_IQ_KI:
case PARAM_IQ_KD:
case PARAM_OVERCURRENT_LIMIT:
case PARAM_OVERVOLTAGE_LIMIT:
case PARAM_UNDERVOLTAGE_LIMIT:
param_addr += 3;
break;
default:
param_addr += 1;
break;
}
}
else
{
// 保存其他参数
old_params[old_params_len++] = id;
switch (id)
{
case PARAM_MOTOR_POLES:
case PARAM_OVERTEMP_LIMIT:
case PARAM_START_POWER:
flash_read_data(param_addr + 1, &old_params[old_params_len], 1);
old_params_len += 1;
param_addr += 2;
break;
case PARAM_IQ_KP:
case PARAM_IQ_KI:
case PARAM_IQ_KD:
case PARAM_OVERCURRENT_LIMIT:
case PARAM_OVERVOLTAGE_LIMIT:
case PARAM_UNDERVOLTAGE_LIMIT:
flash_read_data(param_addr + 1, &old_params[old_params_len], 2);
old_params_len += 2;
param_addr += 3;
break;
default:
param_addr += 1;
break;
}
}
}
// 2. 擦除参数区Flash页(必须先擦除才能写入新数据)
if (flash_erase_page() != HAL_OK)
{
return 1; // 擦除失败
}
// 3. 写入旧参数 + 新参数 + 结束标志
uint8_t new_params[PARAM_FLASH_PAGE_SIZE] = {0};
uint16_t new_params_len = 0;
// 复制旧参数
memcpy(new_params, old_params, old_params_len);
new_params_len = old_params_len;
// 写入新参数
new_params[new_params_len++] = param_id; // 参数ID
switch (param_id)
{
case PARAM_MOTOR_POLES:
case PARAM_OVERTEMP_LIMIT:
case PARAM_START_POWER:
new_params[new_params_len++] = (uint8_t)value; // 1字节数据
break;
case PARAM_IQ_KP:
case PARAM_IQ_KI:
case PARAM_IQ_KD:
case PARAM_OVERCURRENT_LIMIT:
case PARAM_OVERVOLTAGE_LIMIT:
case PARAM_UNDERVOLTAGE_LIMIT:
new_params[new_params_len++] = (uint8_t)(value & 0xFF); // 低字节
new_params[new_params_len++] = (uint8_t)(value >> 8); // 高字节
break;
default:
return 1; // 未知参数,保存失败
}
// 写入结束标志
new_params[new_params_len++] = PARAM_END;
// 4. 将新参数写入Flash
if (flash_write_data(PARAM_FLASH_PAGE_ADDR, new_params, new_params_len) != HAL_OK)
{
return 1; // 写入失败
}
return 0; // 保存成功
}
/**
* @brief 批量保存所有参数(如校准完成后调用)
*/
void param_save_all(void)
{
// 依次保存常用参数(示例)
param_save(PARAM_MOTOR_POLES, motor_poles);
param_save(PARAM_IQ_KP, iq_pid.kp);
param_save(PARAM_IQ_KI, iq_pid.ki);
param_save(PARAM_IQ_KD, iq_pid.kd);
param_save(PARAM_OVERCURRENT_LIMIT, prot.config.overcurrent_limit);
// 其他参数...
}
代码解析:
- Flash 操作流程:遵循 “读旧参数→擦除页→写新参数” 的流程,确保参数更新时不丢失其他配置;
- 参数格式兼容:按 “1 字节 ID + 数据” 的格式存储,不同长度的参数(1 字节 / 2 字节)分开处理,提高存储空间利用率;
- 默认值机制:若 Flash 中无参数(如首次上电),自动加载
param_defaults表中的默认值,保证电调能正常启动。

最低0.47元/天 解锁文章
1358

被折叠的 条评论
为什么被折叠?



