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

📄 poweru.c

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