|
電路采用改變PWM占空比達到恒流放電,軟件是很簡單的算法。PROTEUS已仿真(非常卡頓且要過好一陣虛擬示波器才能出波形)。因水平有限電路及軟件這樣設計不知是否正確,尋求意見,若能完善再DIY.
以下是源代碼
#include <reg51.h>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char
#define ulong unsigned long
/**********1602************/
sbit RS=P1^5;
sbit EN=P1^4;
sbit LCD_D4=P1^3;
sbit LCD_D5=P1^2;
sbit LCD_D6=P1^1;
sbit LCD_D7=P1^0;
sbit SW=P3^2;
sbit PWM_OUT=P3^3;
sbit FMQ=P3^7;
/*********ADC0832**********/
sbit CS = P3^4;
sbit CLK = P3^5;
sbit DI0 = P3^1;
sbit WCS = P3^0;
sbit WCLK = P1^6;
sbit WDI0 = P1^7;
//---------------------------
unsigned char Data[8];
unsigned char Table[]="0123456789";
unsigned char hour=0;//小時
unsigned char min=0;//分鐘
unsigned char miao=0;//秒
unsigned char mstn=0;//50ms計數
bit ptt=0;//秒閃爍標志
unsigned long AH=0;
unsigned int num=0;
/********以下是函數聲明********/
void LCD_en_write(void);//液晶使能
void LCD_by(uchar abc);//寫字節
void LCD_set_xy(uchar x, uchar y);//寫地址
void LCD_write_str(uchar X,uchar Y,uchar *s);//寫字符串
void LCD_init(void);//液晶初始化
void del_ms(uint n);//ms延時函數
void delay_5us(void);//5us延時函數
void delay_nus(uint n);//N us延時函數
void process_3(unsigned long i,unsigned char *p) ;
void display_AH(unsigned char x, unsigned char y, unsigned char *p);
void Timer0_Init(void);
void Timer1_Init(void);
void display_SJ(uchar x,uchar y,uchar hour,uchar min);//時間顯示函數
void display_V(unsigned char x, unsigned char y, uchar *p);
void display_A(unsigned char x, unsigned char y, uchar *p);
uchar V_A();//電壓/電流采集函數
uchar SET_A();//電流調節采集函數
//-----------------------------------------
uchar V_A(bit CH)//電壓/電流采集函數
{
uchar i,dat,dat2;
CS=0;
_nop_();
DI0=1;
CLK=1;
_nop_();
CLK=0;
_nop_();
DI0=1;
CLK=1;
_nop_();
CLK=0;
_nop_();
if(CH==0)
{
DI0=0;//V
}
if(CH==1)
{
DI0=1;//A
}
CLK=1;
_nop_();
CLK=0;
DI0=1;
dat=0;
for(i=0;i<8;i++)
{
dat<<=1;
CLK=1;
_nop_();
CLK=0;
_nop_();
dat|=DI0;
}
dat2=0;
if(DI0==1)
dat2=0x80;
for(i=0;i<7;i++)
{
dat2>>=1;
CLK=1;
_nop_();
CLK=0;
_nop_();
if(DI0==1)
dat2|=0x80;
}
CS=1;
CLK=0;
DI0=1;
if(dat==dat2)
return(dat);
else
return 0;
}
//--------------------------
uchar SET_A()//電流調節采集函數
{
uchar i,dat,dat2;
WCS=0;
_nop_();
WDI0=1;
WCLK=1;
_nop_();
WCLK=0;
_nop_();
WDI0=1;
WCLK=1;
_nop_();
WCLK=0;
_nop_();
WDI0=0;//
WCLK=1;
_nop_();
WCLK=0;
WDI0=1;
dat=0;
for(i=0;i<8;i++)
{
dat<<=1;
WCLK=1;
_nop_();
WCLK=0;
_nop_();
dat|=WDI0;
}
dat2=0;
if(WDI0==1)
dat2=0x80;
for(i=0;i<7;i++)
{
dat2>>=1;
WCLK=1;
_nop_();
WCLK=0;
_nop_();
if(WDI0==1)
dat2|=0x80;
}
WCS=1;
WCLK=0;
WDI0=1;
if(dat==dat2)
return(dat);
else
return 0;
}
//--------------------------
void display_SJ(uchar x,uchar y,uchar hour,uchar min)
{
unsigned char q[2];
unsigned char w[2];
q[0]=hour/10;
q[1]=hour%10;
w[0]=min/10;
w[1]=min%10;
LCD_set_xy( x, y );
RS=1;
LCD_by(Table[q[0]]);
LCD_by(Table[q[1]]);
if(ptt==1||SW==1)
{
LCD_write_str(13,0,":");//秒閃爍
}
else
{
LCD_write_str(13,0," ");
}
LCD_by(Table[w[0]]);
LCD_by(Table[w[1]]);
}
//-----------------------------------------
void process_3(unsigned long i,uchar *p)
{
p[0]=i/100%10;
p[1]=i/10%10;
p[2]=i%10;
}
//--------------------------------------------------------
void display_AH(unsigned char x, unsigned char y, uchar *p)
{
unsigned char i;
LCD_set_xy( x, y );
RS=1;
for(i=0;i<3;i++)
{
if(i==2)
{
LCD_write_str(12,1,".");
}
LCD_by(Table[p[i]]);
}
}
//---------------------------------------------
void display_V(unsigned char x, unsigned char y, uchar *p)
{
unsigned char i;
LCD_set_xy( x, y );
RS=1;
for(i=0;i<3;i++)
{
if(i==2)
{
LCD_write_str(3,0,".");
}
LCD_by(Table[p[i]]);
}
}
//---------------------------------------------
void display_A(unsigned char x, unsigned char y, uchar *p)
{
unsigned char i;
LCD_set_xy( x, y );
RS=1;
for(i=0;i<3;i++)
{
if(i==2)
{
LCD_write_str(3,1,".");
}
LCD_by(Table[p[i]]);
}
}
//---------------------------------------------
void LCD_en_write(void)
{
delay_5us();
EN=1;
delay_5us();
EN=0;
}
//---------------------------------------
void LCD_by(uchar abc)
{
delay_nus(500);
if(((abc<<0)&0x80)==0)
LCD_D7=0;
else LCD_D7=1;
if(((abc<<1)&0x80)==0)
LCD_D6=0;
else LCD_D6=1;
if(((abc<<2)&0x80)==0)
LCD_D5=0;
else LCD_D5=1;
if(((abc<<3)&0x80)==0)
LCD_D4=0;
else LCD_D4=1;
LCD_en_write();
if(((abc<<4)&0x80)==0)
LCD_D7=0;
else LCD_D7=1;
if(((abc<<5)&0x80)==0)
LCD_D6=0;
else LCD_D6=1;
if(((abc<<6)&0x80)==0)
LCD_D5=0;
else LCD_D5=1;
if(((abc<<7)&0x80)==0)
LCD_D4=0;
else LCD_D4=1;
LCD_en_write();
}
//----------------------------------------------
void LCD_set_xy( uchar x, uchar y )
{
uchar address;
if (y == 0) address = 0x80 + x;
else
address = 0xc0 + x;
RS=0;
LCD_by(address);
}
//---------------------------------------------
void LCD_write_str(uchar X,uchar Y,uchar *s)
{
LCD_set_xy(X,Y);
RS=1;
while(*s)
{
LCD_by(*s);
s++;
}
}
//------------------------------------
void LCD_init(void)
{
RS=0;
del_ms(500);
LCD_by(0x30);
del_ms(60);
LCD_by(0x30);
del_ms(10);
LCD_by(0x30);
del_ms(10);
LCD_by(0x02);
del_ms(10);
LCD_by(0x28);
del_ms(10);
LCD_by(0x08);
del_ms(10);
LCD_by(0x01);
del_ms(10);
LCD_by(0x06);
del_ms(10);
LCD_by(0x0C);
del_ms(100);
}
//----------------------------------------------
void delay_nus(uint n)//N us延時函數
{
uint i=0;
for (i=0;i<n;i++){;}
}
//------------------------------
void delay_5us(void)//@12.000MHz//5us延時函數
{
unsigned char data i;
_nop_();
_nop_();
i = 12;
while (--i);
}
//------------------------------
void del_ms(uint n)//ms延時函數
{
uchar j;
while(n--)
{for(j=0;j<125;j++);}
}
//------------------------------
void Timer1_Init(void) //50毫秒@12.000MHz
{
TMOD &= 0x0F;
TL1 = 0xB0;
TH1 = 0x3C;
TF1 = 0;
}
//-------------------------------
void Timer0_Init(void) //4微秒@12.000MHz
{
TMOD &= 0xF0;
TL0 = 0xFC;
TH0 = 0xFF;
TF0 = 0;
}
//-------------------------------
void timer1(void) interrupt 3
{
TL1 = 0xB0;
TH1 = 0x3C;
TF1 = 0;
mstn++;
if(mstn==20)
{
mstn=0;
miao++;
ptt=~ptt;
if(miao==60)
{
miao=0;
min++;
if(min==60)
{
min=0;
hour++;
if(hour==100)
{
hour=100;
}
}
}
}
}
//-------------------------------
void timer0(void) interrupt 1
{
static unsigned char count=0;
TL0 = 0xFC; //4us
TH0 = 0xFF;
TF0=0;
count++;
if(count>=255)count=0;//4us*255=1020us
if(count>=num)PWM_OUT=1;//改變占空比
else PWM_OUT=0;//調整電流
}
//-------------------------------
void main(void)
{
uchar Set_A=0;
uchar Batt_A=0;
uchar Batt_V=0;
uchar A_A=0;
uchar V_V=0;
ulong AH=0;
LCD_init();
del_ms(10);
Timer0_Init();
del_ms(10);
Timer1_Init();
del_ms(10);
FMQ=1;
PWM_OUT=1;
ET0=1;
ET1=1;
EA=1;
while(1)
{
Set_A=SET_A();//電流調節
V_V=V_A(0);
Batt_V=V_V*200./255;//電池電壓
A_A=V_A(1);
Batt_A=A_A*200./255;//放電電流
if(SW==1)//停止
{
TR0=0;
TR1=0;
PWM_OUT=1;//放電MOS管截止
}
if(SW==0)//開始
{
TR0=1;
TR1=1;
num=num+(Set_A-A_A)/2;//恒流放電
}
if(V_V<=108)//12V電池放電截止
{
// while(1)//加上這段仿真會停止
// {
// TR0=0;
// TR1=0;
// PWM_OUT=1;
// FMQ=0;//蜂鳴器響
// }
}
AH=hour*60+min;//放電容量計算
AH*=Batt_A;
AH/=60;
display_SJ(11,0,hour,min);//時間
process_3(AH,Data);
display_AH(10,1,Data);//容量
LCD_write_str(14,1,"AH");
process_3(Batt_V,Data);
display_V(1,0,Data);//電壓
LCD_write_str(5,0,"V");
process_3(Batt_A,Data);
display_A(1,1,Data);//電流
LCD_write_str(5,1,"A");
}
}
|
|