📄 chongdianqi.c
字号:
//***************************************************************************
//* Charger.c
//* By : 王进
//* Date : March 2009
//* Description : P89LPC916用于充电器控制部分
//***************************************************************************
#include <reg916.h> // 定义LPC916头文件
#define uchar unsigned char
#define uint unsigned int
//-----------------------------------------------
//定义全局变量
//---------------------------------------------
uchar data RTC_Counter_LED, LED_Flash_Speed; //RTC 用于 LED 延时
uint data RTC_Counter_AD; //RTC 计数用于 AD转换
uint data AD_Convert_Speed; //AD转换间隔时间
uint data RTC_Counter; //RTC定时
uchar data RTC_Counter_Minute; // 延时控制的时间
bit data LED_Flag, AD1_Flag, AD_Flag, Battery_On_Socket;
bit data Pre_Charge_Status, Constant_Current_Charge, Constant_Voltage_Charge;
uint data AD1_1,AD1_2,AD1_3; //AD1.1-检测电压, AD1.2-检测温度., AD1.3-检测电流
uchar data average; // AD 转换的平均时间
/****************************************************************************
各脚位功能:P0.2脚AD采样电压。P0.4脚AD采样电流。P1.2为PWM输出。P0.1为LED输出。
****************************************************************************/
//-----------------------------------------------
//定义常量
//-----------------------------------------------
#define LED_FLASH_FAST 10 // 定义LED灯闪最高频率
#define LED_FLASH_SLOW 200 // 定义LED灯闪最低频率
#define STOP_CHARGE_DELAY 50 // 当电流为1.5A时延时开始,延时X分
//***************************************************************************
//* 声明
//***************************************************************************
void main(void); // 主函数
void init(void); // 初始化函数
void ad_convert(void);//AD控制函数
//***************************************************************************
//* main()
//* Description : 主函数
//***************************************************************************
void main ()
{
EA = 0;
init();
EA = 1;
for( RTC_Counter = 1; RTC_Counter < 1700; );
RTC_Counter = 0;
for(;;)
{
if(LED_Flag == 0) // 控制LED为灯闪
{
KB1 = 0;
}
else
{
KB1 = 1;
}
if( ( AD_Flag == 1 ) && ( Battery_On_Socket == 1 ))
// 开始 AD 转换并控制 PWM, 预设AD转换速度
{ // AD_Flag 控制 AD 转换速度
ad_convert();
AD_Flag = 0;
}
if( RTC_Counter_Minute == STOP_CHARGE_DELAY ) // 如果延时结束, 停止 charge
{
EA = 0; //关闭中断, 所以无法设置 AD_Flag
P1 = 0; //关闭 PWM
LED_Flag = 1; //LED打开
}
}
}
//***************************************************************************
//* init()
//* Description : P89LPC916 初始化
//***************************************************************************
void init(void)
{
//SP = 0x30; //设置 SP 从 50H - 7FH
//-----------------------------------------------
//配置 P0 I/O
//-----------------------------------------------
P0M1 = 0x1C; // 设置 P0.2/3/4 为输入, 0001 1100
P0M2 = 0xE3; // 设置 P0.1 for PP, P0^1 用于LED, 1110 0011
//-----------------------------------------------
//配置 P1 I/O
//-----------------------------------------------
P1M1 = 0x24; // ^5 Input only 0010 0100
P1M2 = 0xdf; // 设置 P1^2 为开漏输出 1101 1111
//-----------------------------------------------
//配置 P2 I/O (P2 没有使用)
//-----------------------------------------------
P2M1 = 0x00; // 设置P2口为推挽输出
P2M2 = 0xFF;
KB5 = 0; //设置 p0.5 = 0
P1 = 0x00; //设置 p1.2 = 0 TO为PWM
P2 = 0x00;
RTC_Counter = 0x00;
RTC_Counter_LED = 0x00;
LED_Flag = 0;
LED_Flash_Speed = LED_FLASH_SLOW;
AD1_1 = 0;
AD1_2 = 0;
AD1_3 = 0;
AD1_Flag = 0;
RTC_Counter_LED= 0;
AD_Flag = 0;
average = 10;
Pre_Charge_Status = 0;
Constant_Current_Charge = 0;
Constant_Voltage_Charge = 0;
RTC_Counter_Minute = 0;
Battery_On_Socket = 1;
AD_Convert_Speed = 10;
//-----------------------------------------------
//初始化 RTC 用于定时器
//-----------------------------------------------
WDCON &=0xE0; //关闭 WDT
RTCH = 0x01; //设置RTC为16bit, 大约8.9ms
RTCL = 0xFF;
RTCCON = 0x63; //启用RTC, 使用内部 RC
EWDRT = 1; //启用 RTC/WD 中断
//-----------------------------------------------
//初始化 T0 用于 PWM
//-----------------------------------------------
TMOD |= 0x02; //Set T0 mode 6
TAMOD |= 0x01; //For PWM, 0x01
TH0 = 255; //Duty cycle = 256 - TH0, for 5v input, set initial charge current very small
AUXR1 |= 0x10; //Enable toggling pin P1.2
TR0 = 1; //Enable T0
//----------------------------------------------------------------------
//Enable the A/D Converter and use the CPU clock as the A/D clock.
//----------------------------------------------------------------------
ADMODA = 0x10; //AD1 single mode no boundary interrupt
ADMODB = 0x40; //AD "40" for CCLK/3, 7.3728/3=2.4576M. "60" for CLK = CCLK/4, 1.8432M, ADC MODE
ADINS = 0xE0; //Enable AD11,AD12,AD13
ADCON1 = 0x04; //Enable AD1 with timer no start occurs mode, no completed & boundary interrupt
}
//***************************************************************************
//* ad_convert()
//* Description : AD转换控制
//***************************************************************************
void ad_convert ()
{
uchar temp = 0;
ADCON1 |= 0x01; //启用AD转换
while( !(ADCON1 & 0x08) ); //等待AD转换结果
ADCON1 &= ~0x08;
if( average-- == 0) // 每隔10S输出一次转换结果,第一判断以下--
{
AD1_1 = AD1_1/10;
AD1_2 = AD1_2/10;
AD1_3 = AD1_3/10;
average = 10;
//-----------------------------------------------
//AD11 用于检测电池电压
//-----------------------------------------------
if( AD1_1 > 176 ) // If Vout > 4.6v
{ // 为防止电池损坏或没插插头
SCL=0;
Battery_On_Socket = 0; // 关闭AD转换, skip <115, <162, <176, until <38
RTC_Counter = 5000; //延时15's, 启动 RTC_Interrupt()
LED_Flash_Speed = LED_FLASH_FAST; // 显示错误状态
}
else if( AD1_1 <= 38 ) // If Vout <= 1V, <=(1/3.31*2)*256 = 256/6.66
{
SCL=0; // p1.2 = 0, 关闭PWM
LED_Flash_Speed = LED_FLASH_FAST; // indicate error status
AD1_1 = 0; // LED关闭
} // 电池损坏或插头没接
else if( AD1_1 <= 115) // 如果电压<=115
{
SCL=1; // 启动 P1.2 PWN
TH0 = 250; //预设充电电流为50V输入,约2A。
LED_Flash_Speed = LED_FLASH_SLOW; // 显示充电状态
if( Constant_Current_Charge == 0 ) Pre_Charge_Status = 1; // Set Precharge status
}
else if( AD1_1 < 162) // 输出电压 = 电池电压 + 0.35*0.75
// for fullly charged bat,bat vol=4.24,I limit 20mA, 4.24+0.02*0.75=4.26v
// 为保护电池, 设置输出电压 = 4.26v (162)
{ // if bat vol=4.2, 仅仅输出 1.5A, 4.2+0.08*0.75=4.26v
// if bat vol=4.15, 我仅仅是2A, 4.15 + 0.15*0.75 = 4.26v
// 为保护电池充电电流,4.26-0.35*0.75=4.00v, so Vbat>4.00v,enter cons-vol
// 第一波充电, charge I= min 20mA,Vbat= 4.26-0.02*0.75=4.24v
// ( 161-4.252, 162-4.267, 160-4.234 )
SCL=1;
LED_Flash_Speed = LED_FLASH_SLOW; // 显示充电状态
if( Constant_Voltage_Charge == 0)
{
Constant_Current_Charge = 1; // 设置为恒流充电
Pre_Charge_Status = 0; // 禁止预充电状态
}
}
else // If 4.26V < Vout <4.6V
{
SCL=1;
LED_Flash_Speed = LED_FLASH_SLOW; // 显示充电状态
Constant_Voltage_Charge = 1; // 为恒压充电状态
Constant_Current_Charge = 0; // 禁止恒流充电
Pre_Charge_Status = 0; // 禁止预充电
}
temp = AD1_1;
AD1_1 = 0; // 重启 AD1_1
//-----------------------------------------------
//AD12 检测温度
//-----------------------------------------------
// AD1_2 = AD1_2*83/64; // input x 3.31 x 100 / 256
// First_Bit = AD1_2/100;
// AD1_2 = AD1_2%100;
// Second_Bit = AD1_2/10;
// Third_Bit = AD1_2%10;
// DP_Enable = 0;
AD1_2 = 0; // reset AD1_2
//-----------------------------------------------
//AD13 检测电流
//-----------------------------------------------
if( Pre_Charge_Status == 1 )
{
if( ( AD1_3 > 1 ) && ( TH0 < 250 ) ) // 确保预充电电流 < 65mA
{ TH0++;}
}
else if( Constant_Current_Charge == 1 )
{
if( AD1_3 < 17 ) // 260mv,(充电电流 = 350mA)
{ // 如果充电电流 < 350mA, pwm++
if( TH0 < 2 )
{
TH0 = 1;
if( RTC_Counter == 0 ) //延时20min结束充电
{ RTC_Counter = 1; } //电池在这种情况下,if Vout < 2.6v
//无法实现电流 350mA, PWM开最大
}
else
{ TH0 = TH0 - 1; }
}
else if( AD1_3 > 17)
{ //如果充电电流 > 350mA, pwm--
if( TH0 > 253 )
{ TH0 = 254; }
else
{
TH0 = TH0 + 1;
}
}
}
else if( Constant_Voltage_Charge == 1 )
{
if( AD1_3 <= 1 ) // 充电电流 < 60mA
{
if( RTC_Counter == 0 ) { RTC_Counter = 1; } //开始延时50分钟结束充电
}
if( temp > 160 ) //temp=AD1_1, if Vout is > 4.23v(达到 4.23v), -- PWM
{
if( TH0 < 255)
{
TH0++;
}
}
else if( temp < 160 ) // if Vout is < 4.21v (达到 4.21v), ++PWM
{
if( TH0 > 1 )
{
TH0--;
}
}
}
AD1_3 = 0; // 重启 AD1_3
}
else
{
AD1_1 += AD1DAT1;
AD1_2 += AD1DAT2;
AD1_3 += AD1DAT3;
}
}
//***************************************************************************
//* RTC_Interrupt
//* Description : RTC 中断
//***************************************************************************
void RTC_Interrupt (void) interrupt 10 using 1
{
if( RTC_Counter != 0 ) { RTC_Counter++; }
{
RTC_Counter_LED++;
RTC_Counter_AD++;
}
if ( RTC_Counter_LED == LED_Flash_Speed)
{
LED_Flag = ~LED_Flag;
RTC_Counter_LED = 0;
}
if ( RTC_Counter_AD == AD_Convert_Speed )
{
AD_Flag = 1;
RTC_Counter_AD = 0;
}
if ( RTC_Counter == 6750) // 延时1分钟
{
RTC_Counter_Minute++;
RTC_Counter = 1;
if( Battery_On_Socket == 0) // 拔掉插座延时15S
{
Battery_On_Socket = 1;
RTC_Counter = 0;
}
}
RTCCON = 0x63; //Clear RTCCON.7-RTCF
}
/*********************************************END***************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -