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

📄 main.c

📁 充电器源代码 才有AVR CPU 控制 可以对大部分电池充电
💻 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 + -