📄 chongdian0418.c
字号:
#include <reg52.h> // 充电选择
#include <absacc.h>
#include <intrins.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#define DAC0832 XBYTE[0xfeff] /* 定义DAC0832端口地址 */
#define samples 10 //采样点数6--100?:根据试验结果选择合适数值
//电压电流数据采集位定义
sbit AD_CLK = P1^1; //TLC2543
sbit DIN = P1^2;
sbit DOUT = P1^3;
sbit AD_CS = P1^4;
sbit EOC = P1^0;
sbit FlagYa = P3^2; //D3 恒压
sbit FlagLiu = P3^3; //D2 恒流
sbit chongstyle = P3^4; //充电方式
unsigned char bdata flag;
sbit hengliu =flag^0; //恒流充
sbit hengya =flag^1; //恒压充
sbit fuchongFlag =flag^2; //浮充
sbit kuaichong =flag^3;
sbit nonect =flag^4;
float voltage; //最终显示或控制用电压值
float current; //最终显示或控制用电流值
unsigned int count=0; //过渡计数
unsigned int v[samples],c[samples]; //采样保存点
extern void delay(unsigned int);
unsigned int ADRead(unsigned char);
void dac(unsigned char);
unsigned char AV=0; //调节电压控制值
float maxck=50.0; //快充方式:恒流阶段充电,最大电流值:根据需要修改
float maxcp=30.0; //普通方式:恒流阶段充电,最大电流值:根据需要修改
float maxc; //实际恒流阶段充电最大电流值=maxck或者maxcp
float maxv=59.1; //最高充电电压:和电池特性有关
float ra=0.217,rc=0.0305; // 采样系数
float difc=0.31,difv=0.21; //==电流电压允许波动范围
unsigned char pos=0; //==当前先进先出FIFO的位置
unsigned int ncount=0,nstop=0; //==几个计数器
unsigned int getv(void) //==采样电压值
{ ADRead(0x00);
return ADRead(0x00); }
unsigned int getc(void) //==采样电流值
{ ADRead(0x20);
return ADRead(0x20); }
void dispnocont(void) //显示开路状态:灯交替闪烁
{ ncount=ncount+1; //交替闪烁计数器
nonect=1; //必须重新上电,才能开始工作
AV=0;
dac(AV); //关断IGBT
if ((ncount % 50) < 25 ) //大约一秒的周期: 点亮恒压灯D3,恒流灯D2灭
{ FlagYa=0; FlagLiu=1; }
else
{ FlagYa=1; FlagLiu=0; }
}
void getac(void) //==采样,并处理数据
{ unsigned char i;
v[pos]=getv();
delay(1);
c[pos]=getc();
delay(1); //==采样一个周期,约2毫秒
pos++;
if (pos>=samples) pos=0;
voltage=0;
current=0;
for(i=0; i<samples; i++)
{ voltage=voltage+v[i];
current=current+c[i];
}
voltage=voltage/samples; //==取平均值
current=current/samples;
voltage=voltage*ra;
current=current*rc;
}
/******************************************
1、先以maxc电流恒流充电,充到maxv,再恒压充
2、9脚:补偿端工作电压范围为1.5V到5.2V。
*******************************************/
main()
{ unsigned char n;
P1=0xff;
P2=0xff;
P3=0xff;
chongstyle=1; //P0=0xff;
hengliu=1;
hengya=0; //==首先为恒流充电
fuchongFlag=0;
nonect=0; //==开路标志
AV=80; //==输出初始电压值
dac(AV);
delay(1);
dac(AV);
delay(100); //==稍延时,等待电路稳定?
/*************阶段一:开机10A过渡********************/
for(n=0;n<200;n++) //开机10A过渡
{ getac(); //==采样
nstop=nstop+1;
if (nstop>150) //==稍延时后再判断开路处理
if ((current<0.4) || nonect) //==开路处理:灯交替闪烁?
{ dispnocont(); //显示开路状态:灯交替闪烁
continue; //循环继续!
} // end of nonect
if(voltage>maxv) //maxv为蓄电池的最高安全充电电压,如超过,须降压处理
{ FlagYa=0; //点亮恒压灯D3
FlagLiu=1;
if(AV>4) { AV=AV-4; dac(AV); }
}
else //恒流充电
{ FlagLiu=0; //点亮恒流灯D2
FlagYa=1;
if(current<10.0) //==电流小,加大
{ if(AV<255) { AV=AV+1; dac(AV); } }
if(current>10.0) //==电流大,减小
{ if(AV>4) { AV=AV-4; dac(AV); } }
}
delay(30);
} // end of for n
/*************阶段二:正常恒流充电过程 ******************/
while(1)
{ getac(); //==采样
kuaichong=chongstyle;
if(kuaichong) maxc=maxck; /****** 快速充电处理过程 ******/
else maxc=maxcp; /****** 普通充电处理过程 ******/
if ((current<0.4) || nonect) //==开路处理:灯交替闪烁?
{ dispnocont();
continue; //==循环继续!实际上,必须重新上电才能工作,因为IGBT关断了
} // end of nonect
if(voltage>maxv) //==首先判断安全电压
{ if(count<0xfffe) count++; //==通过试验确定逼近恒压的计数值
else { hengya=1; break; } //==进入恒压充电状态标志,跳出恒流充电过程!
FlagYa=0; //点亮恒压灯D3
if(voltage>(maxv+difv)) //=超压处理
{ if(AV>1) { AV=AV-1; dac(AV); } }
} //== end of 判断安全电压
else //===恒流充电处理过程
{ FlagLiu=0; //点亮恒流灯D2
FlagYa=1;
if(current<(maxc-difc)) //==判断恒流电流:偏小
{ if(AV<255) { AV=AV+1; dac(AV); } }
if(current>(maxc+difc)) //==电流偏大
{ if(AV>1) { AV=AV-1; dac(AV); } }
} //==end of else
delay(30); //==适当延时:控制循环周期
} // end of while
/*************阶段三:正常恒压和浮充电过程 ******************/
while(hengya)
{ getac(); //==采样
if ((current<0.4) || nonect) //==开路处理:灯交替闪烁?
{ dispnocont();
continue; //==循环继续!实际上,必须重新上电才能工作,因为IGBT关断了
} // end of nonect
FlagYa=0; //点亮恒压灯D3
FlagLiu=1;
if(voltage<maxv) // maxv-difv ?
{ if(AV<255) { AV=AV+1; dac(AV); } }
if(voltage>(maxv+difv))
{ if(AV>1) { AV=AV-1; dac(AV); } }
delay(30); //==适当延时:控制循环周期
} //==end of while
} //==主程序结束
unsigned int ADRead(unsigned char channel) //channel=0x00,选择0通道;channel=0x10,选择1通道。返回结果为整型变量DATA,里面
{
unsigned int ad_regist=0;
unsigned char i;
AD_CLK = 0;
AD_CS=1;
_nop_(); //存的为AD转换结果,格式为D11~D0,共12位
AD_CS=0;
_nop_();
_nop_();
for(i=0;i<8;i++)
{
ad_regist=_irol_(ad_regist,1);
ad_regist|=DOUT;
DIN=channel&0x80;
channel=_crol_(channel,1);
AD_CLK = 1; //先读取AD的'D11,D10,D9。。。D4'高8位
AD_CLK = 0;
}
for(i=0;i<4;i++)
{
ad_regist=_irol_(ad_regist,1);
ad_regist|=DOUT;
AD_CLK = 1; //先读取AD的'D11,D10,D9。。。D4'高8位
AD_CLK = 0;
} //后读取AD的'D3,D2,D1,D0'低4位
AD_CS=1;
return ad_regist;
}
void dac(unsigned char AdjVoltage)
{
DAC0832=AdjVoltage;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -