270 lines
7.3 KiB
C
270 lines
7.3 KiB
C
/**
|
||
******************************************************************************
|
||
* @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_CH1(PA8)的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模式1:CNT<CCR时输出高电平
|
||
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; // 使能通道输出
|
||
TIM_OCInitStructure.TIM_Pulse = 0; // 初始占空比0(CCR值)
|
||
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);
|
||
}
|
||
|