Files
2026-08-25 17:30:40 +08:00

270 lines
7.3 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
******************************************************************************
* @file pwm.c
* @author
* @version
* @date
* @brief
******************************************************************************
* @attention
*
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include "global.h"
//GPIOA
#define PIN_CHG_LIMIT_PON GPIO_Pin_8 //限流 电源控制管脚
//GPIOB
#define PIN_CHG_LIMIT_PWM GPIO_Pin_9 //限流 电流值控制
#define BIAS_VOLTAGE (200 * bmsMem.ucCellNum/16) //基准偏差电压值,单位1mV
#define BASE_VOLTAGE (60000 * bmsMem.ucCellNum/16) //基准电压值,单位1mV
#define BASE_CURRENT 10000 //基准/目标电流值10A,单位1mA
#define MAX_DUTY 99.00f //最大占空比(百分比)
#define MIN_DUTY 50.00f //最小占空比(百分比)
#define PWM_ARR 3599 //定时器自动重装值(对应0~100%占空比)
#define PWM_PSC 0 //预分频系数(PWM频率=72M/(0+1)/(3599+1) = 20kHz
uint8_t curLimit_ctrlFlag; //执行限流开/关的标志 0:关限流 1:开限流
float base_duty; //初始电流值偏小最好,对应假设充电器电压是最大值60V
float old_duty; //有效的上一次调整的占空比
float duty_cycle; //实时基准占空比
//开限流
void CHG_LIMIT_On(void)
{
if(curLimit_ctrlFlag != 1)
{
curLimit_ctrlFlag = 1;
delay_ms(10); //关充电MOS后,再延时开限流
//计算初始占空比
base_duty = (float)(bmsMem.packVoltage + BIAS_VOLTAGE) / BASE_VOLTAGE * 100;
base_duty = (int)(base_duty * 100 + 0.5) / 100.0f;
if(base_duty < MIN_DUTY)
{
base_duty = MIN_DUTY;
}
else if(base_duty > MAX_DUTY)
{
base_duty = MAX_DUTY;
}
//限流功能开启
GPIO_SetBits(GPIOA, PIN_CHG_LIMIT_PON);
//PWM占空比为默认值
duty_cycle = base_duty;
old_duty = duty_cycle;
PWM_Set_Duty_Percent(duty_cycle);
}
}
//关限流
void CHG_LIMIT_Off(void)
{
if(curLimit_ctrlFlag != 0)
{
curLimit_ctrlFlag = 0;
//限流功能关闭
GPIO_ResetBits(GPIOA, PIN_CHG_LIMIT_PON);
//PWM占空比为0%
duty_cycle = 0.00f;
old_duty = duty_cycle;
PWM_Set_Duty_Percent(duty_cycle);
delay_ms(10); //关限流后,延时开充电MOS
}
}
//限流控制脚和PWM脚的初始化
void CHG_LIMIT_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
//限流充电控制
GPIO_InitStructure.GPIO_Pin = PIN_CHG_LIMIT_PON;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_ResetBits(GPIOA, PIN_CHG_LIMIT_PON); //限流控制脚,默认关闭状态
//限流PWM波初始化
TIM4_PWM_Init(PWM_ARR, PWM_PSC);
}
/**************************************************************************
** 初始化TIM4_CH1PA8)的PWM输出
** arr: 定时器自动重装值
** psc: 定时器预分频系数
***************************************************************************/
void TIM4_PWM_Init(uint16_t arr, uint16_t psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
// 开启外设时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); // TIM4+GPIOB时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOB, ENABLE); // 复用功能时钟(必要)
// 配置PB9为复用推挽输出(PWM必须用复用模式)
GPIO_InitStructure.GPIO_Pin = PIN_CHG_LIMIT_PWM;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// 配置TIM4时基参数
TIM_TimeBaseStructure.TIM_Period = arr; // 自动重装值
TIM_TimeBaseStructure.TIM_Prescaler = psc; // 预分频系数
TIM_TimeBaseStructure.TIM_ClockDivision = 0; // 时钟分割(无分频)
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
// 配置TIM4_CH1的PWM模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; // PWM模式1CNT<CCR时输出高电平
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; // 使能通道输出
TIM_OCInitStructure.TIM_Pulse = 0; // 初始占空比0CCR值)
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; // 有效电平为高
TIM_OC4Init(TIM4, &TIM_OCInitStructure); // 初始化通道4
// 使能预装载寄存器(保证参数修改生效)
TIM_OC4PreloadConfig(TIM4, TIM_OCPreload_Enable); // 通道4预装载使能
TIM_ARRPreloadConfig(TIM4, ENABLE); // TIM4自动重装预装载使能
// 开启主输出(否则无PWM波形)
TIM_CtrlPWMOutputs(TIM4, ENABLE);
// 启动TIM4
TIM_Cmd(TIM4, ENABLE);
}
/*************************************************************************************************
* 函数名: PWM_Set_Duty_Percent
* 参 数: 无
* 返回值: 无
* 描 述:
*************************************************************************************************/
void PWM_Set_Duty_Percent(float duty_per)
{
uint16_t ccr_val;
//限制百分比范围
if (duty_per < 0.00f) duty_per = 0.00f;
if (duty_per > 100.00f) duty_per = 100.00f;
//转换为定时器CCR值(四舍五入,提升精度)
ccr_val = (u16)(duty_per / 100.00f * PWM_ARR + 0.50f);
//设置CCR值
TIM_SetCompare4(TIM4, ccr_val);
}
/*************************************************************************************************
* 函数名: CHG_LIMIT_PWM_Adjust
* 参 数: 无
* 返回值: 无
* 描 述: pwm限流,根据电流来计算占空比,53.4V 10A时占空比为93.0
*************************************************************************************************/
void CHG_LIMIT_PWM_Adjust(void)
{
int16_t cur_diff = bmsMem.packCurrent - BASE_CURRENT;
//根据电流差值调整占空比,变化越大电流波动越大
if(cur_diff >= 9000)
{
//电流超过目标9A以上,快速减小占空比(步长5.00,因为大电流有风险)
duty_cycle -= 5.00f;
}
else if(cur_diff >= 5000)
{
//电流超过目标5A以上,快速减小占空比(步长1.50,因为大电流有风险)
duty_cycle -= 1.50f;
}
else if(cur_diff >= 2000)
{
//电流超过目标2A以上,中速减小占空比(步长0.30)
duty_cycle -= 0.30f;
}
else if(cur_diff >= 1000)
{
//电流超过目标1A以上,中速减小占空比(步长0.20)
duty_cycle -= 0.20f;
}
else if(cur_diff >= 500)
{
//电流超过目标0.5A以上,慢速减小占空比(步长0.05)
duty_cycle -= 0.05f;
}
else if(cur_diff >= 100)
{
//电流超过目标0.5A以上,慢速减小占空比(步长0.01)
duty_cycle -= 0.01f;
}
else if(cur_diff <= -9000)
{
//电流低于目标9A以上,快速增大占空比(步长2.00)
duty_cycle += 2.00f;
}
else if(cur_diff <= -5000)
{
//电流低于目标5A以上,快速增大占空比(步长1.00)
duty_cycle += 1.00f;
}
else if(cur_diff <= -2000)
{
//电流低于目标3A以上,中速增大占空比(步长0.30)
duty_cycle += 0.30f;
}
else if(cur_diff <= -1000)
{
//电流低于目标1A以上,中速增大占空比(步长0.20)
duty_cycle += 0.20f;
}
else if(cur_diff <= -500)
{
//电流低于目标0.5A以上,慢速增大占空比(步长0.05)
duty_cycle += 0.05f;
}
else if(cur_diff <= -100)
{
//电流低于目标0.5A以上,慢速增大占空比(步长0.01)
duty_cycle += 0.01f;
}
else
{
//电流差在±500mA(0.5A)以内,占空比保持不变
duty_cycle = old_duty;
}
//限制占空比范围
if(duty_cycle < MIN_DUTY)
{
duty_cycle = MIN_DUTY;
}
else if(duty_cycle > MAX_DUTY)
{
duty_cycle = MAX_DUTY;
}
old_duty = duty_cycle;
PWM_Set_Duty_Percent(duty_cycle);
}