项目场景:
项目场景:适用于所有带充电检测的电子产品,USB充电识别
USB充电接入时判断一次电池电压是否为满电
void Charge_Detect(void)//充电检测
{
if (Charge_Flag != Read_Charge_IO())//USB接入时会读取一次IO 口,每次接入,移除会进入一次
{
Standby_Flag = 0;//待机标志
if (Charge_IoChange_Flag)
{
Charge_IoChange_Flag = 0;
ChargeFull_Flag = 0;//充满标志
ChargeFull_ChangeFlag = 0;
#ifdef Use_NearFull_Time
NearFull_Cnt = 0;//快充满计数清零
#endif
#ifdef Use_ChargeFullCnt
ChargeFull_Cnt = 0;//充满计数清零
#endif
if (Charge_Flag)//判断是否有充电标志
{
Charge_Flag = 0;//有标志清零
Set_Prompt(Prompt_Usb_Remove);//提示USB移除
}
else
{
Charge_Flag = 1;
#ifdef Use_ChargeManage //带有充电关断
Bat_Single_Sample();//采集电池电压
if (Sample_Val > BatFull_Sill)//判断电池电压是否大于预设电压值
{
Charge_Dis();//充电关闭
SysDelay_x10ms(2);//延时20MS用于采集电压值
Bat_Single_Sample();//采集电池电压
Charge_En();//打开充电使能
if (Sample_Val > BatFull_Sill)//再次判断电池电压是否大于预设电压值
{
ChargeFull_Flag = 1;//充满标志置1
ChargeFull_Cnt = ChargeFull_Time-(uint16_t)(3ul*1000/160); //充满计数调整为3s //3s;
// Set_Prompt(Prompt_ChargeFull);
}
}
else
Set_Prompt(Prompt_Usb_JoinUp); //提示USB已经接入
#else //没有充电关断功能
Bat_Single_Sample();//采集电压
if (Sample_Val > BatFull_Sill)//判断是否大于预设电压值
{
Bat_Single_Sample();//再次采集电压
if (Sample_Val > BatFull_Sill)//再次判断是否大于预设电压值
{
ChargeFull_Flag = 1;//充满标志置1
ChargeFull_Cnt = ChargeFull_Time-(uint16_t)(3ul*1000/160); //充满计数调整为3s //3s;
}
}
else
Set_Prompt(Prompt_Usb_JoinUp); //提示USB已经接入
#endif
}
}
else
{
Charge_IoChange_Flag = 1;//用于延时
}
}
else
{
Charge_IoChange_Flag = 0;
}
if (Charge_Flag && !ChargeFull_Flag)//有充电标志但是还没充满的情况下可以进入下面函数
{
#ifdef Use_ChargeFull_IO //有充满IO口可以检测
if (Read_ChargeFull_IO())//读取充满IO口是否达到
{
if (ChargeFull_IoChange_Flag)
{
ChargeFull_IoChange_Flag = 0;
if (Read_Charge_IO())//还在充电
{
ChargeFull_Flag = 1;//充满标志置1
Set_Prompt(Prompt_ChargeFull);//提示充满了
}
}
else
{
Bat_Single_Sample();//采集电压
if (Sample_Val > BatFull_Sill - VDD_Vol(100))//判断是否达到预设电压
ChargeFull_IoChange_Flag = 1;//达到预设电压
}
}
else
{
ChargeFull_IoChange_Flag = 0;
}
#endif
#ifdef Use_NearFull_Time//用于没有充电关断的场景下使用,假如说客户要求4.08以上为满电,单片机有时候会有采集误差,让单片机识别到电压为4.05V时,通过调用此延时 来继续显示充电,只要满足时间条件,才会提示对应的提示
if (NearFull_Cnt)//快充满计数还在递减
{
NearFull_Cnt--;
if (NearFull_Cnt == 0)//快充满计数为0后进入下面执行
{
ChargeFull_Flag = 1;//充满标志
/******************************/
LedBreathe_Flag = 0;//停止呼吸
Led_Val = 0;//LED清零
Led_Cnt = 0;
Led_Times = 0;
/*充电呼吸,充满后常亮需要把相关标志为清除,否则会导致灯光异常*/
//Set_Prompt(Prompt_ChargeFull);//提示充满
}
}
#endif
}
#ifdef Use_ChargeFullCnt //充满计数
if (ChargeFull_Flag)//已经充满了
{
ChargeFull_Cnt++;//计数递增
if (ChargeFull_Cnt > ChargeFull_Time)//递增到指定时间后
{
ChargeFull_Cnt = ChargeFull_Time;//计数不在递增
}
}
else
{
ChargeFull_Cnt = 0;
}
#endif
}
电压分档
//不同档位对应的LED灯
#define BatLev0_Led Common0_Led //一档对应的第一颗灯
#define BatLev1_Led (Common1_Led) //二档对应的第二颗灯
#define BatLev2_Led (Common2_Led) //三档对应的第三颗灯
#define BatChange_Sill VDD_Vol(30) //充电电压阈值
#define BatSill_ChargeComp VDD_Vol(30) //充电浮高阈值
#define BatLow_Sill VDD_Vol((3100-0)) //低电电压-设备最低的工作电压
#define Bat0_Sill VDD_Vol((3300-0)) //一档电压
#define Bat1_Sill VDD_Vol((3750-0)) //二档电压
#define BatFull_Sill VDD_Vol((4100-0)) //充满电压
void VoltageToLevel_Convert(void)//电压转换档位
{
if (Sample_Val < BatLow_Sill)//小于低电电压值
{
LowBat_Flag = 1;//低电标志
BatVot_Level = BatLev0_Led;//电压档位设置为最低档位
}
else if (LowBat_Flag)
{
if (Sample_Val > BatLow_Sill + BatChange_Sill + VDD_Vol(30))//大于低电压值
{
LowBat_Flag = 0;//清除低电标志
}
}
else
{
switch (BatVot_Level)//根据档位判断
{
case BatLev0_Led://一档
if (Sample_Val > Bat0_Sill + BatChange_Sill)//大于一档电压
{
if (BatChange_Flag)
{
BatChange_Flag = 0;
BatVot_Level = BatLev1_Led;//电压档位设置为二挡
}
else
BatChange_Flag = 1;
}
else
BatChange_Flag = 0;
break;
case BatLev1_Led://二档
if (Sample_Val > Bat1_Sill + BatChange_Sill)//大于二挡电压
{
if (BatChange_Flag)
{
BatChange_Flag = 0;
BatVot_Level = BatLev2_Led;//电压档位设置为三挡
}
else
BatChange_Flag = 1;
}
else if (Sample_Val < Bat0_Sill - BatChange_Sill)//小于一档电压
{
if (BatChange_Flag)
{
BatChange_Flag = 0;
BatVot_Level = BatLev0_Led;//电压档位设置为一档
}
else
BatChange_Flag = 1;
}
else
BatChange_Flag = 0;
break;
case BatLev2_Led://一档
if (Sample_Val < Bat1_Sill - BatChange_Sill)//小于二挡电压
{
if (BatChange_Flag)
{
BatChange_Flag = 0;
BatVot_Level = BatLev1_Led;//电压档位设置为二挡
}
else
BatChange_Flag = 1;
}
else
BatChange_Flag = 0;
break;
default:
break;
}
}
}
void BatteryInit_Detect(void)//电池电压初始化检测
{
Bat_Single_Sample();//采集电压
if (Sample_Val < BatLow_Sill)//判断是否低电
{
LowBat_Flag = 1;
BatVot_Level = BatLev0_Led;
}
else
{
if (Sample_Val > Bat1_Sill)//大于二挡
BatVot_Level = BatLev2_Led;//电压档位设置为三挡
else if (Sample_Val > Bat0_Sill)//大于一档
BatVot_Level = BatLev1_Led;//电压档位设置为二挡
else
BatVot_Level = BatLev0_Led;//电压档位设置为一挡
}
}
电压运行时检测
void BatteryRun_Detect(void)
{
Bat_Single_Sample();//采集电压
#ifdef Use_Charge
if (Charge_Flag)//有充电标志
{
if (!ChargeFull_Flag)//充满电
{
/* #ifdef Use_NearFull_Time
if (!NearFull_Cnt)
{
if (Sample_Val > BatFull_Sill - VDD_Vol(100))
NearFull_Cnt = NearToFull_Time;
}
#endif */
#ifdef Use_ChargeManage //带有开关控制功能
if (Sample_Val > BatFull_Sill)//判断电压是否大于预设值
{
Charge_Dis();//关闭充电
SysDelay_x10ms(2);
Bat_Single_Sample();//采集电压
Charge_En();//打开充电
if (Sample_Val > BatFull_Sill)//再次判断电压
{
if (ChargeFull_ChangeFlag)
{
ChargeFull_ChangeFlag = 0;
ChargeFull_Flag = 1;//满电标志
// Set_Prompt(Prompt_ChargeFull);
}
else
ChargeFull_ChangeFlag = 1;
}
else
{
ChargeFull_ChangeFlag = 0;
}
Sample_Val += BatSill_ChargeComp; //加上充电浮高,后面会减去,实际项目实际调整
}
#else //没有充电关断控制
if (Sample_Val > BatFull_Sill)//判断电压是否大于预设值
{
if (ChargeFull_ChangeFlag)
{
ChargeFull_ChangeFlag = 0;
#ifdef Use_NearFull_Time
if (!NearFull_Cnt)//NearFull_Cnt==0的时候进入
{
if (Sample_Val > BatFull_Sill - VDD_Vol(100))//判断电压是否大于预设值
NearFull_Cnt = NearToFull_Time;//达到预设值,开启充满倒计时
}
#endif
//ChargeFull_Flag = 1;
//Set_Prompt(Prompt_ChargeFull);
}
else
ChargeFull_ChangeFlag = 1;
}
else
{
ChargeFull_ChangeFlag = 0;
}
#endif
}
#if (1)
else
{
if (Sample_Val < BatFull_Sill - VDD_Vol(150))//小于满电阈值
{
ChargeFull_Flag = 0;//充满标志清零
ChargeFull_ChangeFlag = 0;
#ifdef Use_NearFull_Time
NearFull_Cnt = 0;//快充满计数清零
#endif
}
}
#endif
Sample_Val -= BatSill_ChargeComp; //减去浮高
}
#endif
VoltageToLevel_Convert();//根据电压区分档位
}