前言
最近在做一个基于STM32的智能充电管理项目,需要实现对多种快充协议的支持。在调研过程中发现,虽然市面上快充技术五花八门,但底层原理其实都有共通之处。今天就把这段时间的研究心得整理出来,和大家分享一下手机快充技术的核心原理和具体实现方法。
一、快充技术的发展背景
手机电池容量越来越大,从早期的2000mAh到现在普遍4000-5000mAh,如果还用传统5V/1A的充电方式,充满电需要4-5个小时,这显然无法满足用户需求。快充技术应运而生。
传统充电功率只有5W(5V × 1A),而现在主流快充已经达到65W、100W甚至更高。那么问题来了:怎么在保证安全的前提下提升充电功率?
二、快充的核心原理
根据功率公式 P = U × I,要提升充电功率,无非两个方向:
2.1 高压小电流方案
代表技术:高通QC、联发科PE
原理很简单,提高电压到9V、12V甚至20V,电流维持在2-3A。这种方案最大的优点是对数据线要求低,普通线材也能支持。但缺点也明显:
- 需要在手机内部进行降压转换,会产生较多热量
- 转换效率存在损耗,实际充入电池的功率会打折扣
实际测试中,一个12V/2A(24W)的QC充电器,手机端实际充电功率可能只有18W左右,其余6W都变成了热量。
2.2 低压大电流方案
代表技术:OPPO VOOC/SuperVOOC、华为SuperCharge
这种方案反其道行之,电压保持在5V或稍高,但电流提升到4A、5A甚至10A以上。优势在于:
- 手机内部几乎不需要降压,发热量小
- 能量转换效率高,95%以上
但问题是对线缆和接口要求极高,必须用定制的数据线,而且接口触点需要特殊设计,防止过载烧毁。
2.3 USB PD(Power Delivery)
USB PD是USB-IF组织制定的统一标准,兼顾了上述两种方案的优点:
- 支持5V、9V、12V、15V、20V多档电压
- 电流最高可达5A
- 最大功率可达100W(20V/5A)
- 双向充电,既能给手机充电,也能让手机给其他设备充电
PD协议通过CC(Configuration Channel)引脚进行协商,充电器和设备之间会先"握手"确定最佳的电压电流组合。
三、快充协议的握手过程
以USB PD为例,握手过程大致如下:
充电器 -> 设备: 我支持5V/3A、9V/3A、12V/2.5A
设备 -> 充电器: 我需要9V/2A
充电器: 好的,切换到9V输出
[开始充电]
这个过程是通过BMC(Biphase Mark Coding)编码的数字信号完成的,传输速率300Kbps。
四、硬件电路设计
一个完整的快充系统需要以下几个关键模块:
4.1 电源管理芯片(PMIC)
负责:
- 电压电流检测
- 充电曲线控制
- 温度监测
- 电池保护
常用芯片:BQ25890(TI)、MP2760(MPS)等
4.2 协议识别芯片
负责识别充电器类型,与充电器进行协议握手。
- QC协议:通过D+/D-电压识别
- PD协议:需要专用的PD控制器(如FUSB302、CH224等)
4.3 电池管理
锂电池充电遵循CC-CV曲线(恒流-恒压):
- 恒流阶段(CC):以恒定电流充电,电池电压逐渐上升
- 恒压阶段(CV):电压达到4.2V(或4.35V)后保持恒压,电流逐渐减小
- 涓流充电:电流降到很小时,进行补充充电
快充主要优化的是CC阶段,通过提高充电功率缩短这个阶段的时间。
五、软件实现
下面是一个基于STM32的USB PD协议解析和控制程序示例:
5.1 PD协议消息解析
c
// pd_protocol.h
#ifndef __PD_PROTOCOL_H
#define __PD_PROTOCOL_H
#include "stdint.h"
// PD消息类型
#define PD_MSGTYPE_CTRL 0x00
#define PD_MSGTYPE_DATA 0x01
// 控制消息
#define PD_CTRL_GOODCRC 0x01
#define PD_CTRL_ACCEPT 0x03
#define PD_CTRL_REJECT 0x04
#define PD_CTRL_PS_RDY 0x06
// 数据消息
#define PD_DATA_SOURCE_CAP 0x01
#define PD_DATA_REQUEST 0x02
// 电压单位:50mV
// 电流单位:10mA
typedef struct {
uint32_t max_current:10; // 最大电流(10mA单位)
uint32_t voltage:10; // 电压(50mV单位)
uint32_t reserved:12;
} PD_PowerObject_t;
typedef struct {
uint8_t msg_type;
uint8_t num_objects;
PD_PowerObject_t objects[7];
} PD_SourceCap_t;
typedef struct {
uint32_t obj_position:3; // 请求的电源对象位置
uint32_t reserved1:1;
uint32_t operate_current:10; // 工作电流
uint32_t max_current:10; // 最大电流
uint32_t reserved2:8;
} PD_Request_t;
#endif
5.2 PD协议状态机
c
// pd_state_machine.c
#include "pd_protocol.h"
#include "stm32f4xx_hal.h"
typedef enum {
PD_STATE_IDLE,
PD_STATE_WAIT_SOURCE_CAP,
PD_STATE_SEND_REQUEST,
PD_STATE_WAIT_ACCEPT,
PD_STATE_WAIT_PS_READY,
PD_STATE_CHARGING
} PD_State_t;
static PD_State_t pd_state = PD_STATE_IDLE;
static PD_SourceCap_t source_cap;
static uint8_t selected_voltage = 0;
// 解析Source Capabilities消息
void PD_ParseSourceCap(uint8_t *data, uint16_t len) {
source_cap.num_objects = (len - 2) / 4;
for(int i = 0; i < source_cap.num_objects; i++) {
uint32_t pdo = *(uint32_t*)(data + 2 + i*4);
source_cap.objects[i].voltage = (pdo >> 10) & 0x3FF;
source_cap.objects[i].max_current = pdo & 0x3FF;
// 打印支持的电压电流选项
uint16_t voltage_mv = source_cap.objects[i].voltage * 50;
uint16_t current_ma = source_cap.objects[i].max_current * 10;
printf("PDO[%d]: %dmV @ %dmA\n", i, voltage_mv, current_ma);
}
}
// 选择合适的电压档位
uint8_t PD_SelectVoltage(uint16_t target_voltage_mv) {
uint8_t best_index = 0;
uint16_t best_voltage = 0;
for(int i = 0; i < source_cap.num_objects; i++) {
uint16_t voltage_mv = source_cap.objects[i].voltage * 50;
// 选择不超过目标电压的最大电压
if(voltage_mv <= target_voltage_mv && voltage_mv > best_voltage) {
best_voltage = voltage_mv;
best_index = i;
}
}
return best_index;
}
// 发送Request消息
void PD_SendRequest(uint8_t obj_position, uint16_t operate_current_ma) {
PD_Request_t request;
request.obj_position = obj_position + 1; // 1-indexed
request.operate_current = operate_current_ma / 10;
request.max_current = operate_current_ma / 10;
request.reserved1 = 0;
request.reserved2 = 0;
// 发送Request消息(具体发送函数需要根据使用的PD芯片实现)
PD_SendMessage(PD_DATA_REQUEST, (uint8_t*)&request, sizeof(request));
}
// PD协议状态机
void PD_StateMachine(void) {
switch(pd_state) {
case PD_STATE_IDLE:
// 等待插入充电器
pd_state = PD_STATE_WAIT_SOURCE_CAP;
break;
case PD_STATE_WAIT_SOURCE_CAP:
// 等待接收Source Capabilities
// 在中断或轮询中接收到后会调用PD_ParseSourceCap
break;
case PD_STATE_SEND_REQUEST:
// 选择9V电压档位,2A电流
selected_voltage = PD_SelectVoltage(9000);
PD_SendRequest(selected_voltage, 2000);
pd_state = PD_STATE_WAIT_ACCEPT;
break;
case PD_STATE_WAIT_ACCEPT:
// 等待充电器Accept消息
break;
case PD_STATE_WAIT_PS_READY:
// 等待充电器切换电压完成(PS_Ready消息)
break;
case PD_STATE_CHARGING:
// 正常充电中
break;
}
}
// 消息接收回调
void PD_MessageReceived(uint8_t msg_type, uint8_t *data, uint16_t len) {
if(msg_type == PD_DATA_SOURCE_CAP) {
PD_ParseSourceCap(data, len);
pd_state = PD_STATE_SEND_REQUEST;
}
else if(msg_type == PD_CTRL_ACCEPT) {
pd_state = PD_STATE_WAIT_PS_READY;
}
else if(msg_type == PD_CTRL_PS_RDY) {
pd_state = PD_STATE_CHARGING;
printf("PD negotiation complete, charging at %dV\n",
source_cap.objects[selected_voltage].voltage * 50);
}
}
5.3 充电控制算法
c
// charge_control.c
#include "stm32f4xx_hal.h"
#define BATTERY_CAPACITY 4000 // 电池容量mAh
#define MAX_CHARGE_VOLTAGE 4200 // 最大充电电压4.2V
#define CHARGE_CURRENT_CC 2000 // 恒流充电电流2A
#define CHARGE_CURRENT_CV 200 // 恒压阶段截止电流200mA
typedef enum {
CHARGE_STATE_IDLE,
CHARGE_STATE_TRICKLE, // 涓流充电(电池电压<3.0V)
CHARGE_STATE_CC, // 恒流充电
CHARGE_STATE_CV, // 恒压充电
CHARGE_STATE_DONE // 充电完成
} ChargeState_t;
static ChargeState_t charge_state = CHARGE_STATE_IDLE;
static uint16_t battery_voltage_mv = 0;
static uint16_t charge_current_ma = 0;
static uint16_t battery_temp_c = 0;
// ADC读取电池电压
uint16_t ReadBatteryVoltage(void) {
// 实际项目中通过ADC读取
// 这里简化处理
return battery_voltage_mv;
}
// ADC读取充电电流
uint16_t ReadChargeCurrent(void) {
return charge_current_ma;
}
// NTC读取电池温度
uint16_t ReadBatteryTemp(void) {
return battery_temp_c;
}
// 设置充电电流
void SetChargeCurrent(uint16_t current_ma) {
// 通过PWM或DAC控制PMIC的充电电流
// 这里简化处理
charge_current_ma = current_ma;
}
// 充电控制主循环
void ChargeControl_Task(void) {
battery_voltage_mv = ReadBatteryVoltage();
charge_current_ma = ReadChargeCurrent();
battery_temp_c = ReadBatteryTemp();
// 温度保护
if(battery_temp_c > 45 || battery_temp_c < 0) {
SetChargeCurrent(0);
charge_state = CHARGE_STATE_IDLE;
printf("Temperature out of range, stop charging\n");
return;
}
switch(charge_state) {
case CHARGE_STATE_IDLE:
if(battery_voltage_mv < MAX_CHARGE_VOLTAGE) {
if(battery_voltage_mv < 3000) {
charge_state = CHARGE_STATE_TRICKLE;
} else {
charge_state = CHARGE_STATE_CC;
}
}
break;
case CHARGE_STATE_TRICKLE:
// 电池电压过低,先用小电流预充
SetChargeCurrent(200);
if(battery_voltage_mv >= 3000) {
charge_state = CHARGE_STATE_CC;
}
break;
case CHARGE_STATE_CC:
// 恒流充电阶段
SetChargeCurrent(CHARGE_CURRENT_CC);
if(battery_voltage_mv >= MAX_CHARGE_VOLTAGE) {
charge_state = CHARGE_STATE_CV;
}
break;
case CHARGE_STATE_CV:
// 恒压充电阶段
// 电压保持在4.2V,电流逐渐减小
if(charge_current_ma <= CHARGE_CURRENT_CV) {
charge_state = CHARGE_STATE_DONE;
SetChargeCurrent(0);
printf("Charging complete!\n");
}
break;
case CHARGE_STATE_DONE:
// 充电完成
break;
}
// 打印充电状态
static uint32_t last_print = 0;
if(HAL_GetTick() - last_print > 1000) {
printf("State:%d V:%dmV I:%dmA Temp:%dC\n",
charge_state, battery_voltage_mv, charge_current_ma, battery_temp_c);
last_print = HAL_GetTick();
}
}
5.4 主程序
c
// main.c
#include "stm32f4xx_hal.h"
#include "pd_protocol.h"
#include "charge_control.h"
void SystemClock_Config(void);
void GPIO_Init(void);
void ADC_Init(void);
void UART_Init(void);
int main(void) {
HAL_Init();
SystemClock_Config();
GPIO_Init();
ADC_Init();
UART_Init();
printf("Fast Charging System Started\n");
// 初始化PD协议
PD_Init();
while(1) {
// PD协议状态机
PD_StateMachine();
// 充电控制
ChargeControl_Task();
HAL_Delay(100);
}
}
六、实际测试数据
在我的测试中,使用65W PD充电器给4500mAh电池充电:
| 时间 | 电量 | 功率 | 温度 |
|---|---|---|---|
| 0min | 0% | 45W | 25°C |
| 10min | 30% | 43W | 31°C |
| 20min | 55% | 38W | 35°C |
| 30min | 75% | 25W | 36°C |
| 45min | 90% | 12W | 34°C |
| 60min | 100% | 0W | 30°C |
可以看到,快充主要在前30分钟发挥作用,进入恒压阶段后功率会明显下降。这是为了保护电池,延长使用寿命。
七、安全保护机制
快充虽然方便,但必须做好安全防护:
7.1 过流保护
监测充电电流,超过设定值立即切断
7.2 过压保护
电池电压超过4.3V(安全阈值)立即停止充电
7.3 过温保护
- 充电器温度>80°C,降低输出功率
- 电池温度>45°C,停止充电
- 环境温度<0°C,禁止充电
7.4 短路保护
检测到输出短路,立即切断输出
代码实现:
c
// safety_protection.c
void SafetyCheck(void) {
uint16_t voltage = ReadBatteryVoltage();
uint16_t current = ReadChargeCurrent();
uint16_t temp = ReadBatteryTemp();
// 过压保护
if(voltage > 4300) {
DisableCharging();
SetError(ERROR_OVERVOLTAGE);
printf("ERROR: Battery overvoltage!\n");
}
// 过流保护
if(current > 3000) {
DisableCharging();
SetError(ERROR_OVERCURRENT);
printf("ERROR: Charging overcurrent!\n");
}
// 过温保护
if(temp > 45) {
DisableCharging();
SetError(ERROR_OVERTEMP);
printf("ERROR: Battery overtemperature!\n");
}
// 欠温保护
if(temp < 0) {
DisableCharging();
SetError(ERROR_UNDERTEMP);
printf("ERROR: Battery temperature too low!\n");
}
}
八、各厂商快充技术对比
| 技术 | 厂商 | 最大功率 | 电压范围 | 特点 |
|---|---|---|---|---|
| QC 4.0+ | 高通 | 100W | 5-20V | 兼容PD协议 |
| SuperVOOC | OPPO | 240W | 10V | 双电芯设计 |
| SuperCharge | 华为 | 100W | 10V/11V | 直充架构 |
| FlashCharge | vivo | 120W | 20V | 电荷泵技术 |
| Warp Charge | 一加 | 65W | 5V/10V | 低压大电流 |
| USB PD 3.1 | USB-IF | 240W | 5-48V | 通用标准 |
九、未来发展趋势
9.1 更高功率
已经有厂商推出240W快充,理论上可以在10分钟内充满5000mAh电池
9.2 无线快充
目前无线快充已达50W,但效率还有待提升
9.3 GaN氮化镓充电器
体积更小,效率更高,发热更低
9.4 石墨烯电池
新型电池材料,可以承受更大的充电电流
十、总结
手机快充技术的核心就是在保证安全的前提下,通过提高充电功率来缩短充电时间。实现方式主要有三种:高压小电流、低压大电流、以及PD这种灵活可调的方案。
在实际应用中,需要结合硬件电路和软件算法,做好协议握手、充电控制、安全保护等各个环节。虽然各家厂商的快充技术名称不同,但底层原理都是相通的。
希望这篇文章能帮助大家理解快充技术的原理,也欢迎一起交流讨论。
参考资料
- USB Power Delivery Specification Revision 3.1
- Qualcomm Quick Charge Technology
- TI BQ25890 Datasheet
- STM32 Battery Charging Application Note
关键词: 快充原理、USB PD、STM32、充电管理、PMIC、锂电池充电
开发环境: STM32CubeMX、Keil MDK、C语言
硬件平台: STM32F407、BQ25890、FUSB302