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

📄 charge.c

📁 此压缩包为杰得开发得z228的BSP的源代码,可以实现很多功能,尤其是视频解码有很好的效果.
💻 C
字号:
/********************************************************/
/* charge.c: implementation of charging about As3603.		*/
/* Author   : qzsu																			*/
/* History  : 2006-11-01																*/
/********************************************************/

#define CHARGE_WINCE

//include
#include <stdlib.h>
#include <stdio.h>
#include ".\inc\wm97xx.h"
#include ".\inc\charge.h"
#include ".\inc\powermanagement.h"

#ifdef CHARGE_WINCE
#include "hw_lib.h"
#include <windows.h>
#endif

//#define _DEBUG
#define DWORD unsigned int

#define VOL_OFFSET 7
#define VOL_MAX 500
#define VOL_MIN 343

//global
unsigned char* g_AACI_BASE = NULL;

//function
//external
//bool NoSystemStart(void);
//unsigned char GetBatteryQAccPercent(void);

//internal
void Delay(unsigned int msec);
void UDelay(unsigned int us);
static int apAACI_ReadRegister(volatile int reg);
static int apAACI_WriteRegister(volatile int reg, int value);
int GetBatteryVoltage(unsigned int* vol);


/*****************************************
Fuction:	delay msec
Input:		unsigned int msec
Output:		none
Return:		none
Modify:
*******************************************/
void Delay(unsigned int msec)
{
	int i;
	i = msec *50000;
	while(i--);
}


/*****************************************
Fuction:	delay us
Input:		unsigned int us
Output:		none
Return:		none
Modify:
*******************************************/
void UDelay(unsigned int us)
{
	int i;
	i = us *33;
	while(i--);
}


/*****************************************
Fuction:	Write a value to a CODEC control register
Input:		volatile int reg -- register address
					int value
Output:		none
Return:		ture -- success;false -- fail
Modify:
*******************************************/
// Write a value to a CODEC control register
static int apAACI_WriteRegister(volatile int reg, int value)
{
    int timer;

	if(!g_AACI_BASE)return FALSE;

    //AACI_SLFR ---#define AACI_SL1TXBUSY  0x0002---Slot 1 transceive busy????
    // Wait for TX1/2 not to be busy
    timer = AACI_TIMEOUT;
    while ((*((DWORD*)(AACI_SLFR)) & AACI_SL1TXBUSY) && timer) {//等待slot1 的传送寄存器空闲
        UDelay(10);
        timer--;
    }
    // Note: the data value must be setup before the address
    *((DWORD*)(AACI_SL2TX)) = value << 4;//数据寄存器
    *((DWORD*)(AACI_SL1TX)) = reg   << 12;//地址寄存器

    if (timer)
        return TRUE;
    else
        return FALSE;
}

/*****************************************
Fuction:	Read a value from a CODEC control register
Input:		volatile int reg -- register address
Output:		none
Return:		value readed from register
Modify:
*******************************************/
static int apAACI_ReadRegister(volatile int reg)
{
    int timer;
    unsigned int data;//, stat;

	if(!g_AACI_BASE)return FALSE;

	timer = AACI_TIMEOUT;
    //先放数据,再放地址
    while ((*((DWORD*)(AACI_SLFR)) & AACI_SL1TXBUSY) && timer) {//等待slot1 的传送寄存器空闲
        UDelay(10);
        timer--;
    }
	
    //先放数据,再放地址
    *((DWORD*)(AACI_SL2TX)) = 0;
    //地址为8BIT,所以应该放在20位中的高8位,所以要向右移12位
    *((DWORD*)(AACI_SL1TX)) = (reg << 12) | 0x80000;

    timer = AACI_TIMEOUT;
    while(((*((DWORD*)(AACI_SLFR)) & 0x100) == 0) && timer){//当退出这个循环的时候表示数据已经接收到了 
        UDelay(10);
        timer--;
    }

  	data = (*((DWORD*)(AACI_SL2RX)) >> 4);
	return data;
}



/*****************************************
Fuction:	check battery voltage
Input:		none
Output:		voltage value
Return:		-1:address error
					0:data error
					1:success
Modify:
*******************************************/
int GetBatteryVoltage(unsigned int* vol)
{
  unsigned int datax0,datay0;
  unsigned int voltage0,voltage1,voltage2,voltage3;
  unsigned int regValue;
  
  if(!g_AACI_BASE || !vol)
  {
  	return -1;
  }

  regValue = apAACI_ReadRegister(0x78);
#ifdef _DEBUG
	printf("apAACI_ReadRegister(0x78):%x\r\n",regValue);
#endif
	if(!(regValue == 0xc201 || regValue == 0xc001))
	{
	 	apAACI_WriteRegister(0x78, 0xc201);
		return -2;
	}
  
   	//comp1
		apAACI_WriteRegister(0x76, 0xc006);
		datax0 = apAACI_ReadRegister(0x7a)&0x0fff;
    voltage0 = datax0*250*70/(4095*34);
#ifdef _DEBUG
	printf("voltage0:%d\r\n",voltage0);
#endif
        
    if(voltage0 < VOL_MIN-VOL_OFFSET || voltage0 > VOL_MAX-VOL_OFFSET)
    {
    	return 0;
    }
        
    //comp2
		apAACI_WriteRegister(0x76, 0xd006);
		datay0 = apAACI_ReadRegister(0x7a)&0x0fff;      
    voltage1 = datay0*250*70/(4095*33);
#ifdef _DEBUG
	printf("voltage1:%d\r\n",voltage1);
#endif
        
    if(voltage1 < VOL_MIN-VOL_OFFSET || voltage1 > VOL_MAX-VOL_OFFSET)
    {
    	return 0;
    }

    voltage2= (voltage0+voltage1)/2;
    voltage3 = voltage2 + VOL_OFFSET;//铜线降压偏差
        
#ifdef _DEBUG
	printf("GetBatteryVoltage:%d\r\n",voltage3);
#endif
	
	*vol = voltage3;
  
  return 1;
}



/*****************************************
Fuction:	get battery qacc percent using voltage check
Input:		none
Output:		none
Return:		the percent of QAcc
Modify:
*******************************************/
unsigned char GetBatteryQAccPercent(void)
{
	unsigned int vol;
	unsigned int count = 0;
	int ret;
	
	ret = GetBatteryVoltage(&vol);
	while(count++ < 100 && ret <= 0)
	{
		Sleep(20);
		ret = GetBatteryVoltage(&vol);
	}	
	if(ret == 1)
	{
		if(vol >= 420)
		{
			return 100;//100%
		}
		else if(vol >= 390 && vol < 420)
		{
			return (vol-390)*(100-80)/(420-390)+80;
		}
		else if(vol >= 360 && vol < 390)
		{
			return (vol-360)*(80-20)/(390-360)+20;
		}
		else if(vol > VOL_MIN && vol < 360)
		{
			return (vol-VOL_MIN)*(20-0)/(360-VOL_MIN);
		}
		else
		{
			return 0;
		}
	}
	return 0;
}


/*****************************************
Fuction:	judge if permit system start with check battery voltage
Input:		none
Output:		none
Return:		true -- no permit;false -- permit
Modify:
*******************************************/
bool NoSystemStart(void)
{
	unsigned int vol;
	
	if(GetBatteryVoltage(&vol) && vol <= VOL_MIN)
	{
		return true;
	}
	return false;
}


bool InitCharge(void)
{
#ifdef CHARGE_WINCE
	g_AACI_BASE = (unsigned char *)(hw_map_io(0x20037000, 0x1000, 0));
	hw_delay(1);
#else
	g_AACI_BASE = (unsigned char *)0x20037000;
#endif

	if(!g_AACI_BASE)
	{
		return false;
	}

#ifndef CHARGE_WINCE
  //下面复位信号可以让AACI 复位
  *AACI_RESET = 0;
  Delay(100);//复位等待
  *AACI_RESET = 1;//置高电平让外围设备工作
  Delay(1);//等待外围设备工作稳定
   
  *AACI_MAINCR = (1 << 6) | (1 << 5) | (1 << 4) | (1 << 3) | (1 << 0);
#endif

 	apAACI_WriteRegister(0x78, 0xc201);
	
	return true;
}


void DeInitCharge(void)
{
}



//======================Battery Charger Controller BEGIN=====================

void PM_ChargeInitial(void)
{
	WriteAs3603(FUELGAUGE_REG, 0x00);
	
//	WriteAs3603(CHARGECTRL_REG, 0x00);

	PM_ChargeDefaultConfig();
}



U32 PM_ChargeFinish(void)
{
	unsigned char ctrlreg;
		
	ctrlreg = ReadAs3603(CHARGECTRL_REG);
	ctrlreg	&= 0xFE;
	WriteAs3603(CHARGECTRL_REG, ctrlreg);

	return 1;
}

U8 PM_ChargerDetected(void)
{
	U8 value;
	
	value = ReadAs3603(CHARGESTATUS_REG);
	//printf("CHARGESTATUS_REG:%x\r\n",value);
	if((value & 0x01) == 0x01)//chDet
	{
		return true;
	}
	
	return false;
}



void PM_ChargeDefaultConfig(void)
{
	/* Sets charger config register
	000	N/A
	0	Enable battery presence indication
	0	Enable operation without battery
	0	Li+ battery with coke anode
	0	Disable CVM testmode
	*/
	WriteAs3603(CHARGECONF_REG, 0x00);
	
	/* Sets charger current
	TrickleCurrent 2.5mV/RSENSE
	ConstantCurrent 15mV/Rsense
	*/
	WriteAs3603(CHARGECURRENT_REG, 0x1d);//0x11);//700mA
	
	
	WriteAs3603(PRECURDAC_REG, 0x32);//0.5v r=2k
}

#define FULLQ 2200000 //uAh
U8 PM_ChargeUpdate(int* avgCurrent,U32* uiQacc,U32* uiTime)
{
	unsigned char value;
	U32 deltaCount;
	U32 deltaQ;
	U32 deltaT;
	static unsigned char trickleFlag = 0;
	static unsigned char fullFlag = 0;
	
	value = ReadAs3603(FUELGAUGE_REG);
	value |= 0x02;
	WriteAs3603(FUELGAUGE_REG, value);
	
	do
	{
		value = ReadAs3603(FUELGAUGE_REG);
	}while((value & 0x02) == 0x02);//wait update

  //time
	deltaT = ((U32)ReadAs3603(ELAPSEDMSB_REG)) << 8;
	deltaT += ReadAs3603(ELAPSEDLSB_REG);
	if(deltaT == 0)
	{
		return false;
	}
	deltaT = deltaT * 3600000;//8788;//0.8788s per count
	deltaT /= 4096;//10;

  
  //QACC
  value = ReadAs3603(CHARGESTATUS_REG);
  if(fullFlag == 0 && (value & 0x01) == 0x01)//charge
	{
		//charge check sign bit is 0
		if((ReadAs3603(DELTAMSB_REG) & 0x80) != 0)
		{
			return false;
		}
	  deltaCount = ((U32)(ReadAs3603(DELTAMSB_REG)&0x7f)) << 8;
	  deltaCount += ReadAs3603(DELTALSB_REG);
		if(deltaCount == 0)
		{
			return false;
		}
	}
	else//discharge
	{
		//charge check sign bit is 1
		if((ReadAs3603(DELTAMSB_REG) & 0x80) == 0)
		{
			return false;
		}
	  deltaCount = ((U32)(0x7f-(ReadAs3603(DELTAMSB_REG)&0x7f))) << 8;
	  deltaCount += 0xff-ReadAs3603(DELTALSB_REG);
		if(deltaCount == 0 || deltaCount == 0x7fff)
		{
			return false;
		}
	}
	deltaQ = deltaCount * 6103;//61.03uAh per count
	deltaQ /= 100;//uAh

	*uiTime = *uiTime + deltaT;//ms
  if((value & 0x01) == 0x01)//charge
	{
		*uiQacc += deltaQ;//uAh
	}
	else
	{
		if(*uiQacc > deltaQ)
		{
			*uiQacc -= deltaQ;//uAh
		}
		else
		{
			*uiQacc = 0;
		}
	}

	{double temp;
	int iTemp;
		//																							AVFC  Rsense  deltaT/1000 m欧		mA
		temp = (double)deltaCount / ( (double)deltaT * 91.0 * 50.0) * 1000.0 * 1000.0 * 1000.0;
		iTemp = (int)temp;
		*avgCurrent = iTemp;
	}
	//*avgCurrent = (U32)((double)deltaCount*1000*1000*1000 / ( deltaT * 91 * 50));//mA
	
	if(PM_ChargerDetected())
	{
		if(PM_ChargeIsFull() || (*uiQacc) > FULLQ)
		{
			*uiQacc = FULLQ;//uAh
			if(PM_ChargeIsFull())
			{
				PM_ChargeFinish();
				fullFlag = 1;
			}
		}
		else if(!trickleFlag)
		{
			if(PM_ChargeIsTrickle())
			{
				*uiQacc = FULLQ / 100 * 95;
				trickleFlag = 1;
			}
			else if((*uiQacc) > FULLQ / 100 * 94)
			{
				*uiQacc = FULLQ / 100 * 94;
			}
		}
		
		//充满后会放电,掉到98%以下重新启动充电
		if(fullFlag == 1 && (*uiQacc) < FULLQ / 100 * 98)
		{
			PM_ChargeStart(); 
			fullFlag = 0;
		}
	}
	
	return true;
}


U8 PM_IsCharging(void)
{
	unsigned char status;
	
	// Detectes battery
	status = ReadAs3603(CHARGESTATUS_REG);
#ifdef _DEBUG
	printf("CHARGESTATUS_REG:%.2x\r\n",status);
#endif

	if((status & 0x03) == 0x03)//chDet,chAct
	{
		return true;
	}

	return false;
}

U8 PM_ChargeIsFull(void)
{
	U8 value;
	
	value = ReadAs3603(CHARGESTATUS_REG);
	if(PM_ChargerDetected() && (value & 0x20) == 0x20)
	{
		return true;
	}
	else
	{
		return false;
	}
}

U8 PM_ChargeIsTrickle(void)
{
	U8 value;
	
	value = ReadAs3603(CHARGESTATUS_REG);
	if(PM_ChargerDetected() && (value & 0x10) == 0x10)
	{
		return true;
	}
	else
	{
		return false;
	}
}

U8 PM_ChargeIsEmpty(void)
{
	U8 value;
	
	value = ReadAs3603(CHARGESTATUS_REG);
	if(!PM_ChargerDetected() && (value & 0x20) == 0x20)
	{
		return true;
	}
	else
	{
		return false;
	}
}


U8 PM_NoBattery(void)
{
	unsigned char status;
	
	// Detectes battery
	status = ReadAs3603(CHARGESTATUS_REG);
	if(status & 0x40)
	{
//#ifdef _DEBUG
		printf("Not detecte battery!--%x\r\n",status);
//#endif
		return true;
	}

	return false;
}


U8 PM_ChargeStart(void)
{
	/* Sets Fuel Gauge Register
	1	Enables Fuel Gauge.
	0	Controls the updates of the Delta Charge MSB/LSB registers and the Elapsed Time MSB/LSB registers
	1	Request offset calibration.
	0	Sets the offset calibration mode.
	*/
	WriteAs3603(FUELGAUGE_REG, 0x01);

	
	/* Sets parameter of the charger
	0	Disables charging
	0	lithium-based battery
	0	Selects Constant Current charge mode
	0	Li+ battery with coke anode
	0	Select constant voltage charging mode
	0	Normal charger operation.
	0	Nominal current
	*/
	/* Enable charger*/
//	WriteAs3603(CHARGECTRL_REG, 0x41);//boost = 1
	WriteAs3603(CHARGECTRL_REG,ReadAs3603(CHARGECTRL_REG)|0x01);
	
	return true;
}



/************************************************************************/
//======================Battery Charger Controller END=====================


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -