?? 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 + -