标题:
海尔12位单片机写的移动电源程序
[打印本页]
作者:
zzmm5520
时间:
2016-5-16 11:19
标题:
海尔12位单片机写的移动电源程序
需要用海尔的单片机同学可以参考
0.png
(76.32 KB, 下载次数: 123)
下载附件
2016-5-16 17:55 上传
完整代码下载:
移动电源Demo程序.rar
(8.38 KB, 下载次数: 98)
2016-5-16 11:18 上传
点击文件名下载附件
海尔单片机
下载积分: 黑币 -5
/*
---------------------
电源--|VDD VSS|--地
PinCharge--|PA5/OSC1/KIN5 PA0/AIN0|--NC
PinChargeFull--|PA4/OSC2/KIN4 PA1/AIN1|--PinCurrent
PinHalt--|PA3/MRST/KIN3 PA2/AIN2|--PinBoostEN
PinLed1--|PB3/AIN7 PB0/AIN3|--PinSelMode
PinLed2--|PB2/AIN6 PB1/AIN4|--NC
PinLed3--|PA7/AIN5/KIN7 PA6|--PinKey
---------------------
*/
/*****************************************************************************
;* Title :
;*
;*
;*
;* Device : HR7P155-SOP14
;* OSC : 8Mhz( Internal 8Mhz )
;*
;* Compiler: IDE
;* Hardware:
;* Version : A00
;***************************************************************************/
/*********************************************
;* Include headfiles
;********************************************/
#include "Init.h"
/*********************************************
;* Private variables
;********************************************/
/**********************************************
;*
;* Function Name: main
;* Inputs: None
;* Returns: None
;* Description: the main process
;*
;**********************************************/
void main(void)
{
InitialMCU();
while(1)
{
CLRWDT();
RCEN = 1;
if(FlagSysClk1ms)
{
FlagSysClk1ms = 0;
KeyScan(); //按键扫描子程序
ADCurrentSample(); //电流采样处理子程序
}
if(FlagSysClk20ms)
{
FlagSysClk20ms = 0;
GetSysStatus(); //状态处理子程序
LowLoadCheck(); //轻负载、过流保护处理子程序
ControlCharge(); //充电控制子程序
}
if(FlagSysClk500ms)
{
FlagSysClk500ms = 0;
//for debug
//PowerBattaryQ = 2600; //blink
//PowerBattaryQ = 2700; //level1
//PowerBattaryQ = 2800; //level2
//PowerBattaryQ = 2850; //level3
//PowerBattaryQ = 3000; //level4
HandFlagProcess(); //功能模式处理子程序
DealDispData(); //显示数据处理子程序 必须放在电量级别判断之后
HaltProcess(); //休眠处理子程序
AdjustToBalance(); //电池电量级别平衡处理子程序
}
}
}
/**********************************************
;*
;* Function Name: interrupt service routine
;* Inputs: None
;* Returns: None
;* Description: the isr process
;*
;**********************************************/
void isr(void) interrupt
{
if (T8P2IE & T8P2IF)
{
T8P2IF = 0;
FlagSysClk1ms = 1;
CntSysClk20ms++;
//每20ms执行一次
if(CntSysClk20ms >= 20)
{
FlagSysClk20ms = 1;
CntSysClk20ms = 0;
CntSysClk500ms++;
if(CntSysClk500ms >= 25)
{
FlagSysClk500ms = 1;
CntSysClk500ms = 0;
}
}
}
if(KIE & KIF)
{
PABuf = PA; //必须要读一次电平才能清除KIF
KIF = 0;
}
}
/**********************************************
;*
;* Function Name: GetSysStatus routine
;* Inputs: None
;* Returns: None
;* Description: the GetSysStatus process
;*
;**********************************************/
#define CONST_NOCHARGE_CUR 6
void InitChargePWM(void)
{
T8P1P = 131; //周期132 * 1/8M * 2 = 33us
T8P1RL = 20; //初始占空比20 * 1/8M * 2 = 5us
T8P1C = 0x84; //PWM输出模式,使能T8P1
T8P1OC = 0x01; //选择PB0输出PWM
}
void GetSysStatus(void)
{
if(PinCharge)
{
CntDischargeShort = 0;
CntChargeShort++;
if(CntChargeShort >= COUNT_CHARGE_SHORT) //防止拔掉适配器后显示充满状态,保证PinCharge引脚变为低电平
{
CntChargeShort = 0;
if(!FlagChargeDisp)
{
//充电处理程序
FlagEnterBlink = 0;
FlagDispPower = 0;
FlagChargeDisp = 1;
FlagCharging = 1;
FlagChargeFull = 0;
InitChargePWM();
CntDispCharge = 0;
}
}
}
else
{
CntChargeShort = 0;
CntDischargeShort++;
if(CntDischargeShort >= COUNT_CHARGE_SHORT)
{
CntDischargeShort = 0;
if(!FlagDispPower)
{
FlagChargeDisp = 0;
FlagDispPower = 1;
FlagCharging = 0;
FlagChargeFull = 0;
}
}
}
//充电状态下,充电拔出判断
if(FlagCharging && (!FlagChargeFull))
{
if(ChargeCur < CONST_NOCHARGE_CUR)
{
CntNoCharge++;
if(CntNoCharge >= 20)//150)
{
CntNoCharge = 0;
//充电拔出处理
FlagCharging = 0;
ClosePinChargePWM();
CntNoLoad = 0;
//边充边放时,拔掉充电不能进休眠
if(!FlagDischarge)
{
Sleep();
}
}
}
else
{
CntNoCharge = 0;
}
}
}
/**********************************************
;*
;* Function Name: LowLoadCheck routine
;* Inputs: None
;* Returns: None
;* Description: the LowLoadCheck process
;*
;**********************************************/
void LowLoadCheck(void)
{
//放电模式下过流、轻负载判断
if((LoadCurrentVol >= LOAD_OVER_CUR_VALUE))
{
CntShort++;
if(CntShort >= COUNT_SHORT)
{
CntShort = 0;
//防止再次按键不能打开升压
CntADSample = 0;
ADCurSum = 0;
LoadCurrentVol = 0;
PinBoostEN = 0;
FlagDischarge = 0;
}
}
else if(LoadCurrentVol >= NO_LOAD_VALUE)
{
CntShort = 0;
CntNoLoad = 0;
CntHaveLoad++;
if(CntHaveLoad >= COUNT_HAVE_LOAD)
{
CntHaveLoad = 0;
CntDispDelay = 0;
FlagLoad = 1;
}
}
else
{
CntShort = 0;
CntHaveLoad = 0;
CntNoLoad++;
//轻负载时去抖
if(CntNoLoad >= COUNT_LIGHT_LOAD)
{
FlagLoad = 0;
}
//无负载10S关闭升压输出,并休眠
if(CntNoLoad >= COUNT_NO_LOAD)
{
CntNoLoad = 0;
if(!FlagCharging)
{
Sleep();
}
}
}
}
/**********************************************
;*
;* Function Name: DisplaySub routine
;* Inputs: None
;* Returns: None
;* Description: the DisplaySub process
;*
;* 0 //放电模式(有负载)
;* 1 //放电无负载、充电拔出显示处理
;* 2 //充电跑马灯显示处理
;* 3 //充电充满显示
;**********************************************/
void DisplaySub(u8 uMode)
{
//放电有负载、充电显示处理
if(uMode == 1)
{
//充电充满显示
if(FlagChargeFull)
{
SetPinLed1();
SetPinLed2();
SetPinLed3();
SetPinLed4();
}
else
{
switch(PreLedLevel)
{
case 1:
CntDispCharge++;
switch(CntDispCharge)
{
case 1:
SetPinLed1();
break;
case 2:
SetPinLed2();
break;
case 3:
SetPinLed3();
break;
case 4:
SetPinLed4();
break;
case 5:
CntDispCharge = 0;
ClrAllLed();
break;
default:
break;
}
break;
case 2:
SetPinLed1();
CntDispCharge++;
switch(CntDispCharge)
{
case 1:
SetPinLed2();
break;
case 2:
SetPinLed3();
break;
case 3:
SetPinLed4();
break;
case 4:
CntDispCharge = 0;
ClrPinLed2();
ClrPinLed3();
ClrPinLed4();
break;
default:
break;
}
break;
case 3:
SetPinLed1();
SetPinLed2();
CntDispCharge++;
switch(CntDispCharge)
{
case 1:
SetPinLed3();
break;
case 2:
SetPinLed4();
break;
case 3:
CntDispCharge = 0;
ClrPinLed3();
ClrPinLed4();
break;
default:
break;
}
break;
case 4:
SetPinLed1();
SetPinLed2();
SetPinLed3();
CPLPinLed4();
break;
default:
PreLedLevel = NowLedLevel;
break;
}
}
}
//放电模式(有负载或无负载)
else if(uMode == 0)
{
if((FlagDischarge || (!FlagLoad)) && FlagEnterBlink)
{
CPLPinLed1();
ClrPinLed2();
ClrPinLed3();
ClrPinLed4();
}
else
{
switch(PreLedLevel)
{
case 1:
SetPinLed1();
ClrPinLed2();
ClrPinLed3();
ClrPinLed4();
break;
case 2:
SetPinLed1();
SetPinLed2();
ClrPinLed3();
ClrPinLed4();
break;
case 3:
SetPinLed1();
SetPinLed2();
SetPinLed3();
ClrPinLed4();
break;
case 4:
SetPinLed1();
SetPinLed2();
SetPinLed3();
SetPinLed4();
break;
default:
PreLedLevel = NowLedLevel;
break;
}
}
}
}
/**********************************************
;*
;* Function Name: DealDispData routine
;* Inputs: None
;* Returns: None
;* Description: the DealDispData process
;*
;* 0 //放电模式(有负载或无负载)
;* 1 //充电跑马灯显示处理
;**********************************************/
void DealDispData(void)
{
if(FlagShortLoad)
{
CntFlashErr++;
if(CntFlashErr >= 6)
{
CntFlashErr = 0;
FlagShortLoad = 0;
//短路3S后进入休眠
Sleep();
}
else
{
CPLPinLed1();
CPLPinLed2();
CPLPinLed3();
CPLPinLed4();
}
}
//边充边放优先显示充电
else if(FlagCharging)
{
DisplaySub(1);
}
else if(FlagDischarge && (FlagLoad || FlagDispDelay))
{
DisplaySub(0); //放电有负载或无负载显示处理
}
else
{
ClrAllLed(); //关闭显示输出
}
}
/**********************************************
;*
;* Function Name: KeyScan routine
;* Inputs: None
;* Returns: None
;* Description: the KeyScan process
;*
;**********************************************/
void FuncDischarge(void)
{
FlagDischarge = 1;
PinBoostEN = 1;
FlagDispDelay = 1;
CntDispDelay = 0;
CntNoLoad = 0;
}
/**********************************************
;*
;* Function Name: KeyScan routine
;* Inputs: None
;* Returns: None
;* Description: the KeyScan process
;*
;**********************************************/
void KeyScan(void)
{
if(!PinKey)
{
CntPressOn++;
if(CntPressOn >= KEY_SHORT)
{
CntPressOn = 0;
if(!FlagKeyPress)
{
FlagKeyPress = 1;
//单击按键处理程序
FuncDischarge();
}
}
}
else
{
CntPressOn = 0;
FlagKeyPress = 0;
}
}
/**********************************************
;*
;* Function Name: ControlCharge routine
;* Inputs: None
;* Returns: None
;* Description: the ControlCharge process
;*
;**********************************************/
#define CONST_CHARGE_0A95 139//132
#define CONST_CHARGE_1A05 154//132
#define CONST_CHARGE_0A15 22//32
#define MAX_CHARGE_PWM 100
#define MIN_CHARGE_PWM 4
//充电恒流控制
void AdjustChargePWM(void)
{
//电流增加
if(ChargeCur < CONST_CHARGE_0A95)
{
if(T8P1RL < MAX_CHARGE_PWM)
{
T8P1RL++;
}
}
//电流减小
else if(ChargeCur > CONST_CHARGE_1A05)
{
if(T8P1RL > MIN_CHARGE_PWM)
{
T8P1RL--;
}
}
}
void ControlCharge(void)
{
if(FlagCharging && (!FlagChargeFull))
{
if(PowerBattaryQ < CONST_BAT_4V15)
{
AdjustChargePWM();
}
else if((PowerBattaryQ >= CONST_BAT_4V15))
{
//电压增加
if(PowerBattaryQ < CONST_BAT_4V10)
{
if(T8P1RL < MAX_CHARGE_PWM)
{
T8P1RL++;
}
}
//电压减小
else if(PowerBattaryQ > CONST_BAT_4V20)
{
if(T8P1RL > MIN_CHARGE_PWM)
{
T8P1RL--;
}
}
//连续5S延时满足条件则认为已充满
if(ChargeCur < CONST_CHARGE_0A15)
{
CntFull++;
if(CntFull >= 250)
{
CntFull = 0;
FlagChargeFull = 1;
ClosePinChargePWM();
}
}
else
{
CntFull = 0;
}
}
}
}
/**********************************************
;*
;* Function Name: BatLevelCheck routine
;* Inputs: None
;* Returns: None
;* Description: the BatLevelCheck process
;*
;**********************************************/
void BatLevelCheck(void)
{
if(!FlagCharging)
{
//放电级别判定
if(PowerBattaryQ > DISCHARGE_VOL_LEVEL3)
{
NowLedLevel = 4;
}
else if(PowerBattaryQ > DISCHARGE_VOL_LEVEL2)
{
NowLedLevel = 3;
}
else if(PowerBattaryQ > DISCHARGE_VOL_LEVEL1)
{
NowLedLevel = 2;
}
else if(PowerBattaryQ > LED_BLINK_VOL)
{
NowLedLevel = 1;
}
}
//充电级别判定
else
{
if(PowerBattaryQ > CHARGE_VOL_LEVEL3)
{
NowLedLevel = 4;
}
else if(PowerBattaryQ > CHARGE_VOL_LEVEL2)
{
NowLedLevel = 3;
}
else if(PowerBattaryQ > CHARGE_VOL_LEVEL1)
{
NowLedLevel = 2;
}
else if(PowerBattaryQ > LED_BLINK_VOL)
{
NowLedLevel = 1;
}
}
//初始上电时,将当前电量级别赋给上次电量级别
if(FlagNowToPre)
{
FlagNowToPre = 0;
PreLedLevel = NowLedLevel;
}
}
/**********************************************
;*
;* Function Name: HandFlagProcess routine
;* Inputs: None
;* Returns: None
;* Description: the HandFlagProcess process
;*
;**********************************************/
void HandFlagProcess(void)
{
if(FlagDispDelay && (!FlagLoad))
{
CntDispDelay++;
if(CntDispDelay >= 6) //显示电量时间为3S
{
CntDispDelay = 0;
FlagDispDelay = 0;
}
}
//电池电量检测
BatLevelCheck();
// 电池电量盲区检测 放电才判断
if((PowerBattaryQ < LED_BLINK_VOL) && (!FlagCharging))
{
FlagEnterBlink = 1;
NowLedLevel = 1;
}
}
/**********************************************
;*
;* Function Name: AdjustToBalance routine
;* Inputs: None
;* Returns: None
;* Description: the AdjustToBalance process
;*
;**********************************************/
void AdjustToBalance(void)
{
if(PreLedLevel > NowLedLevel)
{
if(FlagLoad)
{
CntDelayLevel1++;
if(CntDelayLevel1 >= COUNT_DELAY_LEVEL)
{
CntDelayLevel1 = 0;
PreLedLevel -= 1;
}
}
}
else if(PreLedLevel < NowLedLevel)
{
if(FlagCharging)
{
CntDelayLevel2++;
if(CntDelayLevel2 >= COUNT_DELAY_LEVEL)
{
CntDelayLevel2 = 0;
PreLedLevel += 1;
CntDispCharge = 0; //跑马灯显示计数清零
}
}
}
else
{
CntDelayLevel1 = 0;
CntDelayLevel2 = 0;
}
}
/**********************************************
;*
;* Function Name: HaltProcess routine
;* Inputs: None
;* Returns: None
;* Description: the HaltProcess process
;*
;**********************************************/
void HaltProcess(void)
{
//当电池电量小于关机电量时休眠
if(!FlagCharging)
{
if(PowerBattaryQ < BAT_OFF_VOL)
{
Sleep();
}
}
}
/**********************************************
;*
;* Function Name: GetADC routine
;* Inputs: u8 channel
;* Returns: u16 m_ADCValue
;* Description: the GetADC process
;*
;**********************************************/
u16 GetADC(u8 channel)
{
//ADCCH = 0xB8;
ADCCL = channel;
ADTRG = 1;
while (ADTRG)
{
;
}
m_ADCValue = (ADCRH << 8) + ADCRL;
return(m_ADCValue);
}
/**********************************************
;*
;* Function Name: ADCurrentSample routine
;* Inputs: None
;* Returns: None
;* Description: the ADCurrentSample process
;*
;**********************************************/
void ADCurrentSample(void)
{
CntADSample++;
if(CntADSample != 17)
{
BakLoadCur = GetADC(AD_CHANNEL_1);
ADCurSum += BakLoadCur;
ADChargeCurSum += GetADC(AD_CHANNEL_4);
if(FlagCharging)
{
if(BakLoadCur > m_ADCValue)
{
BakLoadCur = (BakLoadCur - m_ADCValue);
}
}
//短路1ms保护
if(BakLoadCur >= LOAD_SHORT_VALUE)
{
PinBoostEN = 0;
ClrAllLed();
FlagShortLoad = 1;
}
GetADC(AD_CHANNEL_0);
PABuf = (m_ADCValue >> 4);
ADBatterySum += PABuf;
//ADBatterySum += GetADC(AD_CHANNEL_0);
}
else
{
LoadCurrentVol = (ADCurSum >> 4);
ChargeCur = (ADChargeCurSum >> 4);
PowerBattaryQ = (ADBatterySum >> 4);
//充电时放电电流处理
if(FlagCharging)
{
if(LoadCurrentVol >= ChargeCur)
{
LoadCurrentVol = (LoadCurrentVol - ChargeCur);
}
}
CntADSample = 0;
ADCurSum = 0;
ADChargeCurSum = 0;
ADBatterySum = 0;
}
}
/**********************************************
;*
;* Function Name: Sleep routine
;* Inputs: None
;* Returns: None
;* Description: the Sleep process
;*
;**********************************************/
void Sleep(void)
{
if(FlagChargeFull) return;
ClrAllLed();
PinBoostEN = 0;
FlagDischarge = 0;
CntNoLoad = 0;
while(!SW_HS);
RCEN = 0;
ADEN = 0;//关闭ADC使能
IDLE();
while(!SW_HS); //等待高速时钟稳定
RCEN = 1; //打开看门狗
CLRWDT();
}
复制代码
作者:
billy_jhgg
时间:
2018-5-10 10:40
感谢楼主分享,正需要呢,有原理图就更好了
作者:
啊啊啊手术室
时间:
2018-7-7 23:42
大神,,逻辑非常清晰,
作者:
符小明
时间:
2018-7-13 14:55
大神学习了
作者:
符小明
时间:
2018-10-19 15:04
谢谢
作者:
Nicholas666
时间:
2018-10-30 16:32
感谢!看看有没有参考价值!
作者:
luoj0902
时间:
2019-3-25 22:37
感谢!看看有没有参考价值!
作者:
紫色的云
时间:
2019-5-17 09:44
有没有参考原理图看看
作者:
zhouyidong
时间:
2019-6-16 18:28
求原理图
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1