- 方案论证与选取
- 理论分析与参数计算
- 电路与程序设计
- 测试方案与测试结果
- 条件:U2=30V,实现电池恒流充电。要求:I1在1~2A范围可调,步进值不大于0.1A,电流控制精度不低于5%。
设定值
|
万用表示数
|
精度
|
1
|
1.005
|
0.500%
|
1.1
|
1.102
|
0.182%
|
1.2
|
1.206
|
0.500%
|
1.3
|
1.305
|
0.385%
|
1.4
|
1.406
|
0.429%
|
1.5
|
1.487
|
-0.867%
|
1.6
|
1.606
|
0.375%
|
1.7
|
1.709
|
0.529%
|
1.8
|
1.805
|
0.278%
|
1.9
|
1.904
|
0.211%
|
2.0
|
2.014
|
0.700%
|
- 条件:I1=2A,调整直流稳压电源输出电压。要求:U2在24~36V范围变化时,充电电流I1的变化率不大于1%。
U2
|
I1
|
电流变化率
|
24
|
2.012
|
0.049%
|
30.99
|
2.012
| |
36.09
|
2.013
|
- 条件:I1=2A,U2=30V。要求:变换器的效率η≥90%。
U1
|
I1
|
U2
|
I2
|
效率
|
19.69
|
2.012
|
29.94
|
1.393
|
94.9884%
|
- 条件:单片机显示充电电流I1。要求:I1=1~2A范围内测量精度不低于2%。
万用表
|
单片机
|
误差百分比
|
1.012
|
1
|
1.200%
|
1.115
|
1.1
|
1.364%
|
1.213
|
1.2
|
1.083%
|
1.309
|
1.3
|
0.692%
|
1.408
|
1.4
|
0.571%
|
1.512
|
1.5
|
0.800%
|
1.61
|
1.6
|
0.625%
|
1.72
|
1.71
|
0.585%
|
1.815
|
1.8
|
0.833%
|
1.918
|
1.91
|
0.419%
|
2.021
|
2.06
|
-1.893%
|
- 条件:断开S1,接通S2,将装置设定为放电模式,保持U2=30±0.5V。要求:变换器效率η≥95%。
U1
|
I1
|
U2
|
I2
|
效率
|
20.81
|
1.493
|
30.01
|
0.994
|
96.0109%
|
- 参考文献
- 附件
序 号
|
名称、型号及规格
|
主要技术指标
|
数 量
|
备 注
|
1
|
数字万用表vc980+
|
直流电压:200mV/2V/20V/200 V /1000V——±(0.05%+3)
直流电流:200uA/2mA/20mA/ 200mA/20A——±(0.5%+4)
交流电压:200mV/2V/20V/200 V/750V——±(0.8%+25)
交流电流:200mA/20A—— ±(1.5%+25)
|
4
| |
2
|
Tektronix双通道数字存储示波器
|
200MHz 2GS/S
|
1
|
|
3
|
Lecroy waveRunner 104mxi数字示波器
|
1GHz Oscilloscope 10GS/S
|
1
|
力科
|
4
|
IT8516B可编程直流电子负载
|
500V/120A/2400W
|
1
|
ITECH
|
5
|
IT6164S直流可编程电源
|
60V*20A
|
1
|
ITECH
|
6
|
高精度实验室电源PS 8000 3U
|
0…500V/0…30A/0…5000W
|
1
|
EA
|
7
|
红外测温仪
|
输出<1mW,波长630-670nm
|
1
|
|
8
|
HP34411A六位半数字万用表
|
|
1
|
安捷伦
|
DSPICFJ256GP710单片机源程序如下:
#include "p33FJ256GP710.h"
#include<math.h>
#include "Delay.h"
#include "InitCPU.h"
#include "LCD12864.h"
#include "ADC.h"
#include "KEY.h"
#include "PWM.h"
#include "DS18B20.h"
#define uint unsigned int
#define uchar unsigned char
#define ulint unsigned long int
#define KeyPort PORTE
/*********变量定义***********/
unsigned char KEY_Receive =0; //按键扫描结果存储
unsigned int cls=0; //清屏指示
unsigned char switchover =0; //换屏
unsigned int Duty_one =0,Duty_two=0; //占空比寄存器
unsigned int I_Set_One =15000; //1模块和2模块设定电流值(调光)
unsigned int count =0,start=0,start1=0; //
unsigned char test =0; //按键加减寄存器(test =1加;test=2减)
unsigned char BUCK=0,BOOST=0; //采集100次标志位
/********************状态标志位************************/
unsigned char Menu =1; //主菜单标志位
unsigned char Menu_A =0; //一级菜单A(状态A)
unsigned char Menu_B =0;
unsigned char Menu_C =0; //一级菜单B(状态B)
unsigned char Cursor =1; //光标状态标志位
unsigned char stateA =0; //A状态标志位(区分正常模式还是过流保护)
unsigned char stateB =0; //B状态标志位
unsigned char stateC =0;
float RE_Ui=0,RE_Uo=0,RE_Ii=0,RE_Io=0;
float RE_Ui_all=0,RE_Uo_all=0,RE_Ii_all=0,RE_Io_all=0;
float Ui_ave=0,Uo_ave=0,Ii_ave=0,Io_ave=0;
float Ui=0,Uo=0,Ii=0,Io=0;
float GETTEMP;
float POWER_factor=0;
unsigned char KeyScan();
void main()
{/*****初始化*****/
InitCPU();
InitLCD();
Init_ADC();
Init_PWM();
Init_DS18B20();
_TRISF2=0;//蜂鸣器输出
_TRISD1=0;
_TRISD2=0;
Clear_lcd();
DelayMs(10);
DISPLAY_stri(0 ,0 , "模式选择: ");
DISPLAY_stri(0,1,"->1.充电模块");
DISPLAY_stri(0,2," 2.放电模块");
DISPLAY_stri(0,3," 3.自动模块");
writ_com(0x0F);
writ_com(0x90);
while(1)
{
KEY_Receive=KeyScan();
switch ( KEY_Receive )
{
case 1: //光标向下移动(+)
{
test =1; //按键寄存器,加
if(Menu==1)
{ test=0;
Cursor ++;
Cursor=Cursor>=4?1:Cursor;
if( Cursor ==1 )
{
DISPLAY_stri(0 ,1 , "->1.充电模块");
DISPLAY_stri(0 ,2 , " 2.放电模块");
DISPLAY_stri(0 ,3 , " 3.自动模块");
writ_com(0x90); //光标显示在第一行
}
if( Cursor ==2 )
{DISPLAY_stri(0 ,1 , " 1.充电模块");
DISPLAY_stri(0 ,2 , "->2.放电模块");
DISPLAY_stri(0 ,3 , " 3.自动模块");
writ_com(0x88); //光标显示在第二行
}
if( Cursor ==3 )
{DISPLAY_stri(0 ,1 , " 1.充电模块");
DISPLAY_stri(0 ,2 , " 2.放电模块");
DISPLAY_stri(0 ,3 , "->3.自动模块");
writ_com(0x98);//光标显示在第二行
}
}
break;
}
case 2:
{
//菜单光标,显示2行
test =2; //按键寄存器,减
if( Menu ==1)
{ test=0;
Cursor --;
Cursor=Cursor==0?3:Cursor;
if( Cursor ==1 )
{
DISPLAY_stri(0 ,1 , "->1.充电模块");
DISPLAY_stri(0 ,2 , " 2.放电模块");
DISPLAY_stri(0 ,3 , " 3.自动模块");
writ_com(0x90); //光标显示在第一行
}
if( Cursor ==2 )
{
DISPLAY_stri(0 ,1 , " 1.充电模块");
DISPLAY_stri(0 ,2 , "->2.放电模块");
DISPLAY_stri(0 ,3 , " 3.自动模块");
writ_com(0x88); //光标显示在第二行
}
if( Cursor ==3 )
{ DISPLAY_stri(0 ,1 , " 1.充电模块");
DISPLAY_stri(0 ,2 , " 2.放电模块");
DISPLAY_stri(0 ,3 , "->3.自动模块");
writ_com(0x98); //光标显示在第二行
}
}
break;
}
case 3: //(确定键,进入子状态(执行状态)
{
switchover =~switchover;
cls=1;
if( ( Menu * Cursor ) ==1 ) //BUCK模式
{
_TRISD1=0;
_TRISD2=0;
Menu_A =1;
Menu_B =0;
Menu_C =0;
Menu =0;
stateA=1;
stateB=0;
stateC=0;
OC3CONbits.OCM=0B110;
OC2CONbits.OCM=0B110;
Duty_one=10; //PWM设置one进行BUCK——PWM调整,two关断
Duty_two=0;
T2CONbits.TON=1;
writ_com(0x0C); //关闭游标和游标位置
Clear_lcd();
}
if( ( Menu * Cursor ) ==2 )//BOOST模式
{
_TRISD2=0;
_TRISD1=0;
Menu_A =0;
Menu_B =1;
Menu_C =0;
Menu =0;
stateA=0;
stateB=1;
stateC=0;
OC3CONbits.OCM=0B110;
OC2CONbits.OCM=0B110;
Duty_one=0; PWM设置two进行BUCK——PWM调整,one关断
Duty_two=10;
T2CONbits.TON=1;
writ_com(0x0C); //关闭游标和游标位置
Clear_lcd();
}
if( ( Menu * Cursor ) ==3 )//自动模式
{
_TRISD2=0;
_TRISD1=0;
Menu_A =0;
Menu_B =0;
Menu_C =1;
Menu =0;
stateA=0;
stateB=0;
stateC=1;
OC3CONbits.OCM=0B000;
OC2CONbits.OCM=0B000;
BUCK=0;
BOOST=0;
Duty_one=0; //PWM设置,刚开始用BUCK
Duty_two=0;
T2CONbits.TON=0;
writ_com(0x0C); //关闭游标和游标位置
Clear_lcd();
}
break;
}
case 4:
{
if( Menu_A ==1 )
{
Menu_A =0;
Menu_B =0;
Menu_C =0;
Menu =1;
Cursor =1;
stateA=0;
stateB=0;
stateC=0;
start=0;
OC3RS=0;
OC2RS=0;
OC3CONbits.OCM=0B000;
OC2CONbits.OCM=0B000;
_LATD2=0;
_LATD1=0;
_LATF2=0;
T2CONbits.TON=0;
I_Set_One=15000;
Clear_lcd();
DelayMs(10);
DISPLAY_stri(0 ,0 , "模式选择: ");
DISPLAY_stri(0 ,1 , "->1.充电模块");
DISPLAY_stri(0 ,2 , " 2.放电模块");
DISPLAY_stri(0 ,3 , " 3.自动模块");
writ_com(0x90);
writ_com(0x0F);
}
if( Menu_B ==1 )
{
Menu_A =0;
Menu_B =0;
Menu_C =0;
Menu =1;
Cursor =1;
stateA=0;
stateB=0;
stateC=0;
OC3RS=0;
OC2RS=0;
start1=0;
OC3CONbits.OCM=0B000;
OC2CONbits.OCM=0B000;
_LATD2=0;
_LATD1=0;
T2CONbits.TON=0;
Clear_lcd();
DelayMs(10);
DISPLAY_stri(0 ,0 , "模式选择: ");
DISPLAY_stri(0 ,1 , "->1.充电模块");
DISPLAY_stri(0 ,2 , " 2.放电模块");
DISPLAY_stri(0 ,3 , " 3.自动模块");
writ_com(0x90);
writ_com(0x0F);
}
if( Menu_C ==1 )
{
Menu_A =0;
Menu_B =0;
Menu_C =0;
Menu=1;
Cursor=1;
stateA=0;
stateB=0;
stateC=0;
OC3RS=0;
OC2RS=0;
_LATD2=0;
_LATD1=0;
OC3CONbits.OCM=0B000;
OC2CONbits.OCM=0B000;
T2CONbits.TON=0;
Clear_lcd();
DelayMs(10);
DISPLAY_stri(0 ,0 , "模式选择: ");
DISPLAY_stri(0 ,1 , "->1.充电模块");
DISPLAY_stri(0 ,2 , " 2.放电模块");
DISPLAY_stri(0 ,3 , " 3.自动模块");
writ_com(0x90);
writ_com(0x0F);
}
break;
}
default :break;
}
switch (stateA)//充电模式
{
case 1: //采集电压电流
RE_Ui=filter(0);
RE_Ii=filter(1);
RE_Uo=filter(2);
RE_Io=filter(3);
Ui=(RE_Ui/1.023)*38.74;
Ii=((RE_Ii/1023)*2980-2082)*10000/418;
Uo=(RE_Uo/1.023)*25.33;
Io=((RE_Io/1023)*2980-2063)*10000/417;
// POWER_factor=Ui
start++;
I_Set_One=test==1?I_Set_One+1000:I_Set_One;
I_Set_One=test==2?I_Set_One-1000:I_Set_One;
I_Set_One=I_Set_One>20000?10000:I_Set_One;
I_Set_One=I_Set_One<10000?20000:I_Set_One;
test=0;
if(Io>=I_Set_One)
{
Duty_one=Duty_one<=10?700:Duty_one-1;
}
else
{
Duty_one=Duty_one>=1300?700:Duty_one+1;
}
if(Uo>=24000) //过压保护
{
DelayMs(2000);
if(Uo>=24000)
{
_LATF2=1;
T2CONbits.TON=0;
OC3CONbits.OCM=0B000;
OC2CONbits.OCM=0B000;
_LATD2=0;
_LATD1=0;
}
}
if(switchover) //翻页显示
{
if(cls==1)
{
Clear_lcd();
DelayMs(10);
}
cls=0;
DISPLAY_stri(0,0,"输入Ui:");
DISPLAY_stri(4,0,ADC_deal_U(Ui));
DISPLAY_stri(0,1,"输入Ii:");
DISPLAY_stri(4,1,ADC_deal_I_1(Ii));
DISPLAY_stri(0,2,"输出Uo:");
DISPLAY_stri(4,2,ADC_deal_U(Uo));
DISPLAY_stri(0,3,"输出Io:");
if(start==50)
{start=0;
GETTEMP=GETTEMP_DS18B20();
DISPLAY_stri(4,3,ADC_deal_I_1(Io));
}
}
if(!switchover)
{
if(cls==1)
{
Clear_lcd();
DelayMs(10);
}
cls=0;
DISPLAY_stri(0,1,"I_set : ");
DISPLAY_stri(4,1,ADC_deal_I_1(I_Set_One));
DISPLAY_stri(0,0,"T: ");
DISPLAY_stri(4,0,ADC_deal_U(GETTEMP*100));
DISPLAY_stri(0,2,"I_fact:");
if(start==50)
{
start=0;
GETTEMP=GETTEMP_DS18B20();
DISPLAY_stri(4,2,ADC_deal_I_1(Io));
}
}
stateA=1;
break;
default :break;
}
switch (stateB)//放电模式
{
case 1: //采集电压电流
RE_Ui=filter(0);
RE_Ii=filter(1);
RE_Uo=filter(2);
RE_Io=filter(3);
Ui=(RE_Ui/1.023)*38.74;
Ii=(2082-(RE_Ii/1023)*2980)*10000/418;
Uo=(RE_Uo/1.023)*25.33;
Io=(2079-(RE_Io/1023)*2980)*10000/417;
// GETTEMP=GETTEMP_DS18B20();
if(Ui>=30000) //恒压
{
Duty_two=Duty_two<10?700:Duty_two-1;
}
else
{
Duty_two=Duty_two>1300?700:Duty_two+1;
}
start1++;
DISPLAY_stri(0,0,"输入Ui:");
if(start1==50)
{
start1=0;
DISPLAY_stri(4,0,ADC_deal_U(Ui));
}
DISPLAY_stri(0,1,"输入Ii:");
DISPLAY_stri(4,1,ADC_deal_I_1(Ii));
DISPLAY_stri(0,2,"输出Uo:");
DISPLAY_stri(4,2,ADC_deal_U(Uo));
DISPLAY_stri(0,3,"输出Io:");
DISPLAY_stri(4,3,ADC_deal_I_1(Io));
stateB=1;
break;
default :break;
}
switch (stateC)//自动模式
{
case 1:
RE_Ui=filter(0);
RE_Uo=filter(2);
Ui=(RE_Ui/1.023)*38.74;
Uo=(RE_Uo/1.023)*25.33;
if((Ui>30300)&(BUCK!=1)) //BUCK模式 大于30.3 选定BUCK状态
{
BUCK=1;
BOOST=0;
OC3CONbits.OCM=0B110; //BUCK开
OC2CONbits.OCM=0B000; //BOOST关
Duty_one=10;
T2CONbits.TON=1;
}
if((Ui<29700)&(BOOST!=1)) //BOOST模式 小于29.7 选定BOOST状态
{
BUCK=0;
BOOST=1;
OC3CONbits.OCM=0B000; //BUCK关
OC2CONbits.OCM=0B110; //BOOST开
Duty_two=10;
T2CONbits.TON=1;
}
if(BUCK==1)
{
if(Ui>=30000) //恒压
{
Duty_one=Duty_one>1300?10:Duty_one+1;
}
else
{
Duty_one--;
if(Duty_one==4)
{
//Duty_one=0;
//Duty_two=6;
T2CONbits.TON=0;
OC3CONbits.OCM=0B000; //BUCK关
OC2CONbits.OCM=0B110; //BOOST开
Duty_one=0;
Duty_two=6;
T2CONbits.TON=1;
BOOST=1;
BUCK=0;
}
}
}
if(BOOST==1)
{
if(Ui>=30000) //恒压
{
Duty_two--;
if(Duty_two==4)
{
T2CONbits.TON=0;
Duty_two=0;
Duty_one=6;
OC3CONbits.OCM=0B110; //BUCK开
OC2CONbits.OCM=0B000; //BOOST关
T2CONbits.TON=1;
BOOST=0;
BUCK=1;
}
}
else
{
Duty_two=Duty_two>1300?10:Duty_two+1;