BLOG8
跳转至

嵌入式系统电源设计基础

学习目标

完成本文学习后,你将能够:

  • 理解嵌入式系统电源设计的基本原则和流程
  • 掌握电源需求分析的方法和技巧
  • 能够设计合理的电源架构和电源树
  • 学会进行功耗预算和计算
  • 了解电源时序的重要性和设计方法
  • 掌握典型电源架构的设计案例

前置要求

在开始本文学习之前,你需要:

知识要求: - 了解基本的电学概念(电压、电流、功率) - 熟悉欧姆定律和功率计算公式 - 了解常见的电源元件(LDO、DC-DC、电容等) - 有一定的电路图阅读能力

技能要求: - 能够阅读电路原理图 - 了解基本的电路符号 - 熟悉常用的单位换算(V、A、W)

推荐但非必需: - 有使用万用表测量电压电流的经验 - 了解微控制器的基本工作原理 - 熟悉常见的嵌入式开发板

概述

电源系统是嵌入式系统的"心脏",为所有电路提供稳定可靠的能量供应。一个设计良好的电源系统不仅能保证系统正常工作,还能提高效率、降低功耗、延长电池寿命。

为什么电源设计如此重要

  1. 系统稳定性:
  2. 电源波动会导致系统复位或死机
  3. 纹波噪声会影响模拟电路精度
  4. 电源故障可能损坏芯片

  5. 功耗优化:

  6. 合理的电源架构可以降低功耗
  7. 电源效率直接影响电池寿命
  8. 功耗管理是移动设备的关键

  9. 成本控制:

  10. 电源元件占据较大成本比例
  11. 合理选型可以降低BOM成本
  12. 避免过度设计

  13. EMC性能:

  14. 电源噪声是EMI的主要来源
  15. 良好的电源设计可以改善EMC
  16. 减少后期整改成本

电源设计的基本流程

需求分析 → 架构设计 → 元件选型 → 电路设计 → 仿真验证 → 原型测试 → 优化改进
    ↓          ↓          ↓          ↓          ↓          ↓          ↓
 功耗预算   电源树    稳压器     PCB布局    效率分析   实测验证   性能优化

第一部分:电源需求分析

什么是电源需求分析

电源需求分析是电源设计的第一步,需要明确系统中所有元件的电源需求,包括电压、电流、功率等参数。

需求分析的核心内容:

  1. 电压需求:
  2. 确定所需的电压等级(3.3V、5V、12V等)
  3. 电压精度要求(±5%、±3%、±1%)
  4. 电压范围(最小值、典型值、最大值)

  5. 电流需求:

  6. 静态电流(待机状态)
  7. 动态电流(工作状态)
  8. 峰值电流(瞬态负载)

  9. 功率需求:

  10. 平均功耗
  11. 峰值功耗
  12. 热设计功耗(TDP)

如何进行需求分析

步骤1:列出所有用电元件

创建一个完整的元件清单,包括:

元件清单示例:
┌──────────────┬─────────┬──────────┬──────────┬─────────┐
│ 元件名称     │ 电压(V) │ 电流(mA) │ 功率(mW) │ 数量    │
├──────────────┼─────────┼──────────┼──────────┼─────────┤
│ MCU (STM32)  │ 3.3     │ 50-150   │ 165-495  │ 1       │
│ Flash存储器  │ 3.3     │ 10-30    │ 33-99    │ 1       │
│ 无线模块     │ 3.3     │ 20-200   │ 66-660   │ 1       │
│ 传感器       │ 3.3     │ 1-5      │ 3-17     │ 3       │
│ LED指示灯    │ 3.3     │ 20       │ 66       │ 2       │
│ LCD显示屏    │ 3.3     │ 10-50    │ 33-165   │ 1       │
└──────────────┴─────────┴──────────┴──────────┴─────────┘

步骤2:计算总功耗

功耗计算公式:

/**
 * @brief  计算系统总功耗
 * @param  components: 元件数组
 * @param  count: 元件数量
 * @param  mode: 工作模式(0=待机,1=正常,2=峰值)
 * @retval 总功耗(W)
 */
typedef struct {
    char name[32];
    float voltage;      // 电压(V)
    float current_idle; // 待机电流(A)
    float current_norm; // 正常电流(A)
    float current_peak; // 峰值电流(A)
    int quantity;       // 数量
} Component;

float calculate_total_power(Component *components, int count, int mode) {
    float total_power = 0;

    printf("\n功耗计算 - 模式: %s\n", 
           mode == 0 ? "待机" : (mode == 1 ? "正常" : "峰值"));
    printf("%-20s %8s %10s %10s\n", 
           "元件", "电压(V)", "电流(A)", "功率(W)");
    printf("─────────────────────────────────────────────\n");

    for (int i = 0; i < count; i++) {
        float current;
        switch(mode) {
            case 0: current = components[i].current_idle; break;
            case 1: current = components[i].current_norm; break;
            case 2: current = components[i].current_peak; break;
            default: current = components[i].current_norm;
        }

        float power = components[i].voltage * current * components[i].quantity;
        total_power += power;

        printf("%-20s %8.2f %10.3f %10.3f\n",
               components[i].name,
               components[i].voltage,
               current * components[i].quantity,
               power);
    }

    printf("─────────────────────────────────────────────\n");
    printf("总功耗: %.3f W\n", total_power);

    return total_power;
}

步骤3:确定电压等级

常见电压等级:

嵌入式系统常用电压:
- 1.2V:DDR内存、部分MCU内核
- 1.8V:某些MCU内核、Flash存储器
- 2.5V:部分FPGA内核
- 3.3V:最常用,MCU、外设、通信接口
- 5.0V:USB、部分传感器、电机驱动
- 12V:电机、继电器、某些模拟电路
- 24V:工业设备、电机驱动

电压等级选择原则:

  1. 尽量减少电压等级:
  2. 每增加一个电压等级,就需要一个稳压器
  3. 增加成本和复杂度
  4. 增加PCB面积

  5. 考虑兼容性:

  6. 3.3V和5V是最常用的电压
  7. 优先选择3.3V(现代芯片主流)
  8. 5V用于需要兼容老设备的场合

  9. 考虑效率:

  10. 电压差越大,线性稳压器效率越低
  11. 大压差应使用DC-DC转换器

步骤4:考虑余量

设计余量原则:

/*
 * 电源设计余量建议
 * 
 * 电流余量:
 * - 正常工作:实际电流 × 1.2 - 1.5
 * - 峰值电流:实际电流 × 1.5 - 2.0
 * 
 * 功率余量:
 * - 稳压器:实际功率 × 1.3 - 1.5
 * - 电源适配器:实际功率 × 1.5 - 2.0
 * 
 * 电压精度:
 * - 数字电路:±5% 通常足够
 * - 模拟电路:±3% 或更高
 * - 精密电路:±1% 或更高
 */

/**
 * @brief  计算所需电源容量(含余量)
 * @param  actual_power: 实际功耗(W)
 * @param  margin_factor: 余量系数(1.2-2.0)
 * @retval 所需电源容量(W)
 */
float calculate_power_capacity(float actual_power, float margin_factor) {
    float capacity = actual_power * margin_factor;

    printf("实际功耗: %.2f W\n", actual_power);
    printf("余量系数: %.1f\n", margin_factor);
    printf("所需容量: %.2f W\n", capacity);
    printf("余量: %.2f W (%.0f%%)\n", 
           capacity - actual_power,
           (margin_factor - 1) * 100);

    return capacity;
}

// 使用示例
void power_margin_example(void) {
    // 实际功耗2W,留30%余量
    float capacity = calculate_power_capacity(2.0, 1.3);
    // 结果:2.6W,选择3W或5W电源
}

第二部分:电源架构设计

什么是电源架构

电源架构是指从输入电源到各个负载之间的电源转换和分配方案。一个好的电源架构应该:

  1. 高效率:减少能量损耗
  2. 低成本:元件数量少,成本低
  3. 高可靠性:稳定可靠,故障率低
  4. 易于实现:设计简单,调试方便

常见电源架构类型

1. 单级架构

适用场景: - 简单系统,只需一个电压等级 - 输入输出电压差不大 - 功耗较小

架构示例:

输入电源 ──→ LDO/DC-DC ──→ 3.3V ──→ 所有负载

优点: - 结构简单 - 成本低 - 调试容易

缺点: - 灵活性差 - 不适合多电压系统 - 效率可能不高

2. 多级架构

适用场景: - 需要多个电压等级 - 输入输出电压差较大 - 功耗较大

架构示例:

输入电源(12V) ──→ DC-DC ──→ 5V ──┬──→ USB设备
                                  │
                                  ├──→ LDO ──→ 3.3V ──→ MCU
                                  │
                                  └──→ LDO ──→ 1.8V ──→ Flash

优点: - 灵活性高 - 可以优化每级效率 - 适合复杂系统

缺点: - 成本较高 - 设计复杂 - 占用空间大

3. 分布式架构

适用场景: - 大型系统 - 多个功能模块 - 需要独立控制

架构示例:

输入电源 ──┬──→ DC-DC1 ──→ 模块A电源
           │
           ├──→ DC-DC2 ──→ 模块B电源
           │
           └──→ DC-DC3 ──→ 模块C电源

优点: - 模块化设计 - 故障隔离 - 易于扩展

缺点: - 成本最高 - 设计最复杂 - 需要更多空间

电源架构设计原则

原则1:从高到低

推荐:12V → 5V → 3.3V → 1.8V
不推荐:12V → 1.8V(压差太大,效率低)

原因: - 逐级降压可以提高效率 - 减少每级的压差 - 降低热量产生

原则2:大电流用DC-DC

/*
 * LDO vs DC-DC 选择指南
 * 
 * 使用LDO的条件:
 * - 压差小(<2V)
 * - 电流小(<500mA)
 * - 需要低噪声
 * - 成本敏感
 * 
 * 使用DC-DC的条件:
 * - 压差大(>2V)
 * - 电流大(>500mA)
 * - 需要高效率
 * - 电池供电
 * 
 * 效率对比:
 * LDO效率 = Vout / Vin
 * DC-DC效率 = 85% - 95%
 */

/**
 * @brief  计算LDO和DC-DC的效率和功耗
 * @param  vin: 输入电压(V)
 * @param  vout: 输出电压(V)
 * @param  iout: 输出电流(A)
 * @param  dcdc_eff: DC-DC效率(0-1)
 */
void compare_regulator_efficiency(float vin, float vout, 
                                  float iout, float dcdc_eff) {
    // LDO计算
    float ldo_eff = vout / vin;
    float ldo_pout = vout * iout;
    float ldo_pin = vin * iout;
    float ldo_loss = ldo_pin - ldo_pout;

    // DC-DC计算
    float dcdc_pout = vout * iout;
    float dcdc_pin = dcdc_pout / dcdc_eff;
    float dcdc_loss = dcdc_pin - dcdc_pout;

    printf("\n电源转换效率对比\n");
    printf("输入电压: %.1f V\n", vin);
    printf("输出电压: %.1f V\n", vout);
    printf("输出电流: %.2f A\n", iout);
    printf("输出功率: %.2f W\n\n", vout * iout);

    printf("LDO方案:\n");
    printf("  效率: %.1f%%\n", ldo_eff * 100);
    printf("  输入功率: %.2f W\n", ldo_pin);
    printf("  功率损耗: %.2f W\n", ldo_loss);
    printf("  发热: %.2f W\n\n", ldo_loss);

    printf("DC-DC方案:\n");
    printf("  效率: %.1f%%\n", dcdc_eff * 100);
    printf("  输入功率: %.2f W\n", dcdc_pin);
    printf("  功率损耗: %.2f W\n", dcdc_loss);
    printf("  节省功耗: %.2f W (%.0f%%)\n", 
           ldo_loss - dcdc_loss,
           (1 - dcdc_loss/ldo_loss) * 100);
}

// 使用示例
void regulator_comparison_example(void) {
    // 12V转3.3V,1A输出
    compare_regulator_efficiency(12.0, 3.3, 1.0, 0.90);
    /*
     * 结果:
     * LDO: 27.5%效率,8.7W损耗
     * DC-DC: 90%效率,0.37W损耗
     * 节省8.33W(96%)
     */
}

原则3:噪声敏感用LDO

噪声对比:

DC-DC开关噪声:
- 频率:几十kHz到几MHz
- 幅度:几十mV到几百mV
- 影响:干扰模拟电路、射频电路

LDO噪声:
- 频率:很低
- 幅度:几μV到几十μV
- 影响:很小

推荐方案:
DC-DC → LDO → 噪声敏感电路
(DC-DC提供高效率,LDO提供低噪声)

典型电源架构案例

案例1:简单MCU系统

系统需求: - MCU:STM32F103,3.3V,100mA - 外设:传感器、LED等,3.3V,50mA - 输入:5V USB供电

电源架构:

5V USB ──→ LDO(3.3V) ──→ MCU + 外设

选型:
- LDO:AMS1117-3.3(800mA,压差1.2V)
- 去耦电容:10μF + 0.1μF

优点:
- 简单可靠
- 成本低(<1元)
- 噪声低

缺点:
- 效率66%
- 发热0.25W(可接受)

案例2:电池供电物联网设备

系统需求: - MCU:STM32L4,3.3V,10-50mA - 无线模块:3.3V,峰值200mA - 传感器:3.3V,5mA - 输入:3.7V锂电池

电源架构:

3.7V电池 ──→ DC-DC(3.3V) ──→ MCU + 无线 + 传感器

选型:
- DC-DC:TPS62740(300mA,效率90%)
- 输入电容:10μF
- 输出电容:22μF
- 电感:2.2μH

优点:
- 高效率(90%)
- 延长电池寿命
- 支持宽输入范围

缺点:
- 成本稍高(~3元)
- 有开关噪声

案例3:多电压工业设备

系统需求: - MCU:3.3V,200mA - FPGA内核:1.2V,1A - FPGA IO:3.3V,500mA - 模拟电路:5V,100mA - 电机驱动:12V,2A - 输入:24V工业电源

电源架构:

24V输入 ──┬──→ DC-DC(12V/3A) ──→ 电机驱动
          │
          ├──→ DC-DC(5V/2A) ──┬──→ 模拟电路
          │                   │
          │                   └──→ LDO(3.3V/1A) ──→ MCU + FPGA IO
          │
          └──→ DC-DC(1.2V/1.5A) ──→ FPGA内核

选型说明:
- 12V:Buck DC-DC,大电流
- 5V:Buck DC-DC,中等电流
- 3.3V:LDO,低噪声
- 1.2V:Buck DC-DC,大电流低压

优点:
- 效率高
- 噪声控制好
- 模块化设计

缺点:
- 成本较高
- 设计复杂
- 需要仔细规划

第三部分:电源树规划

什么是电源树

电源树(Power Tree)是一个图形化的表示方法,展示从输入电源到各个负载的电源分配关系。

电源树的作用:

  1. 可视化:清晰展示电源架构
  2. 分析工具:便于分析功耗和效率
  3. 文档记录:作为设计文档的一部分
  4. 沟通工具:便于团队沟通

电源树的绘制方法

基本元素

电源树符号:
┌─────────┐
│ 输入电源 │  矩形:电源输入
└────┬────┘
     │
     ├─────→  箭头:电源流向
     │
┌────┴────┐
│ 稳压器  │  矩形:电源转换
└────┬────┘
     │
     ├─────→  分支:多个输出
     │
┌────┴────┐
│  负载   │  矩形:用电设备
└─────────┘

完整示例

STM32开发板电源树:

                    ┌──────────────┐
                    │  5V USB输入  │
                    │   (500mA)    │
                    └──────┬───────┘
                           │
                    ┌──────┴───────┐
                    │ AMS1117-3.3  │
                    │  LDO稳压器   │
                    │  (800mA)     │
                    └──────┬───────┘
                           │
                           │ 3.3V
                           │
           ┌───────────────┼───────────────┐
           │               │               │
    ┌──────┴──────┐ ┌─────┴─────┐ ┌──────┴──────┐
    │  STM32F103  │ │  Flash    │ │   外设      │
    │   (100mA)   │ │  (20mA)   │ │   (50mA)    │
    └─────────────┘ └───────────┘ └─────────────┘

    总功耗:170mA × 3.3V = 561mW
    输入功率:170mA × 5V = 850mW
    效率:561/850 = 66%

电源树分析

功耗分析

/**
 * @brief  电源树节点结构
 */
typedef struct PowerNode {
    char name[32];          // 节点名称
    float voltage_in;       // 输入电压(V)
    float voltage_out;      // 输出电压(V)
    float current_out;      // 输出电流(A)
    float efficiency;       // 效率(0-1)
    int child_count;        // 子节点数量
    struct PowerNode *children[10];  // 子节点
} PowerNode;

/**
 * @brief  计算电源树节点功耗
 * @param  node: 电源树节点
 * @param  level: 层级(用于缩进)
 */
void analyze_power_tree(PowerNode *node, int level) {
    // 计算输出功率
    float power_out = node->voltage_out * node->current_out;

    // 计算输入功率
    float power_in;
    if (node->efficiency > 0) {
        power_in = power_out / node->efficiency;
    } else {
        power_in = power_out;
    }

    // 计算损耗
    float power_loss = power_in - power_out;

    // 打印节点信息
    for (int i = 0; i < level; i++) printf("  ");
    printf("├─ %s\n", node->name);

    for (int i = 0; i < level; i++) printf("  ");
    printf("│  输入: %.2fV, %.3fA, %.3fW\n", 
           node->voltage_in, power_in/node->voltage_in, power_in);

    for (int i = 0; i < level; i++) printf("  ");
    printf("│  输出: %.2fV, %.3fA, %.3fW\n", 
           node->voltage_out, node->current_out, power_out);

    if (node->efficiency > 0) {
        for (int i = 0; i < level; i++) printf("  ");
        printf("│  效率: %.1f%%, 损耗: %.3fW\n", 
               node->efficiency * 100, power_loss);
    }

    // 递归分析子节点
    for (int i = 0; i < node->child_count; i++) {
        analyze_power_tree(node->children[i], level + 1);
    }
}

第四部分:功耗预算

什么是功耗预算

功耗预算(Power Budget)是对系统各部分功耗的详细规划和分配,确保总功耗不超过电源供应能力。

功耗预算的重要性:

  1. 电池寿命:
  2. 直接影响电池供电设备的续航时间
  3. 需要精确计算平均功耗

  4. 热设计:

  5. 功耗转化为热量
  6. 需要考虑散热方案

  7. 电源选型:

  8. 确定所需的电源容量
  9. 避免过度设计或容量不足

功耗预算的计算方法

方法1:最坏情况法

适用场景: - 安全关键系统 - 需要保证最坏情况下正常工作

计算方法:

/**
 * @brief  最坏情况功耗计算
 * @param  components: 元件数组
 * @param  count: 元件数量
 * @retval 最大功耗(W)
 */
float calculate_worst_case_power(Component *components, int count) {
    float total_power = 0;

    printf("\n最坏情况功耗预算\n");
    printf("%-20s %10s %10s\n", "元件", "电流(A)", "功率(W)");
    printf("────────────────────────────────────────\n");

    for (int i = 0; i < count; i++) {
        // 使用峰值电流
        float current = components[i].current_peak * components[i].quantity;
        float power = components[i].voltage * current;
        total_power += power;

        printf("%-20s %10.3f %10.3f\n",
               components[i].name, current, power);
    }

    printf("────────────────────────────────────────\n");
    printf("总功耗(最坏情况): %.3f W\n", total_power);

    return total_power;
}

方法2:平均功耗法

适用场景: - 电池供电设备 - 需要估算电池寿命

计算方法:

/**
 * @brief  工作模式定义
 */
typedef struct {
    char name[32];
    float duration;     // 持续时间(s)
    float power;        // 功率(W)
} WorkMode;

/**
 * @brief  计算平均功耗
 * @param  modes: 工作模式数组
 * @param  count: 模式数量
 * @retval 平均功耗(W)
 */
float calculate_average_power(WorkMode *modes, int count) {
    float total_energy = 0;
    float total_time = 0;

    printf("\n平均功耗计算\n");
    printf("%-15s %10s %10s %12s\n", 
           "模式", "时间(s)", "功率(W)", "能量(J)");
    printf("───────────────────────────────────────────────\n");

    for (int i = 0; i < count; i++) {
        float energy = modes[i].power * modes[i].duration;
        total_energy += energy;
        total_time += modes[i].duration;

        printf("%-15s %10.1f %10.3f %12.3f\n",
               modes[i].name,
               modes[i].duration,
               modes[i].power,
               energy);
    }

    float avg_power = total_energy / total_time;

    printf("───────────────────────────────────────────────\n");
    printf("总时间: %.1f s\n", total_time);
    printf("总能量: %.3f J\n", total_energy);
    printf("平均功耗: %.3f W\n", avg_power);

    return avg_power;
}

// 使用示例
void average_power_example(void) {
    WorkMode modes[] = {
        {"深度睡眠", 50.0, 0.001},  // 50s, 1mW
        {"待机", 5.0, 0.010},        // 5s, 10mW
        {"工作", 4.0, 0.500},        // 4s, 500mW
        {"峰值", 1.0, 1.000}         // 1s, 1W
    };

    float avg = calculate_average_power(modes, 4);
    // 结果:约42mW平均功耗
}

方法3:占空比法

适用场景: - 周期性工作的设备 - 间歇工作模式

计算公式:

/**
 * @brief  占空比功耗计算
 * @param  power_active: 工作功耗(W)
 * @param  power_sleep: 睡眠功耗(W)
 * @param  duty_cycle: 占空比(0-1)
 * @retval 平均功耗(W)
 */
float calculate_duty_cycle_power(float power_active, 
                                 float power_sleep, 
                                 float duty_cycle) {
    float avg_power = power_active * duty_cycle + 
                      power_sleep * (1 - duty_cycle);

    printf("\n占空比功耗计算\n");
    printf("工作功耗: %.3f W\n", power_active);
    printf("睡眠功耗: %.3f W\n", power_sleep);
    printf("占空比: %.1f%%\n", duty_cycle * 100);
    printf("平均功耗: %.3f W\n", avg_power);

    // 计算节能效果
    float saving = (power_active - avg_power) / power_active * 100;
    printf("节能: %.1f%%\n", saving);

    return avg_power;
}

// 使用示例
void duty_cycle_example(void) {
    // 工作500mW,睡眠1mW,占空比10%
    float avg = calculate_duty_cycle_power(0.5, 0.001, 0.1);
    // 结果:51mW,节能90%
}

电池寿命计算

电池容量单位: - mAh(毫安时):常用单位 - Wh(瓦时):能量单位

电池寿命计算公式:

/**
 * @brief  计算电池寿命
 * @param  battery_capacity: 电池容量(mAh)
 * @param  avg_current: 平均电流(mA)
 * @param  efficiency: 放电效率(0-1,通常0.8-0.9)
 * @retval 电池寿命(小时)
 */
float calculate_battery_life(float battery_capacity, 
                             float avg_current, 
                             float efficiency) {
    // 考虑放电效率
    float effective_capacity = battery_capacity * efficiency;

    // 计算寿命(小时)
    float lifetime_hours = effective_capacity / avg_current;

    // 转换为天
    float lifetime_days = lifetime_hours / 24;

    printf("\n电池寿命计算\n");
    printf("电池容量: %.0f mAh\n", battery_capacity);
    printf("平均电流: %.2f mA\n", avg_current);
    printf("放电效率: %.0f%%\n", efficiency * 100);
    printf("有效容量: %.0f mAh\n", effective_capacity);
    printf("─────────────────────────\n");
    printf("理论寿命: %.1f 小时\n", lifetime_hours);
    printf("理论寿命: %.1f 天\n", lifetime_days);

    // 实际寿命通常是理论值的70-80%
    printf("\n实际寿命估算:\n");
    printf("  保守估计: %.1f 天 (70%%)\n", lifetime_days * 0.7);
    printf("  乐观估计: %.1f 天 (80%%)\n", lifetime_days * 0.8);

    return lifetime_hours;
}

// 使用示例
void battery_life_example(void) {
    // 2000mAh电池,平均10mA电流,85%效率
    float life = calculate_battery_life(2000, 10, 0.85);
    // 结果:170小时 = 7.1天
}

/**
 * @brief  根据目标寿命计算允许的平均电流
 * @param  battery_capacity: 电池容量(mAh)
 * @param  target_days: 目标寿命(天)
 * @param  efficiency: 放电效率(0-1)
 * @retval 允许的平均电流(mA)
 */
float calculate_max_current(float battery_capacity, 
                           float target_days, 
                           float efficiency) {
    float effective_capacity = battery_capacity * efficiency;
    float target_hours = target_days * 24;
    float max_current = effective_capacity / target_hours;

    printf("\n功耗预算计算\n");
    printf("电池容量: %.0f mAh\n", battery_capacity);
    printf("目标寿命: %.0f 天\n", target_days);
    printf("放电效率: %.0f%%\n", efficiency * 100);
    printf("─────────────────────────\n");
    printf("允许平均电流: %.2f mA\n", max_current);
    printf("允许平均功耗: %.3f W (@ 3.7V)\n", max_current * 3.7 / 1000);

    return max_current;
}

// 使用示例
void power_budget_example(void) {
    // 2000mAh电池,目标30天寿命
    float max_i = calculate_max_current(2000, 30, 0.85);
    // 结果:2.36mA,即8.7mW @ 3.7V
}

第五部分:电源时序

什么是电源时序

电源时序(Power Sequencing)是指多个电源按照特定顺序上电和断电的过程。正确的电源时序对系统稳定性至关重要。

为什么需要电源时序:

  1. 避免闩锁效应:
  2. IO电压高于内核电压可能导致闩锁
  3. 需要先上内核电源,再上IO电源

  4. 保护芯片:

  5. 某些芯片对上电顺序有严格要求
  6. 违反顺序可能损坏芯片

  7. 系统稳定性:

  8. 正确的时序保证系统可靠启动
  9. 避免出现未定义状态

  10. 功能需求:

  11. 某些功能模块依赖其他模块先启动
  12. 需要按依赖关系排序

常见电源时序要求

1. FPGA电源时序

典型要求:

FPGA电源上电顺序:
1. 内核电源(Vcore,如1.2V)
2. 辅助电源(Vaux,如1.8V)
3. IO电源(Vio,如3.3V)

时序要求:
- 内核电源必须先于IO电源
- 各电源间延迟:1-100ms
- 上电斜率:0.1-10V/ms

断电顺序:
与上电顺序相反

时序图:

Vcore (1.2V)  ─────┐
                   │ 10ms
Vaux (1.8V)   ─────┼────┐
                   │    │ 10ms
Vio (3.3V)    ─────┼────┼────┐
                   │    │    │
              t0   t1   t2   t3

2. DDR内存电源时序

典型要求:

DDR3电源上电顺序:
1. VDD (1.5V) - 主电源
2. VDDQ (1.5V) - IO电源
3. VTT (0.75V) - 终端电源
4. VREF (0.75V) - 参考电压

时序要求:
- VDD和VDDQ可以同时上电
- VTT必须在VDD之后
- 各电源间延迟:<200ms
- 复位信号在电源稳定后拉高

3. MCU电源时序

典型要求:

多电压MCU上电顺序:
1. 内核电源(如1.2V)
2. IO电源(如3.3V)
3. 模拟电源(如3.3V)

时序要求:
- 内核电源先于IO电源
- 模拟电源可以与IO同时
- 延迟:通常无严格要求(1-10ms)
- 复位信号在所有电源稳定后释放

电源时序实现方法

方法1:使用延迟电路

RC延迟:

/*
 * RC延迟电路
 * 
 * EN1 ──→ 稳压器1 ──→ Vout1
 *                      │
 *                      ├── R ──┬── EN2 ──→ 稳压器2
 *                              │
 *                              C
 *                              │
 *                             GND
 * 
 * 延迟时间:t ≈ 2.2 × R × C
 * 
 * 示例:
 * R = 100kΩ, C = 1μF
 * t ≈ 2.2 × 100k × 1μ = 220ms
 */

/**
 * @brief  计算RC延迟时间
 * @param  R: 电阻值(Ω)
 * @param  C: 电容值(F)
 * @param  threshold: 阈值电压比例(0-1)
 * @retval 延迟时间(s)
 */
float calculate_rc_delay_time(float R, float C, float threshold) {
    // t = -R × C × ln(1 - threshold)
    float delay = -R * C * log(1 - threshold);

    printf("RC延迟计算\n");
    printf("R = %.0f Ω\n", R);
    printf("C = %.2e F = %.1f μF\n", C, C * 1e6);
    printf("阈值 = %.0f%%\n", threshold * 100);
    printf("延迟时间 = %.3f s = %.0f ms\n", delay, delay * 1000);

    return delay;
}

// 使用示例
void rc_delay_example(void) {
    // 100kΩ, 1μF, 63%阈值
    float delay = calculate_rc_delay_time(100000, 1e-6, 0.63);
    // 结果:约100ms
}

方法2:使用时序控制芯片

专用时序芯片:

常用时序控制芯片:
- TPS65023:多路输出,可编程时序
- LTC2937:4路时序控制
- MAX16602:双路时序控制

优点:
- 精确控制时序
- 可编程延迟
- 故障检测
- 集成度高

缺点:
- 成本较高
- 需要额外芯片

方法3:使用MCU控制

软件控制时序:

/**
 * @brief  电源时序控制
 * @note   使用GPIO控制稳压器使能引脚
 */
void power_sequence_control(void) {
    printf("开始电源上电时序...\n");

    // 步骤1:使能内核电源(1.2V)
    printf("1. 使能内核电源 (1.2V)\n");
    GPIO_SetBits(GPIOA, GPIO_Pin_0);  // EN_VCORE = 1
    HAL_Delay(10);  // 延迟10ms

    // 步骤2:检查内核电源是否稳定
    if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1) == 0) {
        printf("   错误:内核电源未稳定!\n");
        return;
    }
    printf("   内核电源稳定\n");

    // 步骤3:使能IO电源(3.3V)
    printf("2. 使能IO电源 (3.3V)\n");
    GPIO_SetBits(GPIOA, GPIO_Pin_2);  // EN_VIO = 1
    HAL_Delay(10);  // 延迟10ms

    // 步骤4:检查IO电源是否稳定
    if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3) == 0) {
        printf("   错误:IO电源未稳定!\n");
        return;
    }
    printf("   IO电源稳定\n");

    // 步骤5:释放复位信号
    printf("3. 释放复位信号\n");
    GPIO_SetBits(GPIOA, GPIO_Pin_4);  // RESET = 1
    HAL_Delay(1);  // 延迟1ms

    printf("电源上电时序完成!\n");
}

/**
 * @brief  电源断电时序控制
 */
void power_shutdown_sequence(void) {
    printf("开始电源断电时序...\n");

    // 步骤1:拉低复位信号
    printf("1. 拉低复位信号\n");
    GPIO_ResetBits(GPIOA, GPIO_Pin_4);  // RESET = 0
    HAL_Delay(1);

    // 步骤2:关闭IO电源
    printf("2. 关闭IO电源\n");
    GPIO_ResetBits(GPIOA, GPIO_Pin_2);  // EN_VIO = 0
    HAL_Delay(10);

    // 步骤3:关闭内核电源
    printf("3. 关闭内核电源\n");
    GPIO_ResetBits(GPIOA, GPIO_Pin_0);  // EN_VCORE = 0

    printf("电源断电时序完成!\n");
}

电源时序设计要点

1. 确定时序要求

查阅数据手册: - 芯片数据手册的"Power Supply"章节 - 应用笔记(Application Note) - 参考设计(Reference Design)

关键参数: - 上电顺序 - 延迟时间 - 上电斜率 - 复位时序

2. 设计时序电路

设计检查清单:

□ 确认所有电源的上电顺序
□ 计算所需的延迟时间
□ 选择合适的实现方法
□ 添加电源监控功能
□ 设计故障保护机制
□ 考虑断电时序
□ 预留调试接口

3. 验证时序

测试方法:

/**
 * @brief  电源时序测试程序
 * @note   使用示波器监测各电源上电波形
 */
void test_power_sequence(void) {
    printf("\n=== 电源时序测试 ===\n");

    // 测试项1:上电顺序
    printf("\n测试1:上电顺序\n");
    printf("  - 使用示波器同时监测所有电源\n");
    printf("  - 确认上电顺序正确\n");
    printf("  - 测量各电源间的延迟时间\n");

    // 测试项2:上电斜率
    printf("\n测试2:上电斜率\n");
    printf("  - 测量电压上升时间\n");
    printf("  - 计算上电斜率 (V/ms)\n");
    printf("  - 确认符合芯片要求\n");

    // 测试项3:复位时序
    printf("\n测试3:复位时序\n");
    printf("  - 确认复位信号在电源稳定后释放\n");
    printf("  - 测量复位脉冲宽度\n");
    printf("  - 验证系统正常启动\n");

    // 测试项4:断电时序
    printf("\n测试4:断电时序\n");
    printf("  - 确认断电顺序正确\n");
    printf("  - 验证无反向供电\n");
    printf("  - 测试多次上下电\n");

    // 测试项5:故障测试
    printf("\n测试5:故障测试\n");
    printf("  - 模拟电源故障\n");
    printf("  - 验证保护机制\n");
    printf("  - 测试恢复功能\n");
}

第六部分:实用设计案例

案例1:USB供电的STM32系统

系统需求: - MCU:STM32F103,3.3V,100mA - 外设:传感器、LED等,3.3V,50mA - 输入:5V USB,最大500mA

设计方案:

5V USB (500mA)
    │
    ├─── 保护电路(TVS、保险丝)
    │
    ├─── AMS1117-3.3 (LDO)
    │    输入:10μF
    │    输出:10μF + 0.1μF
    │
    ├─── 3.3V (150mA)
    │
    ├─── MCU去耦:0.1μF × 4
    │
    └─── 外设去耦:0.1μF × N

功耗分析:
- 输出功率:3.3V × 0.15A = 0.495W
- 输入功率:5V × 0.15A = 0.75W
- 效率:66%
- 发热:0.255W(可接受)

成本分析:
- LDO:¥0.5
- 电容:¥0.3
- 保护器件:¥0.5
- 总计:¥1.3

案例2:锂电池供电的物联网节点

系统需求: - MCU:STM32L4,3.3V,10-50mA - 无线模块:3.3V,峰值200mA - 传感器:3.3V,5mA - 电池:3.7V锂电池,2000mAh - 目标寿命:30天

设计方案:

3.7V锂电池 (2000mAh)
    │
    ├─── 充电管理(TP4056)
    │
    ├─── 保护电路(过充、过放、过流)
    │
    ├─── TPS62740 (Buck DC-DC)
    │    输入:10μF
    │    输出:22μF
    │    电感:2.2μH
    │    效率:90%
    │
    ├─── 3.3V
    │
    ├─── MCU + 无线 + 传感器
    │
    └─── 去耦电容:0.1μF × N

功耗预算:
- 深度睡眠:1mA,90%时间
- 工作:50mA,9%时间
- 峰值:200mA,1%时间
- 平均电流:1×0.9 + 50×0.09 + 200×0.01 = 7.4mA

电池寿命:
- 有效容量:2000mAh × 0.85 = 1700mAh
- 理论寿命:1700 / 7.4 = 230小时 = 9.6天
- 实际寿命:9.6 × 0.75 = 7.2天

优化方案:
- 降低睡眠电流到0.5mA
- 减少工作时间到5%
- 优化后平均电流:3.2mA
- 优化后寿命:33天(达到目标)

案例3:工业设备多电压系统

系统需求: - MCU:3.3V,200mA - FPGA内核:1.2V,1A - FPGA IO:3.3V,500mA - 模拟电路:5V,100mA - 电机驱动:12V,2A - 输入:24V工业电源

设计方案:

24V工业电源
    │
    ├─── EMI滤波(共模电感 + 电容)
    │
    ├─── 保护电路(TVS、保险丝)
    │
    ├─── Buck DC-DC (12V/3A)
    │    │
    │    └─── 电机驱动
    │
    ├─── Buck DC-DC (5V/2A)
    │    │
    │    ├─── 模拟电路
    │    │
    │    └─── LDO (3.3V/1A)
    │         │
    │         ├─── MCU
    │         │
    │         └─── FPGA IO
    │
    └─── Buck DC-DC (1.2V/1.5A)
         │
         └─── FPGA内核

电源时序:
1. 1.2V FPGA内核(t=0)
2. 延迟10ms
3. 3.3V FPGA IO(t=10ms)
4. 延迟5ms
5. 释放FPGA复位(t=15ms)
6. 5V和12V可以随时上电

功耗分析:
- 12V:2A × 12V = 24W
- 5V:0.1A × 5V = 0.5W
- 3.3V:0.7A × 3.3V = 2.31W
- 1.2V:1A × 1.2V = 1.2W
- 总输出功率:28W

效率分析:
- 24V→12V:90%,输入26.7W
- 24V→5V:85%,输入0.59W
- 5V→3.3V:66%,输入3.5W
- 24V→1.2V:80%,输入1.5W
- 总输入功率:32.3W
- 整体效率:28/32.3 = 87%

成本分析:
- DC-DC模块:¥15
- LDO:¥2
- 电容电感:¥5
- 保护器件:¥3
- 总计:¥25

总结

本文全面介绍了嵌入式系统电源设计的基础知识。

核心要点

  1. 电源需求分析:
  2. 列出所有用电元件
  3. 计算总功耗(待机、正常、峰值)
  4. 确定电压等级
  5. 预留设计余量

  6. 电源架构设计:

  7. 选择合适的架构类型
  8. 遵循从高到低原则
  9. 大电流用DC-DC,小电流用LDO
  10. 噪声敏感电路用LDO

  11. 电源树规划:

  12. 绘制清晰的电源树图
  13. 分析各级功耗和效率
  14. 优化电源转换路径

  15. 功耗预算:

  16. 使用合适的计算方法
  17. 考虑不同工作模式
  18. 计算电池寿命
  19. 优化功耗设计

  20. 电源时序:

  21. 遵循芯片数据手册要求
  22. 选择合适的实现方法
  23. 验证时序正确性
  24. 考虑故障保护

设计流程总结

1. 需求分析
   ├─ 列出元件清单
   ├─ 计算功耗
   ├─ 确定电压等级
   └─ 预留余量

2. 架构设计
   ├─ 选择架构类型
   ├─ 选择稳压器类型
   ├─ 绘制电源树
   └─ 优化效率

3. 详细设计
   ├─ 选择具体器件
   ├─ 设计外围电路
   ├─ 设计时序控制
   └─ 添加保护电路

4. 验证测试
   ├─ 仿真分析
   ├─ 原型测试
   ├─ 效率测试
   └─ 可靠性测试

5. 优化改进
   ├─ 功耗优化
   ├─ 成本优化
   ├─ 性能优化
   └─ 可靠性优化

最佳实践

  1. 设计原则:
  2. 安全第一,留足余量
  3. 效率优先,降低功耗
  4. 成本控制,避免过度设计
  5. 可靠性高,考虑故障保护

  6. 常见错误:

  7. ❌ 功耗计算不准确
  8. ❌ 电压余量不足
  9. ❌ 忽略电源时序
  10. ❌ 去耦电容不足
  11. ❌ 没有保护电路

  12. 设计建议:

  13. ✅ 仔细阅读数据手册
  14. ✅ 参考官方参考设计
  15. ✅ 使用仿真工具验证
  16. ✅ 预留测试点和调试接口
  17. ✅ 进行充分的测试验证

延伸阅读

推荐进一步学习的内容:

  1. 进阶主题:
  2. 低功耗设计技术入门
  3. 电池供电系统设计要点
  4. 电源监控与保护电路设计

  5. 相关知识:

  6. 电源电路设计:LDO与DC-DC选择
  7. 动态电源管理(DPM)技术
  8. 电源完整性分析与优化

  9. 实践项目:

  10. 简易电源设计项目
  11. 电池管理系统设计

参考资料

  1. 《电源设计基础》- Texas Instruments
  2. 《开关电源设计》- Abraham I. Pressman
  3. 《低功耗设计方法学》- Michael Keating
  4. 各芯片厂商应用笔记(TI、ADI、Maxim等)
  5. 《Power Supply Cookbook》- Marty Brown

练习题:

  1. 计算系统功耗:
  2. MCU:3.3V,50mA
  3. 无线模块:3.3V,100mA
  4. 传感器×3:3.3V,5mA each
  5. 计算总功耗和所需电源容量(留30%余量)

  6. 设计电源架构:

  7. 输入:12V
  8. 需要:5V/1A,3.3V/500mA,1.8V/200mA
  9. 选择合适的稳压器类型
  10. 绘制电源树

  11. 计算电池寿命:

  12. 电池:2000mAh,3.7V
  13. 平均电流:10mA
  14. 放电效率:85%
  15. 计算理论寿命和实际寿命

  16. 设计电源时序:

  17. FPGA需要先上1.2V内核,再上3.3V IO
  18. 延迟要求:10ms
  19. 设计RC延迟电路或软件控制方案

实践任务:

  1. 分析一个现有开发板的电源设计
  2. 使用万用表测量各电源电压和电流
  3. 绘制该开发板的电源树
  4. 计算各级效率和总功耗
  5. 使用示波器观察电源上电波形

下一步:建议学习 低功耗设计技术入门,了解如何进一步降低系统功耗,延长电池寿命。


常见问题解答:

Q: LDO和DC-DC如何选择?

A: 主要考虑以下因素: - 压差:>2V优先DC-DC - 电流:>500mA优先DC-DC - 噪声:需要低噪声用LDO - 效率:需要高效率用DC-DC - 成本:LDO更便宜 - 空间:LDO更小

Q: 电源余量留多少合适?

A: 建议: - 电流余量:20-50% - 功率余量:30-50% - 电压精度:根据芯片要求 - 宁可多留,不可不足

Q: 如何降低电源噪声?

A: 方法: - 使用LDO代替DC-DC - 增加滤波电容 - 使用LC滤波器 - 改善PCB布局 - 使用屏蔽措施

Q: 电源时序为什么重要?

A: 原因: - 避免闩锁效应 - 保护芯片不损坏 - 保证系统稳定启动 - 满足芯片规格要求 - 提高系统可靠性

Q: 如何测试电源设计?

A: 测试项目: - 电压精度测试 - 纹波噪声测试 - 负载调整率测试 - 效率测试 - 温升测试 - 时序测试 - 可靠性测试