⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ___poweru.c

📁 移动电源方案
💻 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 + -