吃透 AM32 无人机电调:从源码架构到工作原理的全方位解析(附实践指南)(下)

第三章 核心模块源码逐行解析:从 “初始化” 到 “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表中的默认值,保证电调能正常启动。

3.6 校准模块

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值