这个是我自己制作的一个QC2.0快充取电器,主要功能是将支持QC快速充电头的电压取出来使用。功能:用一个按键循环切换输出电压5V--9V--12V....;用一颗LED不同闪烁频率指示不同对应电压。
原理:用单片机IO口控制输出电压达到效果

优点是:1.简单实用 2.成本低廉
缺点是:1.功能简单 2.无输出反馈
特别注意:1.无输出监测,且有EEPROM记忆,每次上电需确定输出电压,再连接用电电路。2. 即使无快充功能(或不支持的协议的)的充电头,指示灯依然指示设定的电压。

制作出来的实物图如下:
image.png

Altium Designer画的原理图和PCB图如下:
image.png
image.png
image.png

单片机源程序如下:


  • /*------------------------------------------------------------------*/
  • /* --- STC MCU International Limited -------------------------------*/

  • /*------------------------------------------------------------------*/

  • #include        "config.h"
  • #include        "GPIO.h"
  • #include        "delay.h"
  • #include    "eeprom.h"

  • /*************        功能说明        **************

  • 本程序是快充 功能,MCU --> STC15W204S  @24MHz

  • *******************************************/
  • #define USBA_PD 0  //D+下拉电阻
  • #define USBA_PU 1  //D+上拉电阻
  • #define USBB_PD 2  //D-下拉电阻
  • #define USBB_PU 3  //D-上拉电阻

  • sbit LED = P5^5;
  • sbit KEY = P5^4;
  • /******************************************/

  • //配置IO口为准双向
  • #define IO_BZ_CONF(IO,PIN) do{\
  •     IO##M0&=~(1<<PIN);\
  •     IO##M1&=~(1<<PIN);\
  •     }while(0)\

  • /******************************************/

  • //配置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)\

  • /******************************************/

  • //配置IO口为开漏
  • #define IO_OD_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)

  • /*************        本地常量声明        **************/
  • #define Modmax 3

  • /*************        本地变量声明        **************/
  • u16 del;
  • u8 tmp[2];
  • /*************        本地函数声明        **************/


  • /*************  外部函数和变量声明 *****************/

  • /*************        本地函数 **************************/
  • void step1(void)
  • {
  •     IO_PP_CONF(P3,USBA_PU);
  •     IO_PP_CONF(P3,USBA_PD);
  •     IO_OUT_HIGH(P3,USBA_PU);
  •     IO_OUT_LOW(P3,USBA_PD);//P30、P31强推挽 D+为0.6V

  •     IO_HR_CONF(P3,USBB_PU);
  •     IO_HR_CONF(P3,USBB_PD);//P32、P33高阻态 D-为断开
  • }
  • /*************        本地函数 ******************/
  • u8 KEY_Scan(u8 mode)
  • {
  •            static u8 key_up=1;//按键按松开标志
  •         if(mode)key_up=1;  //支持连按
  •         if(key_up&&(KEY==0))//||KEY2==0))
  •         {
  •                 Delay_nms(10);//去抖动
  •                 key_up=0;
  •                 if(KEY==0)


  •             return 1;

  •                 //else if(KEY1==0)return KEY1_PRES;
  •        // else if(KEY2==0)return KEY2_PRES;
  •         }else if(KEY==1)key_up=1;
  •          return 0;// 无按键按下
  • }
  • /*************        本地函数 ******************/
  • void OUT5V(void)
  • {
  •     Delay_nms(500);
  •     step1();
  •     Delay_nms(3000);


  •     IO_PP_CONF(P3,USBA_PU);
  •     IO_PP_CONF(P3,USBA_PD);
  •     IO_OUT_HIGH(P3,USBA_PU);
  •     IO_OUT_LOW(P3,USBA_PD);//P30、P31强推挽 D+为0.6V

  •     IO_HR_CONF(P3,USBB_PU);
  •     IO_PP_CONF(P3,USBB_PD);//P32、P33高阻态 D-为0V
  •     IO_OUT_LOW(P3,USBB_PD);

  •     del = 1;
  • }
  • /*************        本地函数 ******************/
  • void OUT9V(void)
  • {
  •     Delay_nms(500);
  •     step1();
  •     Delay_nms(3000);

  •     IO_PP_CONF(P3,USBA_PU);
  •     IO_HR_CONF(P3,USBA_PD);
  •     IO_OUT_HIGH(P3,USBA_PU);//P30、P31强推挽 D+为3.3V

  •     IO_PP_CONF(P3,USBB_PU);
  •     IO_PP_CONF(P3,USBB_PD);
  •     IO_OUT_HIGH(P3,USBB_PU);
  •     IO_OUT_LOW(P3,USBB_PD);//P32、P33强推挽 D-为0.6V

  •     del = 500;
  • }
  • /*************        本地函数 ******************/
  • void OUT12V(void)
  • {
  •     Delay_nms(500);
  •     step1();
  •     Delay_nms(3000);

  •     IO_PP_CONF(P3,USBA_PU);
  •     IO_PP_CONF(P3,USBA_PD);
  •     IO_OUT_HIGH(P3,USBA_PU);
  •     IO_OUT_LOW(P3,USBA_PD);//P30、P31强推挽 D+为0.6V

  •     IO_PP_CONF(P3,USBB_PU);
  •     IO_PP_CONF(P3,USBB_PD);
  •     IO_OUT_HIGH(P3,USBB_PU);
  •     IO_OUT_LOW(P3,USBB_PD);//P32、P33强推挽 D-为0.6V

  •     del = 150;
  • }
  • /*************        本地函数 ******************
  • void OUT20V(void)
  • {
  •     Delay_nms(500);
  •     step1();
  •     Delay_nms(3000);

  •     IO_PP_CONF(P3,USBA_PU);
  •     IO_HR_CONF(P3,USBA_PD);
  •     IO_OUT_HIGH(P3,USBA_PU);//P30、P31强推挽 D+为3.3V

  •     IO_PP_CONF(P3,USBB_PU);
  •     IO_HR_CONF(P3,USBB_PD);
  •     IO_OUT_HIGH(P3,USBB_PU);//P32、P33强推挽 D-为3.3V

  •     del = 10;
  • }
  • /******************** IO配置函数 **************************/
  • void        GPIO_config(void)
  • {
  •         GPIO_InitTypeDef        GPIO_InitStructure;                //结构定义
  •     //P3全部高阻态
  •         GPIO_InitStructure.Pin  = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;                //指定要初始化的IO, 或操作
  •         GPIO_InitStructure.Mode = GPIO_HighZ;                //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
  •         GPIO_Inilize(GPIO_P3,&GPIO_InitStructure);        //初始化
  •     //P5.4是按键
  •         GPIO_InitStructure.Pin  = GPIO_Pin_4;                //指定要初始化的IO, GPIO_Pin_4
  •         GPIO_InitStructure.Mode = GPIO_PullUp;                //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
  •         GPIO_Inilize(GPIO_P5,&GPIO_InitStructure);        //初始化
  •     //P5.5是LED指示灯
  •         GPIO_InitStructure.Pin  = GPIO_Pin_5;                //指定要初始化的IO, GPIO_Pin_4
  •     GPIO_InitStructure.Mode = GPIO_PullUp;
  •         //GPIO_InitStructure.Mode = GPIO_OUT_PP;                //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
  •         GPIO_Inilize(GPIO_P5,&GPIO_InitStructure);        //初始化
  • }



  • /******************** 主函数 **************************/
  • void main(void)
  • {
  •         u8 i=0;

  •         GPIO_config();
  •         EEPROM_read_n(0x0000,tmp,2);
  • //    Delay_nms(500);
  • //    step1();
  • //    Delay_nms(3000);
  • //    LED = 1;
  •     if(tmp[0]==0)
  •     {
  •             OUT5V();
  •     }else if(tmp[0]==1)
  •     {
  •             OUT9V();
  •     }else if(tmp[0]==2)
  •     {
  •             OUT12V();
  •     }
  • //        else if(tmp[0]==3)
  • //    {
  • //            OUT20V();
  • //    }
  •     else
  •     {
  •         tmp[0]=0;
  •         tmp[1]=0xff;
  •         EEPROM_SectorErase(0x0000);
  •         EEPROM_write_n(0x0000,tmp,2);
  •         OUT5V();
  •     }

  •         while(1)
  •         {
  •         i = KEY_Scan(0);
  •         if(i)
  • ……………………