📄 main.c
字号:
/******************************************************************************
* name: main.c
* project: 智能充电器
* author: fengzai(panda)
* date: 2007.1.14 (2007.1.30修改版本)
*
* 感谢ouravr一直以来对我提供的帮助,感谢论坛上的朋友。
* 特别向 armork 章其波bozai sunw2004 表示感谢,谢谢你们不厌其烦的回答我的提问。
* 功能描述:
* 自动判断电池状态,对空电池进行预放电,250ma预充电,800ma快充电,
*
* <1 当温度* 参数呈现上升趋势的时候,大概是每分钟上升1度的速率(跟充电电流有关),
* 则判断停止PWM
* 2 当电池电压* 参数呈现下降趋势的时候,大概是5mv/cell(必须是快速充电),则判断停止
* PWM
* 3 进行你快充时间1倍或则2倍的涓流充电定时.涓流=快充电流/30当温度> sunw2004.
*
* 参数呈现下降趋势的时候,停止充电,进行15分钟的涓流充电。
* 其中的各项参数可以在头文件里修改。
* 具有自动保护功能。
* 温度测量采用芝浦热敏电阻,电路连接见temp.h头文件。
* 暂时未设计人机界面,打算用个8字LED,后续版本推出。
*
* 特别说明:这是本人第一个GCC项目,很多地方很不成熟,充电器的各项充电参数也是
* 想当然的,没有经过严格的测试。我的实验电池为600ma 7号GP充电电池,可能代表性
* 也不强。我会逐步完善代码。敬请各位大虾指出问题所在,谢谢!
*
* 全部代码遵循GPL
* 枫 仔fengzai martin7wind martin7wind@163.com
* 2007.1.28
******************************************************************************/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "i_output.h"
#include "adc.h"
#include "usart.h"
#include "temp.h"
#include "time.h"
#include "main.h"
#define uchar unsigned char
#define uint unsigned int
#define BIT(x) (1<<(x))
#define NOP() asm("nop")
#define WDR() asm("wdr")
uint time_t=0;
volatile uint time=0; //全局变量,定义系统时钟
volatile uint detect_dt_time=0; //全局变量,用来判断合适检测温度
volatile uint purling_time=0; //标志开始涓流充电的时间
volatile uchar purling_status=1;
volatile uchar work_status=2; //全局变量,定义系统工作状态
volatile uint dt = 10; //温度上升幅度
volatile uint dv = 10;
volatile uchar current_status = CURRENT_WAIT; //充电标志,描述电流是否调整完毕
uint c_current; //充电电流
uint b_vol; //电池电压
uint b_vol_pre;
uint b_temp; //电池温度
uint b_temp_pre = 0; //用来计算温度变化的量
/*------------------------------------------------------------------------------
* 系统时钟程序,OK!
*-----------------------------------------------------------------------------*/
//T2溢出中断服务程序
//#pragma interrupt_handler timer2_ovf_isr:6
//void timer2_ovf_isr(void)
SIGNAL(SIG_OVERFLOW2)
{
TCNT2 = 0x28;
time_t++;
if(time_t==100)
{
time++;
detect_dt_time++;
time_t=0;
}
TCCR2 = 0x07;//启动定时器
}
//端口初始化
void port_init(void)
{
PORTA = 0x00;
DDRA = 0x00; //DDRA = 0b00000000
PORTB = 0x00;
DDRB = 0x00;
PORTC = 0x00;
DDRC = 0x00;
PORTD = 0x22; //PORTD = 0x00000010
DDRD = 0xa2; //DDRD = 0x10000010
}
void init_devices(void)
{
cli(); //禁止所有中断
MCUCR = 0x00;
MCUCSR = 0x80;//禁止JTAG
GICR = 0x00;
port_init();
timer1_init();
timer2_init();
usart_init();
sei();//开全局中断
}
/*------------------------------------------------------------------------------
* 测量模块,测量系统各参数,
*-----------------------------------------------------------------------------*/
void system_test(void)
{
if (work_status==WORK_DISCHARGE)
STOP_DISCHARGE;
_delay_ms(100);
c_current = charge_current(); //充电电流
b_vol = battery_vol(); //电池电压
b_temp = temp();
put_s("I:"); //分别测出电流、电压、温度
send_int(c_current);
put_s("V:");
send_int(b_vol);
put_s("T:");
send_int(b_temp);
put_s("Time:");
send_int(time);
if (work_status==WORK_DISCHARGE)
START_DISCHARGE;
_delay_ms(100);
}
/*------------------------------------------------------------------------------
* 测量dt,即温度变化的曲线,每2分钟检测一次dt
*-----------------------------------------------------------------------------*/
void detect_dt(void)
{
if(detect_dt_time>=40)
{
detect_dt_time = 0;
dt = b_temp - b_temp_pre;
b_temp_pre = b_temp;
put_s("dt=\n");
send_int(dt);
}
}
/*------------------------------------------------------------------------------
* 测量dv,
*-----------------------------------------------------------------------------*/
void detect_dv(void)
{
if(detect_dt_time>=40)
{
detect_dt_time = 0;
dv = b_vol - b_vol_pre;
b_vol_pre = b_vol;
put_s("dv=\n");
send_int(dv);
}
}
/*------------------------------------------------------------------------------
* 第一次决定充电工作状态
* TOP_CHARGE_VOL 1350
* NORMAL_CHARGE_VOL 1300
* START_DISCHARGE_VOL 1200
* STOP_DISCHARGE_VOL 1000
*------------------------------------------------------------------------------*/
void pre_choose_work(void)
{
if( b_vol > TOP_CHARGE_VOL )
{
work_status = WORK_FULL; //电压大于极限电压,表示电池本来就是满的。
put_s("Battery is Full!");
}
if( b_vol > NORMAL_CHARGE_VOL && b_vol <= TOP_CHARGE_VOL ) //是否进行涓流充电
{
work_status = WORK_PURLING;
put_s("Purling Charge!\n");
}
if( b_vol > START_DISCHARGE_VOL && b_vol <= NORMAL_CHARGE_VOL) //是否直接进入正常充电
{
work_status = WORK_CHARGE;
put_s("Charging!\n");
}
if( b_vol > STOP_DISCHARGE_VOL && b_vol <= START_DISCHARGE_VOL ) //放入电池,如果小于设定值,进入放电状态
{
work_status = WORK_DISCHARGE;
put_s("Start Discharge!\n");
}
if( b_vol > EMPTY_VOL && b_vol < STOP_DISCHARGE_VOL ) //电池小于空电压,直接进入充电状态
{
work_status = WORK_PRE_CHARGE;
put_s("Start PreCharge!\n");
}
if( b_vol <= EMPTY_VOL ) //电池小于最低电压,认为没有电池存在或电池已损坏
{
work_status = WORK_EMPTY;
put_sput_s("No Battery In!\n");
}
}
/*------------------------------------------------------------------------------
* 保护函数,当电压过高,温度过高,充电时间过长时,自动停止一切动作
*------------------------------------------------------------------------------*/
void protect(void)
{
/* while( (b_vol > DANGER_VOL) || (b_temp > DANGER_T) || (time > MAX_TIME) )*/
//put_s("protecting!\n");
if ( b_temp > DANGER_T )
{
put_s("The temprature is too high! Stop charging!\n");
work_status = WORK_ERROR;
}
if ( time > MAX_TIME )
{
put_s("The charging is too long! Stop charging1\n");
work_status = WORK_ERROR;
}
if ( b_vol > DANGER_VOL )
{
put_s("The voltage is too high! Stop Charging!\n");
work_status = WORK_ERROR;
}
}
int main()
{
init_devices();
put_s("ok!\n");
pwm_output(1000);
//current_control(0);
//STOP_DISCHARGE;
put_s("Battery Detecting......\n");
system_test();
put_s("Battery Voltage is:");
send_int(b_vol);
pre_choose_work();
//START_DISCHARGE;
put_c(work_status+48);
put_c('\n');
while(1)
{
_delay_ms(60000);
system_test();
protect();
//_delay_ms(1000);
//put_c(work_status+48);
//put_c('\n');
//put_s("start dt!\n");
detect_dt(); //第一次结果舍弃
//detect_dt();
// put_s("?\n");
//put_c(work_status+48);
switch(work_status)
{
case WORK_ERROR: //错误状态,停止充电,停止放电,报错
{
//current_control(1);
STOP_DISCHARGE;
if (b_vol > EMPTY_VOL)
pre_choose_work();
put_s("Error!\n");
}break;
case WORK_EMPTY: //没有电池,停止放电
{
STOP_DISCHARGE;
//current_control(1); 错误所在,没有电池,电流肯定是0
put_s("No Battery!\n");
if (b_vol < EMPTY_VOL)
pre_choose_work();
}break;
case WORK_DISCHARGE: //放电态,检查是否达到停止放电的程度
{
put_s("Discharging!\n");
pwm_output(1023); //关闭充电电流
START_DISCHARGE;
_delay_ms(60000);
_delay_ms(60000);
_delay_ms(60000);
_delay_ms(60000);
_delay_ms(60000);
_delay_ms(60000);
if ( b_vol < STOP_DISCHARGE_VOL && b_vol > EMPTY_VOL )
{
STOP_DISCHARGE;
work_status = WORK_PRE_CHARGE;
}
if ( b_vol <= EMPTY_VOL )
{
STOP_DISCHARGE;
work_status = WORK_EMPTY;
put_s("No Battery In!");
}
}break;
case WORK_PRE_CHARGE: //预充电态,当电池达到1300mv时,开始快充
{
STOP_DISCHARGE;
put_s("preCharging!\n");
while(current_status)
{
current_control(PRE_CHARGE_CURRENT);
current_status = CURRENT_OK;
}
if ( b_vol >= NORMAL_CHARGE_VOL )
{
work_status = WORK_CHARGE;
current_status = CURRENT_WAIT;
}
if( b_vol < EMPTY_VOL )
{
current_control(1);
work_status = WORK_EMPTY;
put_s("No Battery!\n");
}
}break;
case WORK_CHARGE: //快速充电状态,默认充电电流800MA,2007.1.30修正
{
STOP_DISCHARGE;
put_s("Normal Charging!\n");
while(current_status)
{
current_control(CHARGE_CURRENT);
current_status = CURRENT_OK;
}
if( dt >= STOP_CHARGE_DT ) //温度上升达到1分钟1度,2007.1.30修正
{
pwm_output(1023); //关闭电流
work_status = WORK_PURLING;
current_status = CURRENT_WAIT;
}
if( dv <= STOP_CHARGE_DV ) //电压呈下降趋势 2007.1.30 修正
{
pwm_output(1023); //关闭电流
work_status = WORK_PURLING;
current_status = CURRENT_WAIT;
}
if( b_vol < EMPTY_VOL )
{
pwm_output(1023); //关闭电流
work_status = WORK_EMPTY;
put_s("No Battery!\n");
}
}break;
case WORK_PURLING: //涓流充电,大约持续10分钟就充满电池了,OK!
{
STOP_DISCHARGE;
uint dtime;
while(purling_status)
{
purling_status = 0;
purling_time = time;
}
put_s("Purling Charging!\n");
pwm_output(1023); //关闭电流
_delay_ms(PURLING_DELAY);
purling_current_control(PURLING_CURRENT);
dtime = time;
dtime -= purling_time;
send_int(dtime);
if( dtime >= PURLING_TIME )
{
work_status = WORK_FULL;
current_control(1); //涓流充电完成,关闭电流
purling_status = 1;
}
if( b_vol < EMPTY_VOL )
{
current_control(1);
work_status = WORK_EMPTY;
put_s("No Battery!\n");
}
}break;
case WORK_FULL: //电池已经满的状态。OK!
{
put_s("The Battery is Full!\n");
system_test();
if( b_vol < EMPTY_VOL )
{
work_status = WORK_EMPTY;
put_s("No Battery!\n");
}
}break;
}
}
}
/*------------------------------------------------------------------------------
* end of file
*-----------------------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -