?? ___poweru.c
字號:
/*
FILENAME : MAIN.C
AUTHOR : Direction
PURPOSE : 20110920后備電池方案9-HT-深飛
REVISION : X01 09/21/2011 First issue
*/
#include "HT46R064.h"
#define TRUE 1
#define FALSE 0
#define CHARGE 0
#define DISCHARGE 1
#define NO_CHARGE_DISCHARGE 2
#define TURN_ON 1
#define TURN_OFF 0
#define LED1PORT _pb0
#define LED2PORT _pb1
#define LED3PORT _pb2
#define LED4PORT _pb3
#define LED5PORT _pb4
#define BUTTON1PORT _pa5
#define BUTTON1_STATUS_PRESSED 0
#define BUTTON1_STATUS_NOPRESSED 1
#define LED5_ON_DELAY_TIME 20
#define SLEEP_DELAY_TIME 30
#define CHARGER_PLUGGED (_pa2==1)
#define CHARGER_UNPLUGGED (_pa2==0)
#define CHARGE_FULL (_pa3==1)
#define CHARGE_UNFULL (_pa3==0)
unsigned char Counter_10ms_background,
Counter_100ms_background,
Counter_1second_background,
Counter_EnterSleepCounterDown,
Counter_Button1PressedCounter,
Counter_100ms_counter,
Timer0_temp_data,
Counter_8ms_counter,
Previous_Level_Charge,
Previous_Level_DisCharge,
Blink_LED_Number;
bit LED5PORT_Data_SHADE,
LED5_Update_flag,
Previous_State,
Blink_state,
Charge_Full_flag;
unsigned short battery_voltage,tempinta,WDT_Over_Counter;
unsigned long templonga;
unsigned short ADC_GetBatteryData()
{
_start=0;
_start=1;
_start=0;
while(_eocb==1)
{
#asm
clr wdt
#endasm
}
_start=0;
_start=1;
_start=0;
while(_eocb==1)
{
#asm
clr wdt
#endasm
}
tempinta=_adrh;
tempinta*=16;
tempinta+=_adrl/16;
//計算真實的MCU的電源電壓,以毫伏為單位
templonga=0x9c4000; //2500*4096=0x9c4000,由于編譯器的原因,此處不能寫成2500*4096,而要直接寫成0x9c4000
templonga/=tempinta;
battery_voltage=templonga;
return (battery_voltage);
}
unsigned char just_discharge()
{
battery_voltage=ADC_GetBatteryData();
_acs0=1; //選擇ADC通道1
_start=0;
_start=1;
_start=0;
while(_eocb==1)
{
#asm
clr wdt
#endasm
}
_start=0;
_start=1;
_start=0;
while(_eocb==1)
{
#asm
clr wdt
#endasm
}
tempinta=_adrh;
tempinta*=16;
tempinta+=_adrl/16;
//計算真實的AN1的電壓,以毫伏為單位
templonga=battery_voltage;
templonga*=tempinta;
templonga/=4096;
_acs0=0; //恢復ADC的通道為0
if(templonga>50) //如果AN1的電壓大于50毫伏
return TRUE;
else
return FALSE;
}
#pragma vector ISR_Timer @ 0x08
void ISR_Timer(void)
{
Timer0_temp_data++;
Counter_8ms_counter++;
if(Timer0_temp_data==12)
{
Counter_100ms_background++;
Counter_EnterSleepCounterDown++;
Counter_100ms_counter++;
if((Counter_100ms_background%10)==0)Counter_1second_background++;
Timer0_temp_data=0;
if(BUTTON1PORT==BUTTON1_STATUS_PRESSED)
{
Counter_Button1PressedCounter++;
}
else
{
Counter_Button1PressedCounter=0;
}
if(Counter_Button1PressedCounter>= LED5_ON_DELAY_TIME)
{
LED5PORT_Data_SHADE=~LED5PORT_Data_SHADE;
LED5PORT=LED5PORT_Data_SHADE;
LED5_Update_flag=TRUE;
Counter_Button1PressedCounter=0;
}
if(Counter_100ms_background%10 <5)
Blink_state=0;
else
Blink_state=1;
switch(Blink_LED_Number)
{
case 1:
LED1PORT=Blink_state;
break;
case 2:
LED2PORT=Blink_state;
break;
case 3:
LED3PORT=Blink_state;
break;
case 4:
LED4PORT=Blink_state;
break;
default:
break;
}
}
}
void BATT_VOL_SEG_Charge_Just()
{
if(battery_voltage<3860)
{
if((Previous_Level_Charge<=1))
Previous_Level_Charge=1;
}
else if(battery_voltage<3960)
{
if(Previous_Level_Charge<=2)
Previous_Level_Charge=2;
}
else if((battery_voltage<4160 ))
{
if(Previous_Level_Charge<=3)
Previous_Level_Charge=3;
}
else
{
if(Previous_Level_Charge<=4)
Previous_Level_Charge=4;
}
}
void LED_ShowChargeVoltage_Charging()
{
switch(Previous_Level_Charge)
{
case 1:
Blink_LED_Number=1;
LED2PORT=TURN_OFF;
LED3PORT=TURN_OFF;
LED4PORT=TURN_OFF;
break;
case 2:
LED1PORT=TURN_ON;
Blink_LED_Number=2;
LED3PORT=TURN_OFF;
LED4PORT=TURN_OFF;
break;
case 3:
LED1PORT=TURN_ON;
LED2PORT=TURN_ON;
Blink_LED_Number=3;
LED4PORT=TURN_OFF;
break;
case 4:
LED1PORT=TURN_ON;
LED2PORT=TURN_ON;
LED3PORT=TURN_ON;
Blink_LED_Number=4;
break;
case 5:
Blink_LED_Number=0;
LED1PORT=TURN_ON;
LED2PORT=TURN_ON;
LED3PORT=TURN_ON;
LED4PORT=TURN_ON;
break;
default:
Previous_Level_Charge=1;
}
}
void LED_ShowChargeVoltage()
{
Blink_LED_Number=0;
switch(Previous_Level_Charge)
{
case 1:
LED1PORT=TURN_ON;
LED2PORT=TURN_OFF;
LED3PORT=TURN_OFF;
LED4PORT=TURN_OFF;
break;
case 2:
LED1PORT=TURN_ON;
LED2PORT=TURN_ON;
LED3PORT=TURN_OFF;
LED4PORT=TURN_OFF;
break;
case 3:
LED1PORT=TURN_ON;
LED2PORT=TURN_ON;
LED3PORT=TURN_ON;
LED4PORT=TURN_OFF;
break;
case 4:
case 5:
LED1PORT=TURN_ON;
LED2PORT=TURN_ON;
LED3PORT=TURN_ON;
LED4PORT=TURN_ON;
break;
default:
Previous_Level_Charge=1;
}
}
bit LED_ShowDisChargeVoltage()
{
unsigned char tempchara;
if(battery_voltage<3250)
{
Previous_Level_DisCharge=1;
}
else if(battery_voltage<3650)
{
if(Previous_Level_DisCharge>= 2)
Previous_Level_DisCharge=2;
}
else if(battery_voltage<3800)
{
if(Previous_Level_DisCharge>= 3)
Previous_Level_DisCharge=3;
}
else if(battery_voltage<3950)
{
if(Previous_Level_DisCharge>= 4)
Previous_Level_DisCharge=4;
}
else
{
if(Previous_Level_DisCharge>= 5)
Previous_Level_DisCharge=5;
}
switch(Previous_Level_DisCharge)
{
case 1:
LED2PORT=TURN_OFF;
LED3PORT=TURN_OFF;
LED4PORT=TURN_OFF;
for(tempchara=0;tempchara<3;tempchara++)
{
LED1PORT=TURN_ON;
while(Blink_state==0)
{
#asm
clr wdt
#endasm
}
LED1PORT=TURN_OFF;
while(Blink_state==1)
{
#asm
clr wdt
#endasm
}
}
LED1PORT=TURN_OFF;
LED2PORT=TURN_OFF;
LED3PORT=TURN_OFF;
LED4PORT=TURN_OFF;
return FALSE;
case 2:
LED1PORT=TURN_ON;
LED2PORT=TURN_OFF;
LED3PORT=TURN_OFF;
LED4PORT=TURN_OFF;
break;
case 3:
LED1PORT=TURN_ON;
LED2PORT=TURN_ON;
LED3PORT=TURN_OFF;
LED4PORT=TURN_OFF;
break;
case 4:
LED1PORT=TURN_ON;
LED2PORT=TURN_ON;
LED3PORT=TURN_ON;
LED4PORT=TURN_OFF;
break;
case 5:
LED1PORT=TURN_ON;
LED2PORT=TURN_ON;
LED3PORT=TURN_ON;
LED4PORT=TURN_ON;
break;
default:
Previous_Level_DisCharge=5;
}
return TRUE;
}
void sys_init()
{
Counter_100ms_background=0;
Timer0_temp_data=0;
Counter_EnterSleepCounterDown=0;
Counter_Button1PressedCounter=0;
LED5_Update_flag=FALSE;
LED1PORT=TURN_OFF;
LED2PORT=TURN_OFF;
LED3PORT=TURN_OFF;
LED4PORT=TURN_OFF;
_pawk3=1; //有喚醒功能
_pac3=1; //設為輸入
_papu3=1; //使能上拉
_pawk5=1;
_pac5=1;
_papu5=1;
_pawk2=1;
_pac2=1;
_papu2=0;
_pa6=0;
_pac6=0;
_papu6=0;
_pa1=0;
_pac1=0;
_papu1=0;
_pa0=0;
_pac0=0;
_papu0=0;
_pa4=1;
_papu4=0;
_pawk4=0;
_pac4=0;
_pbc=0x00; //PB口全為輸出
_pbpu=0x00; //PB口無需上拉
_pb5=1;
//初始化timer0
_tmr0c=0b10000111; //設定timer0的時鐘源為4MHZ/16(812.5 HZ)
_tmr0=0; //設定timer0預裝數為0,使得其中斷頻率約為122 HZ
_t0f=0; //清timer0 interrupt request flag
_et0i=1; //開timer0中斷
Timer0_temp_data=0;
//初始化ADC
_acsr=0b00000001; //使能ADC的電源,并設置ADC的時鐘為system clock/8
_adcr=0b00010000; //PA0~PA1 enabled as AN0~AN1,并選擇ADC的通道為AN0
_t0on=1;//啟動timer0
_emi = 1 ; // Enable global interrupt
_wdts=0b00000111;
}
void main()
{
if(_to==0) //上電復位
{
Previous_State=CHARGE;
Previous_Level_Charge=1;
LED5PORT_Data_SHADE=TURN_OFF;
LED5PORT=LED5PORT_Data_SHADE;
WDT_Over_Counter=0;
Blink_LED_Number=0;
}
main_infinity_loop:
sys_init();
if(_to==1) //watchdog time-out occurred
{
WDT_Over_Counter++;
if(WDT_Over_Counter>=14400) //(24小時乘3600秒)除6
{
if(Previous_State==CHARGE)
Previous_Level_Charge=1;
WDT_Over_Counter=0;
}
if(just_discharge()==TRUE) //看門狗溢出喚醒后,若偵測到放電,并電池電壓低于3.25V時,LED1反復閃爍
{
Previous_State=DISCHARGE;
Previous_Level_Charge=1;
battery_voltage=ADC_GetBatteryData();
if(battery_voltage<3250)
{
for(;just_discharge()==TRUE;)
{
Previous_Level_DisCharge=1;
LED2PORT=TURN_OFF;
LED3PORT=TURN_OFF;
LED4PORT=TURN_OFF;
LED1PORT=TURN_ON;
while(Blink_state==0)
{
#asm
clr wdt
#endasm
}
LED1PORT=TURN_OFF;
while(Blink_state==1)
{
#asm
clr wdt
#endasm
}
if(CHARGER_PLUGGED) goto Charging;
}
}
}
if(CHARGER_PLUGGED) goto Charging;//由于硬件的原因,當插入充電器時后,若不在充電狀態,是不能喚醒MCU的
goto sleep;
}
if(BUTTON1PORT==BUTTON1_STATUS_NOPRESSED)//不是由按鍵喚醒的
{
Counter_100ms_background=0;
while(Counter_100ms_background<10)//延時1秒,規避插上充電器的瞬間的不穩定。
{
#asm
clr wdt
#endasm
}
}
if(CHARGER_PLUGGED)//充電中
{
Charging:
Counter_1second_background=0;
for(;CHARGER_PLUGGED;)//充電中
{
Previous_State=CHARGE;
Previous_Level_DisCharge=5;
battery_voltage=ADC_GetBatteryData();//執行一次ADC轉換
BATT_VOL_SEG_Charge_Just();
LED_ShowChargeVoltage_Charging(); //電壓顯示
//充滿的判斷..........
Charge_Full_flag=FALSE;
if(CHARGER_PLUGGED && CHARGE_FULL)
{
Counter_8ms_counter=0;
Charge_Full_flag=TRUE;
while(Counter_8ms_counter<122)//_pa3處于高電平長達1秒,則判為已充滿
{
if(CHARGER_UNPLUGGED || CHARGE_UNFULL)
{
Charge_Full_flag=FALSE;
break;
}
#asm
clr wdt
#endasm
}
}
if(Charge_Full_flag==TRUE)//已經充滿
{
Previous_Level_Charge=5;
LED_ShowChargeVoltage_Charging();
while(CHARGER_PLUGGED)//充滿后,等待充電器移除
{
if(CHARGE_UNFULL)//充滿后,有可能重新進入充電狀態
{
Previous_Level_Charge=4;
break;
}
#asm
clr wdt
#endasm
}
}
}
if(Previous_Level_Charge==5) Previous_Level_Charge=4;//移除充電器進入休眠后,再一次接入充電器時,允許再充電
goto sleep;
}
while(BUTTON1PORT==BUTTON1_STATUS_PRESSED)//如果有Button1按下,則等其松開
{
#asm
clr wdt
#endasm
}
if(LED5_Update_flag==TRUE)
{
Counter_100ms_background=0;
while(Counter_100ms_background==0);//延時一下再進入休眠,避開Button1松開時的毛刺
goto sleep;
}
if(just_discharge()==TRUE)
{
Previous_State=DISCHARGE;
Previous_Level_Charge=1;
}
if(battery_voltage<3250)//如果電壓低于3.25V,將早前的狀態切換成放電,用以指示低電壓警告
{
Previous_State=DISCHARGE;
Previous_Level_Charge=1;
}
if(Previous_State==CHARGE)
{
battery_voltage=ADC_GetBatteryData();//執行一次ADC轉換
BATT_VOL_SEG_Charge_Just();
LED_ShowChargeVoltage(); //電壓顯示(充電)
}
else
{
battery_voltage=ADC_GetBatteryData();//執行一次ADC轉換
if(LED_ShowDisChargeVoltage()==FALSE) //電壓顯示(放電)
{
while((_pa2==1) ||
(BUTTON1PORT==BUTTON1_STATUS_PRESSED))
{
if(_pa2==1)
goto Charging;
}
goto sleep;
}
}
prepare_to_sleep:
_emi = 0 ; // disable global interrupt
Counter_EnterSleepCounterDown=0;
_emi = 1 ; // Enable global interrupt
while((_pa2==1) ||
(BUTTON1PORT==BUTTON1_STATUS_PRESSED) ||
(Counter_EnterSleepCounterDown < SLEEP_DELAY_TIME))
{
if(_pa2==1)
goto Charging;
#asm
clr wdt
#endasm
if(Counter_EnterSleepCounterDown > SLEEP_DELAY_TIME)
{
LED1PORT=TURN_OFF;
LED2PORT=TURN_OFF;
LED3PORT=TURN_OFF;
LED4PORT=TURN_OFF;
}
}
sleep:
Blink_LED_Number=0;
LED1PORT=TURN_OFF;
LED2PORT=TURN_OFF;
LED3PORT=TURN_OFF;
LED4PORT=TURN_OFF;
_adonb=1; //關閉ADC的電源
_pb5=0;
_pa4=0;
_adcr=0;
#asm
HALT //進入sleep
NOP
NOP
#endasm
//初始化ADC
_t0on=0;//停止timer0
_emi = 0; // Disable global interrupt
goto main_infinity_loop;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -