[中微快充电压申请kit] 测评报告4: QC快充协议学习
[复制链接]
本帖最后由 flyaqiao 于 2023-11-19 19:09 编辑
环境搞了,灯也点了,应该要学习一下快充了,经过一周的爬网,发现PD的资源很少,目前也没搞明白,但发现QC好像比较简单,那么我们就先从QC开始学习!
从别人那复制一段说明,想放链接,找不到了,对不起原作者了:
1、手机在d+上加0.6v电压,这时充电器内部d+和d-是联通的,d-也是0.6v。
2、在1.35秒后,充电器断开d+和d-的联通,d-电压降到0,这时表示充电器支持协议。
3、接下来就是手机请求电压,并保持:
在d+加0.6v,d-加0v时,输出5v;
在d+加3.3v,d-加0.6v时,输出9v;
在d+加0.6v,d-加0.6v时,输出12v;
在d+加3.3v,d-加3.3v时,输出20v;
在d+加0.6v,d-加3.3v时,充电器进入continuous mode 也就是我们称的qc3.0模式。
Portable Device | HVDCP Class A | HVDCP Class B
D+ | D- | Adapate Voltage| Adapter Voltage
0.6V | 0.6V | 12V | 12V
3.3V | 0.6V | 9V | 9V
0.6V | 3.3V | Continuous mode| Continuous mode
3.3V | 3.3V | Previous voltage| 20V
0.6V | GND | 5V | 5V
上电---> D+0.6V D-浮空 ---> 延时1.5S ---> D-3.3V ---> 进入QC3.0模式 --->
由于我手头的充电器只支持5V和9V,所以我只测试了5V和9V的输出
I(31030) : VBUS=9048mv
I(31048) : VBUS=5096mv
I(31050) : VBUS=9056mv
I(31092) : VBUS=5096mv
I(31094) : VBUS=9048mv
I(31097) : VBUS=5096mv
I(31099) : VBUS=9056mv
I(31101) : VBUS=5096mv
I(31105) : VBUS=9056mv
I(31106) : VBUS=5096mv
I(31110) : VBUS=9048mv
I(31119) : VBUS=5096mv
I(31121) : VBUS=9056mv
I(31178) : VBUS=5088mv
I(31181) : VBUS=9048mv
I(31184) : VBUS=5096mv
I(31186) : VBUS=9056mv
I(31187) : VBUS=5096mv
I(31189) : VBUS=9056mv
I(31518) : VBUS=5096mv
root:/$
通过QC的协议可以看出,USB+和USB-需要通过不同电压值表示不同的功能.主要是0V,0.6V,3.3V三种状态.从官方原理图可以看出DP1输出低时USB+=0.6V,DP1输出3.3V时,USB+=3.3V
DM1和DM2输出0时,USB-=0V,DM1高DM2低时USB-=0.6V,DM1高,DM2高时USB-=3.3V
经过封装:
void DP_OUT_3V3()
{
GPIO3->DO_f.P6 = 1;
}
void DP_OUT_0V6()
{
GPIO3->DO_f.P6 = 0;
}
void DM_OUT_3V3()
{
GPIO1->DO_f.P6 = 1;
GPIO1->DO_f.P7 = 1;
}
void DM_OUT_0V6()
{
GPIO1->DO_f.P6 = 1;
GPIO1->DO_f.P7 = 0;
}
void DM_OUT_0V0()
{
GPIO1->DO_f.P6 = 0;
GPIO1->DO_f.P7 = 0;
}
QC的握手过程:
1、手机在D+或D-上加0.6V电压,这时D+和D-是通过充电器内部MOS管联通联通的,D+和D-同时是0.6V。
2、在1秒后,充电器内部断开D+和D-的联通,D-电压降到0,这时表示充电器支持协议。如果D-电压不变,说明是支持QC的充电器,但不支持数据通信.DCP模式
static int SupportQCCheck(void)
{
int dm_v;
DP_OUT_0V6();
OsWaitDelay(OS_TICKS_PER_SEC / 2); // 0.5s
dm_v = ADCA_ReadDM();
if (dm_v < 250) // 判断DM < 0.25V
return 0; // 不支持QC SDP
OsWaitDelay(OS_TICKS_PER_SEC);
dm_v = ADCA_ReadDM();
if (dm_v > 400)
return 1; // 支持QC, DCP
return 2; // 支持QC, CDP
}
int ADCA_ReadDM()
{
int ret = 0;
/*
(2)设置ADCA通道使能
*/
ADCA_EnableChannel(ADCA_CH_12_MSK); /*选择AN11/12*/
//SYS_SET_IOCFG(IOP16CFG, SYS_IOCFG_P16_AN11); /*关闭P16的数字功能*/
SYS_SET_IOCFG(IOP17CFG, SYS_IOCFG_P17_AN12); /*关闭P17的数字功能*/
/*
(5)开启ADCA
*/
ADCA_Start();
if (!ADCA_IS_BUSY()) {
ADCA_Go();
while (ADCA_IS_BUSY());
ret = ADCA_GetResult(ADCA_CH_12);
ADCA_DisableChannel(ADCA_CH_12_MSK);
ADCA_Stop();
}
return ret;
}
检测是通过ADC功能,检测DM2脚电压判断
然后再封装几个常用电压切换接口
static void QCSwitch12V(void)
{
DP_OUT_0V6();
DM_OUT_0V6();
}
static void QCSwitch9V(void)
{
DP_OUT_3V3();
DM_OUT_0V6();
}
static void QCSwitch5V(void)
{
DP_OUT_0V6();
DM_OUT_0V0();
}
接下来我们开一个任务来实现QC的握手和电压切换
void AppQCTask(void)
{
int vbus = 0;
int iVStep = 0;
SYS_SET_IOCFG(IOP36CFG, SYS_IOCFG_P36_GPIO);
SYS_SET_IOCFG(IOP16CFG, SYS_IOCFG_P16_GPIO);
SYS_SET_IOCFG(IOP17CFG, SYS_IOCFG_P17_GPIO);
GPIO_CONFIG_IO_MODE(GPIO3, GPIO_PIN_6, GPIO_MODE_OUTPUT);
GPIO_CONFIG_IO_MODE(GPIO1, GPIO_PIN_6, GPIO_MODE_OUTPUT);
GPIO_CONFIG_IO_MODE(GPIO1, GPIO_PIN_7, GPIO_MODE_OUTPUT);
GPIO3->DO_f.P6 = 0;
GPIO1->DO_f.P6 = 0;
GPIO1->DO_f.P7 = 0;
SYS_SET_IOCFG(IOP16CFG, SYS_IOCFG_P16_AN11);
SYS_SET_IOCFG(IOP17CFG, SYS_IOCFG_P17_AN12);
GPIO_CONFIG_IO_MODE(GPIO1, GPIO_PIN_6, GPIO_MODE_INPUT);
GPIO_CONFIG_IO_MODE(GPIO1, GPIO_PIN_7, GPIO_MODE_INPUT);
m_bSupportQC = SupportQCCheck(); // 充电器必须上电才能检测
SYS_SET_IOCFG(IOP16CFG, SYS_IOCFG_P16_GPIO);
SYS_SET_IOCFG(IOP17CFG, SYS_IOCFG_P17_GPIO);
GPIO_CONFIG_IO_MODE(GPIO1, GPIO_PIN_6, GPIO_MODE_OUTPUT);
GPIO_CONFIG_IO_MODE(GPIO1, GPIO_PIN_7, GPIO_MODE_OUTPUT);
if (m_bSupportQC) {
logInfo("QC is support => %d", m_bSupportQC);
QCSwitch5V();
// QCSwitchContinuousMode();
}
while (1) {
OsWaitDelay(OS_TICKS_PER_SEC); // 1s
vbus = (ADCA_ReadVBus() * 3300 / 4096) * 8;
logInfo("VBUS=%dmv", vbus);
UpdateLed(vbus);
OsWaitSignal(KEY_SIGNAL, INFINITE); // 等待按钮信号
if (m_bSupportQC) {
// QCAdd200mv();
// iVStep++;
if (iVStep == 0)
QCSwitch5V();
else if (iVStep == 1)
QCSwitch9V();
else if (iVStep == 2)
QCSwitch12V();
iVStep = (iVStep + 1) % 2;
}
}
}
任务第一步先检测是否支持QC,如果支持QC,则申请5V电压,然后串口打印当前电压,并等待按钮消息(按钮消息由GPIO中断触发)
触发后在5V和9V之间切换,按一次切换一次
void GPIO2_IRQHandler(void)
{
if (GPIO_GetIntFlag(GPIO2, GPIO_PIN_1)) {
OsSetSignal(KEY_SIGNAL);
GPIO_ClearIntFlag(GPIO2, GPIO_PIN_1);
}
}
// 按钮中断初始化
GPIO_CONFIG_IO_MODE(GPIO2, GPIO_PIN_1, GPIO_MODE_INPUT_WITH_PULL_UP);
GPIO_EnableInt(GPIO2, GPIO_PIN_1_MSK, GPIO_INT_EDGE_FALLING);
NVIC_SetPriority(GPIO2_IRQn, 2);
NVIC_EnableIRQ(GPIO2_IRQn);
通过这次学习,基本了解了QC2.0/QC3.0的工作原理,但是由于手头没有大功能QC的充电器,有的旧的手机充电器好像QC3.0也不支持.只支持5V/9V两种,所以测试的有限.
代码写的有点粗陋,还请各位大神多多指教.如有发现QC的不对之处,也请帮忙指正...
|