?? 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 LED6PORT _pa4
#define BUTTON1PORT _pa5
#define BUTTON1_PRESSED (_pa5==0)
#define BUTTON1_NOPRESSED (_pa5==1)
#define LED6_ON_DELAY_TIME 20
#define SLEEP_DELAY_TIME 30
#define CHARGER_PLUGGED (_pa2==0)
#define CHARGER_UNPLUGGED (_pa2==1)
#define CHARGE_FULL (_pa3==1)
#define CHARGE_UNFULL (_pa3==0)
#define DISCHARGE_ENABLE (_pa6=0)
#define DISCHARGE_DISABLE (_pa6=1)
unsigned char
Counter_100ms_background,
Counter_1second_background,
Counter_1second_background2,
Counter_1second_background3,
Counter_Button1PressedCounter,
Counter_100ms_counter,
Counter_8ms_counter,
Timer0_temp_data,
Previous_Level,
tempchara;
bit LED6PORT_Data_SHADE,
LED6_Update_flag,
Previous_State,
Blink_state,
Charge_Full_flag;
unsigned short battery_voltage,tempinta,WDT_Over_Counter,Discharge_Sensor_Voltage;
unsigned long templonga;
void All_LED_Off(void)
{
LED1PORT=TURN_OFF;
LED2PORT=TURN_OFF;
LED3PORT=TURN_OFF;
LED4PORT=TURN_OFF;
LED5PORT=TURN_OFF;
}
void All_LED_ON(void)
{
LED1PORT=TURN_ON;
LED2PORT=TURN_ON;
LED3PORT=TURN_ON;
LED4PORT=TURN_ON;
LED5PORT=TURN_ON;
}
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;
Discharge_Sensor_Voltage=templonga;
_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_100ms_counter++;
if((Counter_100ms_background&0b00000111)==0)
{
Counter_1second_background++;
Counter_1second_background2++;
Counter_1second_background3++;
}
Timer0_temp_data=0;
if(BUTTON1_PRESSED)
{
Counter_Button1PressedCounter++;
}
else
{
Counter_Button1PressedCounter=0;
}
if(Counter_Button1PressedCounter>= LED6_ON_DELAY_TIME)
{
LED6PORT_Data_SHADE=~LED6PORT_Data_SHADE;
LED6PORT=LED6PORT_Data_SHADE;
LED6_Update_flag=TRUE;
Counter_Button1PressedCounter=0;
}
if((Counter_100ms_background&0b00000111) <4)
Blink_state=0;
else
Blink_state=1;
}
}
bit Batt_Vol_LessThan(unsigned short COMP_Value)
{
if(battery_voltage<COMP_Value) return TRUE;
else return FALSE;
}
/*
unsigned char BATT_VOL_SEG_Charge_Just()
{
unsigned char tempchar4;
if(Batt_Vol_LessThan(3830)==TRUE)
{
tempchar4=1;
}
else if(Batt_Vol_LessThan(3900)==TRUE)
{
tempchar4=2;
}
else if(Batt_Vol_LessThan(4000)==TRUE)
{
tempchar4=3;
}
else if(Batt_Vol_LessThan(4160)==TRUE)
{
tempchar4=4;
}
else
{
tempchar4=5;
}
return(tempchar4);
}
unsigned char BATT_VOL_SEG_Discharge_Just()
{
unsigned char tempchar5;
if(Batt_Vol_LessThan(3250)==TRUE)
{
tempchar5=0;
}
else if(Batt_Vol_LessThan(3650)==TRUE)
{
tempchar5=1;
}
else if(Batt_Vol_LessThan(3750)==TRUE)
{
tempchar5=2;
}
else if(Batt_Vol_LessThan(3850)==TRUE)
{
tempchar5=3;
}
else if(Batt_Vol_LessThan(4000)==TRUE)
{
tempchar5=4;
}
else
{
tempchar5=5;
}
return(tempchar5);
}
*/
unsigned char BATT_VOL_SEG_Just()
{
unsigned char tempchar5;
if(Batt_Vol_LessThan(3300)==TRUE)
{
tempchar5=0;
}
else if(Batt_Vol_LessThan(3600)==TRUE)
{
tempchar5=1;
}
else if(Batt_Vol_LessThan(3800)==TRUE)
{
tempchar5=2;
}
else if(Batt_Vol_LessThan(4000)==TRUE)
{
tempchar5=3;
}
/* else if(Batt_Vol_LessThan(4000)==TRUE)
{
tempchar5=4;
}
*/ else
{
tempchar5=4;
}
return(tempchar5);
}
void LED_ShowVoltage(unsigned char Previous_Voltage_Level)
{
unsigned char tempchara;
Counter_100ms_counter=0;
switch(Previous_Voltage_Level)
{
case 0:
LED2PORT=TURN_OFF;
LED3PORT=TURN_OFF;
LED4PORT=TURN_OFF;
LED5PORT=TURN_OFF;
for(tempchara=0;tempchara<5;tempchara++)
{
LED1PORT=TURN_ON;
while(Blink_state==0)
{
#asm
clr wdt
#endasm
}
LED1PORT=TURN_OFF;
while(Blink_state==1)
{
#asm
clr wdt
#endasm
}
}
break;
case 1:
LED1PORT=TURN_ON;
LED2PORT=TURN_OFF;
LED3PORT=TURN_OFF;
LED4PORT=TURN_OFF;
LED5PORT=TURN_OFF;
break;
case 2:
LED1PORT=TURN_ON;
LED2PORT=TURN_ON;
LED3PORT=TURN_OFF;
LED4PORT=TURN_OFF;
LED5PORT=TURN_OFF;
break;
case 3:
LED1PORT=TURN_ON;
LED2PORT=TURN_ON;
LED3PORT=TURN_ON;
LED4PORT=TURN_OFF;
LED5PORT=TURN_OFF;
break;
case 4:
LED1PORT=TURN_ON;
LED2PORT=TURN_ON;
LED3PORT=TURN_ON;
LED4PORT=TURN_ON;
LED5PORT=TURN_OFF;
break;
case 5:
/* LED1PORT=TURN_ON;
while(Counter_100ms_counter<3);
LED2PORT=TURN_ON;
while(Counter_100ms_counter<6);
LED3PORT=TURN_ON;
while(Counter_100ms_counter<9);
LED4PORT=TURN_ON;
#asm
clr wdt
#endasm
while(Counter_100ms_counter<12);
LED5PORT=TURN_ON;
break;
case 6:
*/ All_LED_ON();
break;
default:
Previous_Level=5;
}
#asm
clr wdt
#endasm
if(CHARGER_PLUGGED)
{
while(Blink_state==0);
#asm
clr wdt
#endasm
switch(Previous_Voltage_Level)
{
case 1: LED1PORT=TURN_OFF;
break;
case 2: LED2PORT=TURN_OFF;
break;
case 3: LED3PORT=TURN_OFF;
break;
case 4: LED4PORT=TURN_OFF;
break;
}
while(Blink_state==1);
#asm
clr wdt
#endasm
}
}
void Voltage_Display()
{
if(Previous_Level==0)
{
LED_ShowVoltage(Previous_Level);
}
else
{
LED_ShowVoltage(Previous_Level);
Counter_100ms_counter=0;
while(Counter_100ms_counter < 50)//等待5秒
{
#asm
clr wdt
#endasm
}
}
All_LED_Off();
}
void sys_init()
{
Counter_100ms_background=0;
Timer0_temp_data=0;
Counter_100ms_counter=0;
Counter_Button1PressedCounter=0;
LED6_Update_flag=FALSE;
_pawk3=1; //有喚醒功能
_pac3=1; //設為輸入
_papu3=1; //使能上拉
_pawk5=1;
_pac5=1;
_papu5=1;
_pawk2=1;
_pac2=1;
_papu2=1;
_pa6=1;
_pac6=1;//不管放電啦
_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
_t0e=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;
// _ctrl1=0b10000101;//Enable WDT;
}
void main()
{
if(_to==0) //上電復位
{
sys_init();
All_LED_ON();
Counter_100ms_counter=0;
while(Counter_100ms_counter<30)//接上電芯后,所有LED點亮3秒后熄滅。
{
#asm
clr wdt
#endasm
}
LED6PORT_Data_SHADE=TURN_OFF;
LED6PORT=LED6PORT_Data_SHADE;
WDT_Over_Counter=0;
battery_voltage=ADC_GetBatteryData();//執行一次ADC轉換
Previous_Level=BATT_VOL_SEG_Just();
goto sleep;
}
main_infinity_loop:
sys_init();
if(_to==1) //watchdog time-out occurred
{
/* WDT_Over_Counter++;
if(WDT_Over_Counter>=57600) //(96小時乘3600秒)除6
{
Counter_100ms_counter=0;
while(Counter_100ms_counter<2)//等待外圍電路穩定。
{
#asm
clr wdt
#endasm
}
battery_voltage=ADC_GetBatteryData();
tempchara=BATT_VOL_SEG_Just();
if(tempchara<Previous_Level) Previous_Level--;
WDT_Over_Counter=0;
}
if(just_discharge()==TRUE) //看門狗溢出喚醒后,若偵測到放電,則跳轉到放電處理程序
goto Discharging;
else
*/ goto sleep;
}
if(BUTTON1_NOPRESSED)//不是由按鍵喚醒的
{
Counter_100ms_counter=0;
while(Counter_100ms_counter<5)//延時0.5秒,規避插上充電器的瞬間的不穩定。
{
#asm
clr wdt
#endasm
}
}
if(CHARGER_PLUGGED)//充電中
{
Charging:
// DISCHARGE_DISABLE;
battery_voltage=ADC_GetBatteryData();//執行一次ADC轉換
tempchara=BATT_VOL_SEG_Just();
Previous_Level=tempchara;
Counter_1second_background=0;
for(;CHARGER_PLUGGED;)//充電中
{
if(Previous_Level<=1) Previous_Level=1;
battery_voltage=ADC_GetBatteryData();//執行一次ADC轉換
tempchara=BATT_VOL_SEG_Just();
if(tempchara==Previous_Level) Counter_1second_background=0;
if(Counter_1second_background>120)//如果在120秒內,每次采樣得到的電壓段與之前都不一樣,則說明電壓真的改變了。
{
if(tempchara>Previous_Level)Previous_Level++;
Counter_1second_background=0;
}
LED_ShowVoltage(Previous_Level); //電壓顯示
//充滿的判斷..........
Charge_Full_flag=FALSE;
if(CHARGER_PLUGGED && CHARGE_FULL)
{
Counter_100ms_counter=0;
Charge_Full_flag=TRUE;
while(Counter_100ms_counter<30)//_pa3處于高電平長達3秒,則判為已充滿
{
if(CHARGER_UNPLUGGED || CHARGE_UNFULL)
{
Charge_Full_flag=FALSE;
break;
}
#asm
clr wdt
#endasm
}
}
if(Charge_Full_flag==TRUE)//已經充滿
{
All_LED_ON();
Previous_Level=4;
while(CHARGER_PLUGGED)//充滿后,等待充電器移除
{
#asm
clr wdt
#endasm
}
Counter_100ms_counter=0;
while(Counter_100ms_counter<50)//當取下充電器后5S,LED燈全滅,MCU自動進入休眠狀態。
{
#asm
clr wdt
#endasm
}
goto sleep;
}
}
LED_ShowVoltage(Previous_Level);//非充滿的情況下取下充電器后,由于前一次跑馬完成后,LED都是熄滅的,所以在此還需再點亮
Counter_100ms_counter=0;
while(Counter_100ms_counter<50)//當取下充電器后5S,LED燈全滅,MCU自動進入休眠狀態。
{
#asm
clr wdt
#endasm
}
goto sleep;
}
// DISCHARGE_ENABLE;
while(BUTTON1_PRESSED)//如果有Button1按下,則等其松開
{
#asm
clr wdt
#endasm
}
if(LED6_Update_flag==TRUE)
{
Counter_100ms_counter=0;
while(Counter_100ms_counter==0);//延時一下再進入休眠,避開Button1松開時的毛刺
goto sleep;
}
battery_voltage=ADC_GetBatteryData();//執行一次ADC轉換
tempchara=BATT_VOL_SEG_Just();
// if(tempchara<Previous_Level) Previous_Level=tempchara;//非充電狀態下,電壓只容許下降
Previous_Level=tempchara;
Voltage_Display();
while(BUTTON1_PRESSED)//如果有Button1按下,則等其松開
{
#asm
clr wdt
#endasm
}
sleep:
if(CHARGER_PLUGGED)
goto Charging;
All_LED_Off();
_adonb=1; //關閉ADC的電源
_pb5=0;
_adcr=0;
#asm
HALT //進入sleep
NOP
NOP
#endasm
//初始化ADC
_t0on=0;//停止timer0
_emi = 0; // Disable global interrupt
#asm
clr wdt
#endasm
goto main_infinity_loop;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -