基于STM8的快充快放程序设计方案

基于STM8的快充快放程序设计方案

一、系统架构设计

1.1 硬件配置(STM8S003F3P6)

主控芯片:STM8S003F3P6(8KB Flash, 1KB RAM)
充电管理:CN3791(太阳能/锂电池充电芯片,支持MPPT)
快充协议:IP2712(支持QC/PD/FCP/SCP等协议)
放电控制:AO4407(P沟道MOS)+ AO3400(N沟道MOS)
监测电路:
  - 电压采样:ADC1(电池电压)
  - 电流采样:ACS712(霍尔电流传感器)
  - 温度监测:NTC热敏电阻
保护电路:DW01+(锂电保护IC)

1.2 功能指标

参数 规格
电池类型 单节锂电芯(3.7V)
快充输入 5-12V(支持QC2.0/3.0)
最大充电电流 2A(可调)
最大放电电流 3A(可调)
转换效率 ≥92%
保护功能 过充/过放/过流/短路/过温

二、软件架构

2.1 程序流程图

上电初始化
  ↓
检测电池状态
  ↓
  ├─→ 电池正常 → 进入待机模式
  ↓
  ├─→ 检测到充电输入 → 启动快充协议协商
  ↓
  ├─→ 协议握手成功 → 进入CC-CV充电阶段
  ↓
  ├─→ 充电完成 → 进入浮充维护
  ↓
  ├─→ 检测到放电请求 → 启动PWM放电控制
  ↓
  ├─→ 实时监控(电压/电流/温度)→ 触发保护

2.2 核心状态机

typedef enum {
    SYS_INIT = 0,        // 系统初始化
    SYS_STANDBY,         // 待机模式
    SYS_CHG_DETECT,      // 检测充电输入
    SYS_CHG_PROTOCOL,    // 快充协议握手
    SYS_CHG_CC,          // 恒流充电
    SYS_CHG_CV,          // 恒压充电
    SYS_CHG_DONE,        // 充电完成
    SYS_DISCHARGE,       // 放电模式
    SYS_PROTECT,         // 保护状态
    SYS_ERROR            // 故障状态
} SystemState;

三、关键代码实现

3.1 主程序(main.c)

/**
  * @file main.c
  * @brief STM8快充快放主程序
  */
#include "stm8s.h"
#include "battery.h"
#include "charge.h"
#include "discharge.h"
#include "protocol.h"
#include "protect.h"

SystemState sys_state = SYS_INIT;
BatteryInfo bat_info;
ChargeInfo chg_info;
DischargeInfo dis_info;

void main(void)
{
    /* 系统初始化 */
    System_Init();
    ADC_Init();
    PWM_Init();
    Timer_Init();
    UART_Init(9600);
    
    /* 读取电池信息 */
    Battery_ReadInfo(&bat_info);
    
    /* 主循环 */
    while (1)
    {
        /* 状态机处理 */
        switch (sys_state)
        {
            case SYS_INIT:
                sys_state = SYS_STANDBY;
                break;
                
            case SYS_STANDBY:
                /* 检测充电输入 */
                if (Charge_DetectInput())
                {
                    sys_state = SYS_CHG_PROTOCOL;
                }
                /* 检测放电请求 */
                else if (Discharge_DetectRequest())
                {
                    sys_state = SYS_DISCHARGE;
                }
                break;
                
            case SYS_CHG_PROTOCOL:
                /* 快充协议握手 */
                if (Protocol_Handshake(&chg_info))
                {
                    sys_state = SYS_CHG_CC;
                }
                else
                {
                    sys_state = SYS_ERROR;
                }
                break;
                
            case SYS_CHG_CC:
                /* 恒流充电 */
                Charge_CC_Control(&chg_info);
                if (bat_info.voltage >= CV_THRESHOLD)
                {
                    sys_state = SYS_CHG_CV;
                }
                break;
                
            case SYS_CHG_CV:
                /* 恒压充电 */
                Charge_CV_Control(&chg_info);
                if (chg_info.current < CV_CURRENT_MIN)
                {
                    sys_state = SYS_CHG_DONE;
                }
                break;
                
            case SYS_CHG_DONE:
                /* 充电完成,进入浮充 */
                Charge_FloatControl();
                if (!Charge_DetectInput())
                {
                    sys_state = SYS_STANDBY;
                }
                break;
                
            case SYS_DISCHARGE:
                /* 放电控制 */
                Discharge_Control(&dis_info);
                if (bat_info.voltage <= DISCHARGE_CUTOFF)
                {
                    sys_state = SYS_STANDBY;
                }
                break;
                
            case SYS_PROTECT:
                /* 保护状态 */
                Protect_Process();
                break;
                
            case SYS_ERROR:
                /* 错误处理 */
                Error_Handler();
                break;
        }
        
        /* 实时监测 */
        Battery_Monitor(&bat_info);
        Protect_Check(&bat_info, &chg_info, &dis_info);
        
        /* 延时10ms */
        Delay_Ms(10);
    }
}

3.2 充电控制(charge.c)

/**
  * @file charge.c
  * @brief 快充充电控制
  */
#include "charge.h"
#include "pwm.h"

/* 充电参数 */
#define CC_CURRENT      2000    // 恒流电流(mA)
#define CV_VOLTAGE      4200    // 恒压电压(mV)
#define CV_CURRENT_MIN  100     // 恒压截止电流(mA)
#define PRE_CHARGE_VOLT 3000    // 预充电压阈值(mV)

/* PWM配置 */
#define PWM_MAX_DUTY    95      // 最大占空比(%)
#define PWM_MIN_DUTY    5       // 最小占空比(%)

/* 充电控制结构体 */
ChargeInfo chg_info;

/* 初始化充电参数 */
void Charge_Init(void)
{
    chg_info.state = CHG_IDLE;
    chg_info.target_current = CC_CURRENT;
    chg_info.target_voltage = CV_VOLTAGE;
    chg_info.current_duty = 0;
    chg_info.input_voltage = 0;
    chg_info.protocol = PROTOCOL_NONE;
}

/* 检测充电输入 */
uint8_t Charge_DetectInput(void)
{
    uint16_t vin = ADC_Read(ADC_VIN);  // 输入电压采样
    chg_info.input_voltage = (vin * 3300 * 11) / 4095;  // 分压比11:1
    
    return (chg_info.input_voltage > 4500);  // >4.5V认为有输入
}

/* 恒流充电控制 */
void Charge_CC_Control(ChargeInfo *info)
{
    uint16_t bat_voltage = Battery_GetVoltage();
    uint16_t bat_current = Battery_GetCurrent();
    
    /* PI调节PWM占空比 */
    int16_t error = info->target_current - bat_current;
    info->current_duty += (error * 3) / 100;  // P=3
    
    /* 限制占空比范围 */
    if (info->current_duty > PWM_MAX_DUTY)
        info->current_duty = PWM_MAX_DUTY;
    if (info->current_duty < PWM_MIN_DUTY)
        info->current_duty = PWM_MIN_DUTY;
    
    /* 设置PWM输出 */
    PWM_SetDuty(PWM_CHG, info->current_duty);
    
    /* 更新充电状态 */
    info->state = CHG_CC;
}

/* 恒压充电控制 */
void Charge_CV_Control(ChargeInfo *info)
{
    uint16_t bat_voltage = Battery_GetVoltage();
    
    /* PI调节PWM占空比 */
    int16_t error = info->target_voltage - bat_voltage;
    info->current_duty += (error * 5) / 100;  // P=5
    
    /* 限制占空比范围 */
    if (info->current_duty > PWM_MAX_DUTY)
        info->current_duty = PWM_MAX_DUTY;
    if (info->current_duty < PWM_MIN_DUTY)
        info->current_duty = PWM_MIN_DUTY;
    
    /* 设置PWM输出 */
    PWM_SetDuty(PWM_CHG, info->current_duty);
    
    /* 更新充电状态 */
    info->state = CHG_CV;
}

/* 预充电(低压保护) */
void Charge_PreCharge(void)
{
    uint16_t bat_voltage = Battery_GetVoltage();
    
    if (bat_voltage < PRE_CHARGE_VOLT)
    {
        /* 小电流预充 */
        PWM_SetDuty(PWM_CHG, 10);  // 10%占空比
    }
}

3.3 快充协议(protocol.c)

/**
  * @file protocol.c
  * @brief 快充协议处理(QC2.0/3.0)
  */
#include "protocol.h"
#include "gpio.h"

/* QC协议引脚定义 */
#define QC_DP_PORT  GPIOC
#define QC_DP_PIN   GPIO_PIN_4
#define QC_DM_PORT  GPIOC
#define QC_DM_PIN   GPIO_PIN_5

/* 协议状态 */
ProtocolState proto_state = PROTOCOL_IDLE;

/* QC2.0电压设置 */
typedef enum {
    QC2_5V = 0,
    QC2_9V,
    QC2_12V,
    QC2_20V
} QC2_Voltage;

/* QC3.0步进电压 */
#define QC3_STEP_200MV  0x01
#define QC3_STEP_20MV   0x02

/* 初始化QC协议 */
void Protocol_Init(void)
{
    /* 配置DP/DM为开漏输出 */
    GPIO_Init(QC_DP_PORT, QC_DP_PIN, GPIO_MODE_OUT_OD_LOW_FAST);
    GPIO_Init(QC_DM_PORT, QC_DM_PIN, GPIO_MODE_OUT_OD_LOW_FAST);
}

/* QC2.0握手 */
uint8_t QC2_Handshake(void)
{
    /* 1. 拉高DP,拉低DM */
    GPIO_WriteHigh(QC_DP_PORT, QC_DP_PIN);
    GPIO_WriteLow(QC_DM_PORT, QC_DM_PIN);
    Delay_Ms(1500);
    
    /* 2. 拉高DP和DM */
    GPIO_WriteHigh(QC_DP_PORT, QC_DP_PIN);
    GPIO_WriteHigh(QC_DM_PORT, QC_DM_PIN);
    Delay_Ms(50);
    
    /* 3. 检测充电器响应 */
    GPIO_Init(QC_DP_PORT, QC_DP_PIN, GPIO_MODE_IN_FL_NO_IT);
    GPIO_Init(QC_DM_PORT, QC_DM_PIN, GPIO_MODE_IN_FL_NO_IT);
    
    if (GPIO_ReadInputPin(QC_DP_PORT, QC_DP_PIN) == SET &&
        GPIO_ReadInputPin(QC_DM_PORT, QC_DM_PIN) == SET)
    {
        return 1;  // 握手成功
    }
    
    return 0;  // 握手失败
}

/* 设置QC2.0输出电压 */
void QC2_SetVoltage(QC2_Voltage volt)
{
    GPIO_Init(QC_DP_PORT, QC_DP_PIN, GPIO_MODE_OUT_OD_LOW_FAST);
    GPIO_Init(QC_DM_PORT, QC_DM_PIN, GPIO_MODE_OUT_OD_LOW_FAST);
    
    switch (volt)
    {
        case QC2_5V:
            GPIO_WriteLow(QC_DP_PORT, QC_DP_PIN);
            GPIO_WriteLow(QC_DM_PORT, QC_DM_PIN);
            break;
        case QC2_9V:
            GPIO_WriteHigh(QC_DP_PORT, QC_DP_PIN);
            GPIO_WriteLow(QC_DM_PORT, QC_DM_PIN);
            break;
        case QC2_12V:
            GPIO_WriteLow(QC_DP_PORT, QC_DP_PIN);
            GPIO_WriteHigh(QC_DM_PORT, QC_DM_PIN);
            break;
        case QC2_20V:
            GPIO_WriteHigh(QC_DP_PORT, QC_DP_PIN);
            GPIO_WriteHigh(QC_DM_PORT, QC_DM_PIN);
            break;
    }
    Delay_Ms(100);
}

/* QC3.0连续调压 */
void QC3_ContinuousVoltage(uint8_t step)
{
    GPIO_Init(QC_DP_PORT, QC_DP_PIN, GPIO_MODE_OUT_OD_LOW_FAST);
    GPIO_Init(QC_DM_PORT, QC_DM_PIN, GPIO_MODE_OUT_OD_LOW_FAST);
    
    if (step == QC3_STEP_200MV)
    {
        /* 200mV步进 */
        GPIO_WriteHigh(QC_DP_PORT, QC_DP_PIN);
        GPIO_WriteLow(QC_DM_PORT, QC_DM_PIN);
        Delay_Ms(1);
        GPIO_WriteLow(QC_DP_PORT, QC_DP_PIN);
        GPIO_WriteLow(QC_DM_PORT, QC_DM_PIN);
    }
    else if (step == QC3_STEP_20MV)
    {
        /* 20mV步进 */
        GPIO_WriteLow(QC_DP_PORT, QC_DP_PIN);
        GPIO_WriteHigh(QC_DM_PORT, QC_DM_PIN);
        Delay_Ms(1);
        GPIO_WriteLow(QC_DP_PORT, QC_DP_PIN);
        GPIO_WriteLow(QC_DM_PORT, QC_DM_PIN);
    }
}

/* 协议握手主函数 */
uint8_t Protocol_Handshake(ChargeInfo *info)
{
    /* 尝试QC2.0握手 */
    if (QC2_Handshake())
    {
        /* 根据输入电压选择输出 */
        if (info->input_voltage >= 9000)
        {
            QC2_SetVoltage(QC2_9V);
            info->target_voltage = 9000;
        }
        else if (info->input_voltage >= 12000)
        {
            QC2_SetVoltage(QC2_12V);
            info->target_voltage = 12000;
        }
        else
        {
            QC2_SetVoltage(QC2_5V);
            info->target_voltage = 5000;
        }
        
        info->protocol = PROTOCOL_QC2;
        return 1;
    }
    
    /* 尝试其他协议... */
    
    return 0;
}

3.4 放电控制(discharge.c)

/**
  * @file discharge.c
  * @brief 快放控制(电池测试/应急供电)
  */
#include "discharge.h"
#include "pwm.h"

/* 放电参数 */
#define DISCHARGE_CURRENT  3000    // 放电电流(mA)
#define DISCHARGE_CUTOFF   3000    // 放电截止电压(mV)
#define PWM_FREQ          20000    // PWM频率(Hz)

/* 放电控制结构体 */
DischargeInfo dis_info;

/* 初始化放电 */
void Discharge_Init(void)
{
    dis_info.state = DIS_IDLE;
    dis_info.target_current = DISCHARGE_CURRENT;
    dis_info.current_duty = 0;
    dis_info.load_enable = 0;
}

/* 检测放电请求 */
uint8_t Discharge_DetectRequest(void)
{
    /* 检测按键或通信命令 */
    if (GPIO_ReadInputPin(DISCHARGE_KEY_PORT, DISCHARGE_KEY_PIN) == RESET)
    {
        return 1;
    }
    return 0;
}

/* 放电控制 */
void Discharge_Control(DischargeInfo *info)
{
    uint16_t bat_current = Battery_GetCurrent();
    uint16_t bat_voltage = Battery_GetVoltage();
    
    /* 检查截止条件 */
    if (bat_voltage <= DISCHARGE_CUTOFF)
    {
        Discharge_Stop();
        return;
    }
    
    /* PI调节放电电流 */
    int16_t error = info->target_current - bat_current;
    info->current_duty += (error * 2) / 100;  // P=2
    
    /* 限制占空比 */
    if (info->current_duty > 90) info->current_duty = 90;
    if (info->current_duty < 10) info->current_duty = 10;
    
    /* 设置放电PWM */
    PWM_SetDuty(PWM_DIS, info->current_duty);
    
    /* 使能负载 */
    if (!info->load_enable)
    {
        GPIO_WriteHigh(LOAD_EN_PORT, LOAD_EN_PIN);
        info->load_enable = 1;
    }
    
    info->state = DIS_RUNNING;
}

/* 停止放电 */
void Discharge_Stop(void)
{
    PWM_SetDuty(PWM_DIS, 0);
    GPIO_WriteLow(LOAD_EN_PORT, LOAD_EN_PIN);
    dis_info.load_enable = 0;
    dis_info.state = DIS_IDLE;
}

3.5 保护功能(protect.c)

/**
  * @file protect.c
  * @brief 电池保护功能
  */
#include "protect.h"
#include "battery.h"

/* 保护阈值 */
#define OVER_VOLTAGE    4300    // 过压阈值(mV)
#define UNDER_VOLTAGE   2800    // 欠压阈值(mV)
#define OVER_CURRENT    3500    // 过流阈值(mA)
#define OVER_TEMP       65      // 过温阈值(℃)
#define UNDER_TEMP      -10     // 低温阈值(℃)

/* 保护状态 */
ProtectState protect_state = PROTECT_NORMAL;

/* 保护检测 */
void Protect_Check(BatteryInfo *bat, ChargeInfo *chg, DischargeInfo *dis)
{
    uint8_t fault = 0;
    
    /* 1. 电压保护 */
    if (bat->voltage > OVER_VOLTAGE)
    {
        fault |= FAULT_OVER_VOLTAGE;
    }
    if (bat->voltage < UNDER_VOLTAGE)
    {
        fault |= FAULT_UNDER_VOLTAGE;
    }
    
    /* 2. 电流保护 */
    if (bat->current > OVER_CURRENT)
    {
        fault |= FAULT_OVER_CURRENT;
    }
    
    /* 3. 温度保护 */
    if (bat->temperature > OVER_TEMP)
    {
        fault |= FAULT_OVER_TEMP;
    }
    if (bat->temperature < UNDER_TEMP)
    {
        fault |= FAULT_UNDER_TEMP;
    }
    
    /* 4. 短路保护 */
    if (bat->current > OVER_CURRENT * 2)
    {
        fault |= FAULT_SHORT_CIRCUIT;
    }
    
    /* 处理故障 */
    if (fault)
    {
        Protect_Execute(fault);
    }
}

/* 执行保护 */
void Protect_Execute(uint8_t fault)
{
    /* 立即切断充放电 */
    PWM_SetDuty(PWM_CHG, 0);
    PWM_SetDuty(PWM_DIS, 0);
    GPIO_WriteLow(LOAD_EN_PORT, LOAD_EN_PIN);
    
    /* 记录故障码 */
    protect_state.fault_code = fault;
    protect_state.state = PROTECT_ACTIVE;
    
    /* 报警指示 */
    for (uint8_t i = 0; i < 5; i++)
    {
        GPIO_WriteReverse(LED_FAULT_PORT, LED_FAULT_PIN);
        Delay_Ms(200);
    }
}

四、STM8配置(stm8s_conf.h)

/* STM8S配置头文件 */
#ifndef __STM8S_CONF_H
#define __STM8S_CONF_H

#include "stm8s.h"

/* 时钟配置 */
#define HSI_VALUE  16000000UL  // 内部16MHz RC
#define CPU_CLOCK  16000000UL  // CPU时钟16MHz

/* 外设使能 */
#define USE_ADC
#define USE_TIM1
#define USE_TIM2
#define USE_UART1
#define USE_GPIO

/* 中断优先级 */
#define ITC_PRIORITY_0  0  // 最高优先级
#define ITC_PRIORITY_1  1
#define ITC_PRIORITY_2  2
#define ITC_PRIORITY_3  3  // 最低优先级

#endif /* __STM8S_CONF_H */

五、编译与烧录

5.1 IAR工程配置

Project Options:
  - General Options → Target → Device: STM8S003F3
  - C/C++ Compiler → Preprocessor → Include directories: ./
  - Linker → Config → Linker configuration file: stm8s003f3.icf
  - Debugger → Setup → Driver: ST-LINK

5.2 编译优化

/* 编译器优化选项 */
#pragma optimize=speed  // 速度优化
#pragma vector=0xXX    // 中断向量

参考代码 基于stm8的快充快放程序 www.youwenfan.com/contentcnu/56320.html

六、测试与调试

6.1 测试项目

测试项 方法 预期结果
充电握手 接入QC充电器 协议识别成功,电压切换正常
恒流充电 监测电流 稳定在设定值±5%
恒压充电 监测电压 稳定在4.20V±0.05V
过流保护 短路输出 立即切断,恢复需重启
过温保护 加热电池 >65℃停止充放电

6.2 调试技巧

  1. 使用SWIM接口:ST-LINK/V2实时调试
  2. 串口打印:输出电压/电流/温度数据
  3. LED指示:不同闪烁模式表示状态
  4. 示波器监测:PWM波形、电压纹波

七、安全注意事项

重要安全提示

  1. 电池选型:必须使用带保护板的锂电池
  2. 散热设计:MOS管和电感需足够散热
  3. 绝缘处理:高压部分做好绝缘隔离
  4. 认证要求:量产需通过GB31241/UL2054认证
  5. 失效保护:加入硬件看门狗(如IMP706)

八、扩展功能

8.1 增加蓝牙控制

/* 蓝牙通信协议 */
void BLE_ProcessCommand(uint8_t *cmd)
{
    if (strcmp(cmd, "START_CHG") == 0)
    {
        sys_state = SYS_CHG_PROTOCOL;
    }
    else if (strcmp(cmd, "START_DIS") == 0)
    {
        sys_state = SYS_DISCHARGE;
    }
    else if (strncmp(cmd, "SET_CUR=", 8) == 0)
    {
        uint16_t cur = atoi(cmd+8);
        chg_info.target_current = cur;
    }
}

8.2 增加LCD显示

/* LCD显示充电状态 */
void LCD_DisplayStatus(void)
{
    LCD_Clear();
    LCD_ShowString(0, 0, "BAT:");
    LCD_ShowNumber(30, 0, bat_info.voltage/1000, 1);
    LCD_ShowString(50, 0, "V");
    
    LCD_ShowString(0, 1, "CUR:");
    LCD_ShowNumber(30, 1, bat_info.current, 4);
    LCD_ShowString(70, 1, "mA");
    
    LCD_ShowString(0, 2, "TEMP:");
    LCD_ShowNumber(40, 2, bat_info.temperature, 2);
    LCD_ShowString(70, 2, "C");
}

 

专注于matlab/simulink,电子电路,编程