📄 poweru.c
字号:
/*
深圳市瑞科威科技有限公司:李德明
2011-9-20
TEL: 15818545833
QQ:164214905
欢迎看到此资源的厂家前来联系,可提供整体方案,包括模具
本压缩包里面的程序与电路图是量产过的,可直接使用。
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 + -