基于51单片机的PD协议移动电源控制程序
基于51单片机的PD协议移动电源控制程序
含PD协议通信、电池管理、充电控制和状态显示等功能。
#include <reg52.h>
#include <intrins.h>
// 硬件引脚定义
sbit USB_CC1 = P1^0;      // Type-C CC1检测引脚
sbit USB_CC2 = P1^1;      // Type-C CC2检测引脚
sbit USB_DM = P1^2;       // USB D- 引脚
sbit USB_DP = P1^3;       // USB D+ 引脚
sbit LED_RED = P2^0;      // 红色LED指示灯
sbit LED_GREEN = P2^1;    // 绿色LED指示灯
sbit LED_BLUE = P2^2;     // 蓝色LED指示灯
sbit CHG_EN = P3^0;       // 充电使能控制
sbit DIS_EN = P3^1;       // 放电使能控制
sbit KEY = P3^2;          // 功能按键
// ADC通道定义
#define ADC_BAT_VOLT  0   // 电池电压检测通道
#define ADC_BAT_TEMP  1   // 电池温度检测通道
#define ADC_OUT_VOLT  2   // 输出电压检测通道
#define ADC_OUT_CURR  3   // 输出电流检测通道
// PD协议相关定义
#define PD_SOURCE_CAPABILITIES 0x01
#define PD_REQUEST             0x02
#define PD_ACCEPT              0x03
#define PD_REJECT              0x04
#define PD_PS_RDY              0x05
// 电压档位定义 (单位: 0.1V)
#define VOLT_5V    50
#define VOLT_9V    90
#define VOLT_12V   120
#define VOLT_15V   150
#define VOLT_20V   200
// 全局变量
unsigned char pd_voltage = VOLT_5V;  // 当前输出电压档位
unsigned char battery_level = 0;     // 电池电量百分比
unsigned char pd_connected = 0;      // PD设备连接状态
unsigned char charging_state = 0;    // 充电状态
// 函数声明
void System_Init(void);
void Timer0_Init(void);
void ADC_Init(void);
void PD_Protocol_Handler(void);
void Battery_Management(void);
void Charging_Control(void);
void LED_Display(void);
unsigned int Read_ADC(unsigned char channel);
void Delay_ms(unsigned int ms);
void UART_Send_Byte(unsigned char dat);
void UART_Send_String(char *s);
// 主函数
void main(void)
{
    System_Init();      // 系统初始化
    Timer0_Init();      // 定时器初始化
    ADC_Init();         // ADC初始化
    
    EA = 1;             // 开启总中断
    
    UART_Send_String("PD Power Bank Started\r\n");
    
    while(1)
    {
        PD_Protocol_Handler();  // PD协议处理
        Battery_Management();   // 电池管理
        Charging_Control();     // 充放电控制
        LED_Display();          // LED状态显示
    }
}
// 系统初始化
void System_Init(void)
{
    // 设置IO方向
    P1 = 0xFF;  // P1口输入
    P2 = 0x00;  // P2口输出
    P3 = 0x04;  // P3.2为输入,其他输出
    
    // 初始状态
    CHG_EN = 0;     // 充电禁用
    DIS_EN = 0;     // 放电禁用
    LED_RED = 0;
    LED_GREEN = 0;
    LED_BLUE = 0;
}
// 定时器0初始化 (用于1ms定时)
void Timer0_Init(void)
{
    TMOD |= 0x01;   // 定时器0,模式1
    TH0 = 0xFC;     // 1ms定时
    TL0 = 0x66;
    ET0 = 1;        // 允许定时器0中断
    TR0 = 1;        // 启动定时器0
}
// ADC初始化
void ADC_Init(void)
{
    P1ASF = 0x0F;   // 设置P1.0-P1.3为模拟输入
    ADC_RES = 0;
    ADC_CONTR = 0x80; // 开启ADC电源,ADC转换速度设为最慢
}
// 定时器0中断服务函数
void Timer0_ISR() interrupt 1
{
    static unsigned int timer_count = 0;
    
    TH0 = 0xFC;     // 重装初值
    TL0 = 0x66;
    
    timer_count++;
    
    // 每100ms执行一次
    if(timer_count >= 100)
    {
        timer_count = 0;
        
        // 检测按键
        if(KEY == 0)
        {
            Delay_ms(20); // 消抖
            if(KEY == 0)
            {
                // 循环切换电压档位
                if(pd_voltage == VOLT_5V) pd_voltage = VOLT_9V;
                else if(pd_voltage == VOLT_9V) pd_voltage = VOLT_12V;
                else if(pd_voltage == VOLT_12V) pd_voltage = VOLT_15V;
                else if(pd_voltage == VOLT_15V) pd_voltage = VOLT_20V;
                else pd_voltage = VOLT_5V;
                
                UART_Send_String("Voltage Changed: ");
                UART_Send_Byte(pd_voltage/10 + '0');
                UART_Send_Byte('.');
                UART_Send_Byte(pd_voltage%10 + '0');
                UART_Send_String("V\r\n");
                
                // 等待按键释放
                while(KEY == 0);
            }
        }
    }
}
// PD协议处理
void PD_Protocol_Handler(void)
{
    static unsigned char last_cc1, last_cc2;
    unsigned char current_cc1, current_cc2;
    
    // 读取CC引脚状态
    current_cc1 = USB_CC1;
    current_cc2 = USB_CC2;
    
    // 检测连接状态变化
    if((current_cc1 != last_cc1) || (current_cc2 != last_cc2))
    {
        last_cc1 = current_cc1;
        last_cc2 = current_cc2;
        
        // 判断连接状态
        if((current_cc1 == 0) || (current_cc2 == 0))
        {
            pd_connected = 1;
            UART_Send_String("PD Device Connected\r\n");
            
            // 发送电源能力信息
            PD_Send_Source_Capabilities();
        }
        else
        {
            pd_connected = 0;
            DIS_EN = 0; // 禁用放电
            UART_Send_String("PD Device Disconnected\r\n");
        }
    }
    
    // 如果已连接,处理PD通信
    if(pd_connected)
    {
        // 模拟PD通信(实际应用中需使用专用PD芯片或软件实现)
        if(PD_Receive_Message())
        {
            // 处理接收到的PD消息
            PD_Process_Message();
        }
    }
}
// 发送电源能力信息
void PD_Send_Source_Capabilities(void)
{
    // 实际应用中需通过USB PD物理层发送
    UART_Send_String("Sending Source Capabilities\r\n");
    UART_Send_String("5V/3A, 9V/3A, 12V/3A, 15V/3A, 20V/3A\r\n");
}
// 接收PD消息(模拟)
unsigned char PD_Receive_Message(void)
{
    // 简化的模拟接收
    static unsigned char counter = 0;
    
    if(counter++ > 100)
    {
        counter = 0;
        return 1; // 模拟接收到消息
    }
    return 0;
}
// 处理PD消息
void PD_Process_Message(void)
{
    // 模拟处理PD消息
    UART_Send_String("Received PD Request\r\n");
    
    // 发送接受响应
    UART_Send_String("Sending PD Accept\r\n");
    
    // 发送电源准备好消息
    UART_Send_String("Sending Power Ready\r\n");
    
    // 使能放电
    DIS_EN = 1;
    UART_Send_String("Output Enabled\r\n");
}
// 电池管理
void Battery_Management(void)
{
    unsigned int bat_voltage, bat_temp;
    static unsigned char bat_counter = 0;
    
    // 每100ms读取一次电池参数
    if(bat_counter++ >= 10)
    {
        bat_counter = 0;
        
        // 读取电池电压 (单位: mV)
        bat_voltage = Read_ADC(ADC_BAT_VOLT) * 10; // 假设ADC值对应mV
        
        // 读取电池温度 (单位: 0.1℃)
        bat_temp = Read_ADC(ADC_BAT_TEMP);
        
        // 计算电池电量 (简化算法)
        if(bat_voltage > 4200) battery_level = 100;
        else if(bat_voltage > 4100) battery_level = 90;
        else if(bat_voltage > 4000) battery_level = 80;
        else if(bat_voltage > 3900) battery_level = 70;
        else if(bat_voltage > 3800) battery_level = 60;
        else if(bat_voltage > 3700) battery_level = 50;
        else if(bat_voltage > 3600) battery_level = 40;
        else if(bat_voltage > 3500) battery_level = 30;
        else if(bat_voltage > 3400) battery_level = 20;
        else if(bat_voltage > 3300) battery_level = 10;
        else battery_level = 0;
        
        // 电池保护
        if(bat_voltage < 3200) // 过放保护
        {
            DIS_EN = 0; // 禁用放电
            CHG_EN = 1; // 强制充电
            UART_Send_String("Battery Under Voltage! Charging Enabled\r\n");
        }
        
        if(bat_temp > 500) // 温度过高 (50℃)
        {
            DIS_EN = 0; // 禁用放电
            CHG_EN = 0; // 禁用充电
            UART_Send_String("Battery Over Temperature! Charging/Discharging Disabled\r\n");
        }
    }
}
// 充放电控制
void Charging_Control(void)
{
    unsigned int out_voltage, out_current;
    static unsigned char charge_counter = 0;
    
    // 每200ms读取一次输出参数
    if(charge_counter++ >= 20)
    {
        charge_counter = 0;
        
        // 读取输出电压 (单位: mV)
        out_voltage = Read_ADC(ADC_OUT_VOLT) * 10;
        
        // 读取输出电流 (单位: mA)
        out_current = Read_ADC(ADC_OUT_CURR) * 10;
        
        // 过压保护
        if(out_voltage > (pd_voltage * 100 + 500)) // 超过设定值0.5V
        {
            DIS_EN = 0; // 禁用放电
            UART_Send_String("Output Over Voltage! Discharging Disabled\r\n");
        }
        
        // 过流保护
        if(out_current > 3500) // 超过3.5A
        {
            DIS_EN = 0; // 禁用放电
            UART_Send_String("Output Over Current! Discharging Disabled\r\n");
        }
        
        // 短路保护
        if(out_voltage < 1000 && out_current > 3000) // 电压低于1V且电流大于3A
        {
            DIS_EN = 0; // 禁用放电
            UART_Send_String("Short Circuit Detected! Discharging Disabled\r\n");
        }
    }
}
// LED状态显示
void LED_Display(void)
{
    static unsigned char led_counter = 0;
    
    // LED显示状态
    if(led_counter++ >= 50) // 每500ms更新一次
    {
        led_counter = 0;
        
        // 充电状态
        if(charging_state)
        {
            // 充电中 - 呼吸灯效果
            static unsigned char pwm_val = 0;
            static bit dir = 0;
            
            if(dir == 0)
            {
                if(++pwm_val == 100) dir = 1;
            }
            else
            {
                if(--pwm_val == 0) dir = 0;
            }
            
            // 红色LED呼吸效果
            if(led_counter < pwm_val) LED_RED = 1;
            else LED_RED = 0;
            
            LED_GREEN = 0;
            LED_BLUE = 0;
        }
        else
        {
            // 电量显示
            if(battery_level > 70)
            {
                LED_RED = 0;
                LED_GREEN = 1; // 绿色 - 电量充足
                LED_BLUE = 0;
            }
            else if(battery_level > 30)
            {
                LED_RED = 0;
                LED_GREEN = 0;
                LED_BLUE = 1; // 蓝色 - 电量中等
            }
            else
            {
                LED_RED = 1; // 红色 - 电量低
                LED_GREEN = 0;
                LED_BLUE = 0;
            }
        }
        
        // PD输出状态
        if(pd_connected && DIS_EN)
        {
            // 输出中 - 蓝色LED闪烁
            static bit blink = 0;
            blink = !blink;
            LED_BLUE = blink;
        }
    }
}
// 读取ADC值
unsigned int Read_ADC(unsigned char channel)
{
    unsigned int result;
    
    ADC_CONTR = 0x80 | (channel & 0x07); // 选择通道并启动转换
    _nop_(); _nop_(); _nop_(); // 等待转换完成
    
    while(!(ADC_CONTR & 0x10)); // 等待转换完成
    ADC_CONTR &= ~0x10; // 清除完成标志
    
    result = ADC_RES;
    result = (result << 2) | (ADC_RESL & 0x03); // 10位ADC
    
    return result;
}
// 延时函数
void Delay_ms(unsigned int ms)
{
    unsigned int i, j;
    for(i=0; i<ms; i++)
        for(j=0; j<120; j++);
}
// UART发送一个字节
void UART_Send_Byte(unsigned char dat)
{
    SBUF = dat;
    while(!TI);
    TI = 0;
}
// UART发送字符串
void UART_Send_String(char *s)
{
    while(*s)
    {
        UART_Send_Byte(*s++);
    }
}
程序功能说明
1. PD协议处理
void PD_Protocol_Handler(void)
{
    // 检测CC引脚状态变化
    // 发送电源能力信息
    // 处理PD请求和响应
    // 控制输出使能
}
2. 电池管理
void Battery_Management(void)
{
    // 监测电池电压和温度
    // 计算电池电量百分比
    // 实现过放保护和过温保护
}
3. 充放电控制
void Charging_Control(void)
{
    // 监测输出电压和电流
    // 实现过压、过流和短路保护
    // 控制充放电状态
}
4. LED状态显示
void LED_Display(void)
{
    // 显示电池电量状态
    // 充电状态呼吸灯效果
    // PD输出状态指示
}
参考源码 针对PD协议移动电源进行开发的51单片机控制程序 youwenfan.com/contentcna/70937.html
硬件连接说明
1. 电源部分
电池组 + --------[MOSFET]-----+------ USB-C VBUS
          |                  |
电池组 - --------+            |
                |            |
                +--[升降压电路]--+
2. 控制部分
STC89C52RC/STC12C5A60S2
  P1.0 ---- USB CC1
  P1.1 ---- USB CC2
  P1.2 ---- USB D-
  P1.3 ---- USB D+
  P1.4 ---- ADC 电池电压检测
  P1.5 ---- ADC 电池温度检测
  P1.6 ---- ADC 输出电压检测
  P1.7 ---- ADC 输出电流检测
  
  P2.0 ---- LED_RED
  P2.1 ---- LED_GREEN
  P2.2 ---- LED_BLUE
  
  P3.0 ---- CHG_EN (充电使能)
  P3.1 ---- DIS_EN (放电使能)
  P3.2 ---- KEY (功能按键)
3. PD协议实现方案
由于51单片机本身不支持USB PD协议,本设计采用以下两种方案之一:
方案1:软件模拟PD协议(简化版)
- 通过CC引脚检测连接状态
 - 使用UART模拟PD通信
 - 支持基本电压档位切换
 
方案2:专用PD协议芯片
+-----------------+          +-----------------+
|  51 单片机       |   I2C    |  PD协议芯片      |
|                 |<-------->|  (如CH236D)     |
|                 |          |                 |
+--------+--------+          +--------+--------+
         |                            |
         |                            |
         |                            |
+--------+--------+          +--------+--------+
|  电池管理电路    |          |  USB-C接口      |
|  升降压电路      |          |                 |
|                 |          |                 |
+-----------------+          +-----------------+
关键算法详解
1. 电池电量计算
// 基于电压的简化电量计算
if(bat_voltage > 4200) battery_level = 100;
else if(bat_voltage > 4100) battery_level = 90;
...
2. 充电状态呼吸灯
// 呼吸灯效果实现
if(dir == 0) {
    if(++pwm_val == 100) dir = 1;
} else {
    if(--pwm_val == 0) dir = 0;
}
if(led_counter < pwm_val) LED_RED = 1;
else LED_RED = 0;
3. 保护机制
// 过压保护
if(out_voltage > (pd_voltage * 100 + 500)) {
    DIS_EN = 0;
}
// 过流保护
if(out_current > 3500) {
    DIS_EN = 0;
}
// 短路保护
if(out_voltage < 1000 && out_current > 3000) {
    DIS_EN = 0;
}
系统工作流程
- 
初始状态
- 所有LED熄灭
 - 充放电均禁用
 - 检测USB连接
 
 - 
设备连接
- 检测CC引脚状态变化
 - 发送电源能力信息
 - 协商输出电压
 
 - 
放电模式
- 使能放电电路
 - 监测输出电压电流
 - 显示电池电量
 
 - 
充电模式
- 检测输入电源
 - 使能充电电路
 - 实现恒流/恒压充电
 
 - 
保护机制
- 电池过放/过温保护
 - 输出过压/过流保护
 - 短路保护
 
 
优化建议
1. 增加快充协议支持
// 添加QC协议支持
void QC_Protocol_Handler(void)
{
    // 检测D+/D-电压
    // 发送QC电压请求
    // 切换升降压电路输出
}
2. 增加电量计功能
// 库仑计实现
void Coulomb_Counter(void)
{
    // 测量充放电电流
    // 积分计算电量
    // 更新剩余容量
}
3. 添加OLED显示
// OLED显示函数
void OLED_Display(void)
{
    // 显示输出电压电流
    // 显示电池电量
    // 显示温度信息
    // 显示工作状态
}
4. 低功耗优化
// 休眠模式
void Enter_Sleep_Mode(void)
{
    // 禁用不需要的外设
    // 设置IO状态
    // 进入空闲/掉电模式
    // 定时唤醒检测
}
测试与调试
1. PD协议测试
- 连接PD充电器,验证5V输出
 - 按键切换电压档位,验证9V/12V/15V/20V输出
 - 断开连接,验证自动关闭输出
 
2. 保护功能测试
- 输出端短路,验证短路保护
 - 连接大功率负载,验证过流保护
 - 电池过放测试,验证充电强制启用
 
3. 性能测试
- 测量转换效率(输入功率 vs 输出功率)
 - 测试输出电压纹波
 - 测量不同负载下的电压稳定性
 
完整系统框架
+------------------+
|    51单片机       |
|   +-----------+  |
|   | PD协议处理 |  |
|   +-----------+  |
|   +-----------+  |
|   | 电池管理   |  |
|   +-----------+  |
|   +-----------+  |
|   | 充放电控制 |  |
|   +-----------+  |
|   +-----------+  |
|   | 状态显示   |  |
|   +-----------+  |
+------------------+
         |
         | 控制信号
         |
+------------------+
|  电源管理电路     |
|  +-------------+ |
|  | 升降压电路   | |
|  +-------------+ |
|  +-------------+ |
|  | 保护电路     | |
|  +-------------+ |
+------------------+
         |
         | USB-C
         |
+------------------+
|   外部设备        |
+------------------+
这个程序实现了基于51单片机的PD协议移动电源核心控制功能,包括PD协议处理、电池管理、充放电控制和状态显示。程序采用模块化设计,可根据实际硬件进行调整和扩展。
                    
                
                
            
        
浙公网安备 33010602011771号