自制QC2.0诱骗器
实际上,安卓手机的快充头就是一个可以更改副边反馈比的可调压开关电源。拥有一个快充头,对我们来说,就是拥有了一个可以调整输出电压的电源。我们只需要模拟手机与快充头进行握手,就可以激活高电压快充协议,进而将快充头变成一个DC电源。
快充协议的握手部分在副边部分,当快充头和手机握手成功时,副边的快充控制芯片就会调整反馈给原边的反馈比,使原边的开关电源占空比升高,进而提高副边的输出电压。对于QC2.0
来说,我们总共可以得到5V
、9V
、12V
和20V
四挡电压,但是一般的充电头都只支持前三档电压。对于QC3.0
来说,我们可以获得3.6V-20V
的可调电压,以0.2V
为步进。一般的手机充电头能做到4V-12V
的可调范围。这一次为了简单起见,我们先尝试制作QC2.0的快充诱骗器。
废话不多说,要激活快充协议,我们首先要知道快充协议握手的过程。好在,QC2.0的握手协议并不复杂,大致可以分为以下几个步骤。
- QC快充头在默认情况下,充电器内部的mos管短接D-和D+并输出5V电压。这样,对于普通的手机或者不支持QC快充协议的手机,识别到此充电器是支持DCP(BC1.2)协议的充电头,对于安卓手机来说激活5V1.5A充电,iPhone激活5V1A充电。
- 设备端(也就是我们的诱骗器)在
D+
上输出0.6V
电压,此时由于充电头内部mos管导通,D-
上也会出现0.6V
的电压。维持D+上的0.6V超过1.25
秒以后,充电头内部mos断开,D-电压变为0V
,此时可以向D-
加载电压。 - 在检测到D-电压变为
0V
以后,设备即可确定充电头支持QC协议。此时设备端通过设置D+、D-的电压值,即可向充电头申请对应档位的电压。具体的对应值如下: - 只需要将D+、D-两引脚均断开,即可关闭快充模式,快充头重新回到DCP模式,输出5V。
档位 | 5V | 9V | 12V | 20V |
---|---|---|---|---|
D+电压 | 0.6V | 3.3V | 0.6V | 3.3V |
D-电压 | 0V | 0.6V | 0.6V | 3.3V |
通过上面的操作,相信大家已经了解到了如何握手QC2.0协议了。接下来我们考虑一下,如何使用单片机去模拟这个握手过程。最大的问题就是如何产生0.6V
与3.3V
的电压。我们首先想到的是DAC。但是如此小的一个制作,我们根本不需要也没必要去使用昂贵的带DAC的单片机。那么,我们的思路就限定在了使用普通单片机的普通IO口上。3.3V电压直接使用3.3V供电的单片机输出高电平即可,而0.6V也可以通过电阻分压3.3V得到。于是,我设计了如下这样的电路,电路中,D+PU
、D+
、D-PU
、D-PD
四个网络连接到了3.3V单片机的普通IO上。
乍一看可能有点懵,我们慢慢分析。根据上面的表格,我们若不考虑充电头给我们的反馈和20V电压档位,我们总共需要
D+
输出0.6V
(握手、5V档位与12V档位)D+
输出3.3V
(9V档位)D-
输出0.6V
(9V档位、12V档位)D-
断开连接(握手与5V档位)
四种状态。因此,每一根数据线只需要完成两种电平状态的切换即可。因此,对应上面四个状态,我们总共也有四种输出模式:
- D+PU输出3.3V,D+高阻,在D+上即可得到
0.6V
电压 - D+PU高阻,D+输出3.3V,在D+上即可得到
3.3V
电压 - D-PU输出3.3V,D-PD输出0V(均为推挽输出),在D-上即可得到
0.6V
电压 - D-PU、D-PD均高阻,即可使D-断开连接
这样,我们就用4个IO口实现了握手和三个档位的切换。使用一个8脚STC单片机,即可完成这项工作,剩下两个IO口分别连接一个LED和一个按键。设计中使用HT7533
,这是一款最高支持24V输入的高压LDO,对于这种只有十几ma的小单片机来说绰绰有余。注意单片机一定要选STC15W104
而不能选STC15F104E
,因为后者不能工作在3.3V下。 电路设计完了,接下来就是程序了。程序无非就是对IO口的操作,操作IO口的部分代码如下:
//配置IO口为推挽
#define IO_PP_CONF(IO,PIN) do { \
IO##M0|=(1<<PIN);\
IO##M1&=~(1<<PIN);\
}while(0)\
//配置IO口为高阻
#define IO_HR_CONF(IO,PIN) do { \
IO##M0&=~(1<<PIN);\
IO##M1|=(1<<PIN);\
}while(0)\
#define IO_OUT_HIGH(IO,PIN) IO|=(1<<PIN)
#define IO_OUT_LOW(IO,PIN) IO&=~(1<<PIN)
//配置IO口为推挽
void USBDP_HIGH(void) { //USBD+输出3.3V
IO_OUT_HIGH(P3,USBDP);//USBDP先输出高
IO_PP_CONF(P3,USBDP);//推挽输出
IO_HR_CONF(P3,USBDP_PU);//USBDP_PU为高阻
}
void USBDP_LOW(void) { //USBD+输出0.6V
IO_HR_CONF(P3,USBDP);//USBDP为高阻
IO_OUT_HIGH(P3,USBDP_PU);
IO_PP_CONF(P3,USBDP_PU);//USBDP_PU推挽输出
}
void USBDM_LOW(void) { //USBD-输出0.6V
IO_OUT_HIGH(P3,USBDM_PU);
IO_OUT_LOW(P3,USBDM_PD);
IO_PP_CONF(P3,USBDM_PU);//USBDM_PU推挽输出
IO_PP_CONF(P3,USBDM_PD);//USBDM_PD推挽输出
}
void USBDM_DISCONN(void) { //USBD-断开
IO_HR_CONF(P3,USBDM_PD);//USBDM为高阻
IO_HR_CONF(P3,USBDM_PU);//USBDM_PU为高阻
}
剩下的程序比较简单,不在此赘述,有兴趣的朋友可以到文末下载代码查看。程序实现的功能主要是,上电后默认输出上一次保存在EEPROM中的电压值,LED灯单闪为5V,双闪为9V,三闪为12V,短按按键可以切换档位,长按按键可以保存当前档位为默认值,下次上电自动读取此电压值。
下面为诱骗器的实物图。
可以看到体积还是很小的。下面是用小米充电宝诱骗9V和12V的效果: