数控电源010V含代码.docx
《数控电源010V含代码.docx》由会员分享,可在线阅读,更多相关《数控电源010V含代码.docx(13页珍藏版)》请在冰豆网上搜索。
数控电源010V含代码
直流数控电压源设计
本小组成员:
刘兵丹,刘朋,刘伶,电子信息工程0904班
系统框架
本数控直流稳压电源的设计以一稳压电源为基础,以高性能单片机系统为控制核心,以稳压驱动放大电路、短路保护电路为外围的硬件系统,在检测与控制软件的支持下实现对电压输出的数字控制,通过对稳压电源输出的电压进行数据采样与给定数据比较,从而调整输入电压。
本数控直流稳压电源实现以下功能:
键盘可以直接设定输出电压值;可步进调整电压;LCD显示电压值。
硬件接口及主要特性:
ADC0804接口
振荡频率为fCLK≈1/1.1RC。
其典型应用参数为:
R=10KΩ,C=150PF,fCLK≈640KHZ,转换速度为100μs。
若采用外部时钟,则外部fCLK可从CLKI端送入,此时不接R、C。
允许的时钟频率范围为100KHZ~1460KHZ。
INTR(引脚5):
INTR是转换结束信号输出端,输出跳转为低电平表示本次转换已经完成,可作为微处理器的中断或查询信号。
如果将CS和WR端与INTR端相连,则ADC0804就处于自动循环转换状态.
CS=0时,允许进行A/D转换。
WR由低跳高时A/D转换开始,8位逐次比较需8×8=64个时钟周期,再加上控制逻辑操作,一次转换需要66~73个时钟周期。
在典型应用fCLK=640KHZ时,转换时间约为103μs~114μs。
当fCLK超过640KHZ,转换精度下降,超过极限值1460KHZ时便不能正常工作。
VREF/2(引脚9):
参考电压VREF/2可以由外部电路供给,从“VREF/2”端直接送入,VREF/2端电压值应是输入电压范围的二分之一。
DAC0832接口
8位D/A转换,其转换时间为1us,工作电压为+5V~+15V,基准电压为—10V~+10V
芯片数据输入可采用双缓冲,单缓冲和直通三种方式。
本次采用直通方式。
LCD1602接口
和ADC0804分时复用P0进行数据传输
键盘接口
单独用P1口对4*4键盘进行扫描识别
程序设计
程序设计思想提炼如下图所示:
精简协作式不可剥夺嵌入式操作系统,得力与田sir的Easy51RTOS操作系统,这个系统运用。
协作式不可剥夺意思是说一个任务得到了CPU时间,除非它自己放弃使用CPU,否则将完全霸占CPU,所以任务之间需要协作——使用一段时间的CPU,放弃使用,其它的任务也如此,才能保证系统的正常运行。
把一些例行的及需要定时执行的程序放在时钟中断中,还可以利用时钟中断协助主程序完成定时、延时等操作。
注意:
应尽量缩短中断处理程序的执行时间,更不要长于20mS。
全局变量
部分代码如下:
ADC0804测得的数字量adc_value;DAC0832输入的数字量dac_value;
程序写好后,编译成功,但1602显示的数据与预期不符。
于是分块检查,发现
DA,1602,AD均是正确的。
后来参考别人的程序,发现单片机在读取AD的数据时,没有先对相应的端口写1.
任务零
ADC0804测数控电源的输出电压(量程限制取其一半进行测量),得到数字量adc_value,
与DAC0832的输入dac_value进行比较,进行反馈(其实我们在把电路做出来,进行测试时发现实际输出和我们通过按键设定的值误差很小,反而ADC0804由于精度不高,测出来的电压值误差较大,最后我们舍去了反馈)来调整0832的dac_value。
#ifndef__adc0804_H__
#define__adc0804_H__
//接口定义
sbitAD_CS=P3^4;
sbitAD_RD=P3^7;
sbitAD_WR=P3^6;
//读ADDR中的数据
intget_data()
{
intdate;
AD_CS=0;
AD_RD=1;
AD_WR=1;//ad开始转换
AD_WR=0;
P0=0xff;
AD_RD=1;
AD_RD=0;
date=P0;
AD_WR=1;//ad停止转换
AD_RD=1;
returndate;
}
#endif
程序写好后,编译成功,但1602显示的数据与预期不符。
于是分块检查,发现
DA,1602,AD均是正确的。
后来参考别人的程序,发现单片机在读取AD的数据时,没有先对相应的端口写1.
任务一
通过按键设定电压,识别到dac_value使DAC0832输出我们需要的电压。
voidtask1(void)
{
floatadc_value1;
floatdac_value1;
intdac_value2;
adc_value1=adc_value;
dac_value1=dac_value;
if(adc_value1*10/255-dac_value1/1000>=0.04)dac_value1=dac_value1-1;
if(dac_value1/1000-adc_value1*10/255>=0.04)dac_value1=dac_value1+1;
dac_value1=dac_value1*255/10000;
dac_value2=dac_value1;
if(key_input_display==0)//当确认键按下时。
dac0832(dac_value2);
task_delay[1]=TASK_DELAY1;
}
涂暗的那段代码是为了用0804的测量值来反馈0832已得到我实际设定的电压值;
涂红的那段代码:
8位精准度,10V对应255,但是按键扫描得到的电压值是放大了一千倍的。
见后面任务三
任务二
通过1602来显示setting:
设定的电压值
measure:
测得的电压值
voidtask2_init(void)
{
lcd1602_init();
print_string("setting:
",0x80);
print_string("measure:
",0x80+0x40);
}
//任务2
voidtask2()
{
task2_init();
if(key_input_display==0)//当确认键按下时.
{
adc_value=19.*adc_value;
adc[0]=adc_value/1000+'0';
adc[1]='.';
adc[2]=adc_value%1000/100+'0';
adc[3]=adc_value%100/10+'0';
adc[4]=adc_value%10+'0';
adc[5]=0;
}
switch(press_time)
{
case0:
{key_value_dac[0]=dac_value/1000+'0';
key_value_dac[1]='.';
key_value_dac[2]=dac_value%1000/100+'0';
key_value_dac[3]=dac_value%1000%100/10+'0';
key_value_dac[4]=dac_value%1000%100%10+'0';
}break;
dac_value是一个四位的整数
case1:
{key_value_dac[0]='_';
key_value_dac[1]='.';
key_value_dac[2]='_';
key_value_dac[3]='_';
key_value_dac[4]='_';
}break;
case2:
key_value_dac[0]=dac_value/1000+'0';break;
case3:
key_value_dac[2]=dac_value%1000/100+'0';break;
case4:
key_value_dac[3]=dac_value%1000%100/10+'0';break;
case5:
key_value_dac[4]=dac_value%1000%100%10+'0';break;
default:
break;
}
print_string(adc,0xc8);
print_string(key_value_dac,0x88);
显示设定的电压值,和测得的电压值
task_delay[2]=TASK_DELAY2;
}
1602在显示数据时会在数据最后乱码,后经在尾数写'/0',显示正确。
任务三
通过对键盘进行扫描,将设定的电压值,转换为数字量dac_value,同时还有步进加减和确定,清零的识别。
voidinput_dac_value(num)
{
uchartemp=0;
staticucharflag=0;
temp=num;
if(temp==0xff)flag=1;
if((temp!
=0xff)&&(flag==1))
{
flag=0;
key=temp;
fmq=0;
if(key<10&&(key_input_display==1))
{
press_time++;
switch(press_time)
{
case2:
dac_value=key*1000;break;
case3:
dac_value=dac_value+key*100;break;
case4:
dac_value=dac_value+key*10;break;
case5:
dac_value=dac_value+key;break;
default:
break;
}
}
注:
将设定的电压转化为整数,放大一千倍
switch(key)
{
case14:
{key_input_display=1;press_time++;key=0;fmq=0;};break;//设置
case13:
{key_input_display=0;press_time=0;fmq=0;};break;//确认
case15:
{dac_value=0;fmq=0;};break;//清零
case10:
{dac_value+=40;fmq=0;};break;//递加
case11:
{dac_value-=40;fmq=0;};break;//递减
default:
break;
}
}
}主要程序见附件(略)
模拟部分
电路仿真图
电路说明图
作品参数测试
设定值
AD测量值
万用表测量值
列1
AD测量得误差
列2
万用表测得误差
1.000
0.941
0.940
5.900%
6.000%
2.000
1.960
1.960
2.000%
2.000%
2.910
2.901
2.900
0.309%
0.344%
3.000
2.980
2.980
0.667%
0.667%
3.790
3.760
3.770
0.792%
0.528%
4.000
4.000
4.000
0.000%
0.000%
5.000
4.941
4.940
1.180%
1.200%
5.550
5.500
5.500
0.901%
0.901%
6.000
5.941
5.940
0.983%
1.000%
7.000
6.980
6.990
0.286%
0.143%
8.000
8.000
8.010
0.000%
-0.125%
8.999
8.941
8.950
0.645%
0.545%
9.999
9.960
9.980
0.390%
0.190%
纹波峰峰值
10mV
纹波频率
50KHZ
内阻
2.2欧姆
最大电流
0.88A
最大功率
11.4W
总结:
这个作品的单片机部分的仿真和电路的焊接是在两天内完工的,模拟部分开始焊好了,测试时烧过,后来又从焊了一次。
当时正是要要校级比赛的作品,我们的器件过来好久才送过来,导致交作品那天我们才拿到器件正式开始焊电路。
在紧张和高度兴奋中,似乎效率很高,程序的设计和仿真中遇到的问题都得到了解决。
第三天,数控和功率放大部分进行联合调,一开始就遇到0804测量不准的问题,差距很大,后来才发现,输出部分的分压电位器是坏的。
改了后误差还是有点大差不多,0.1V左右。
原来是我们为了能输出更大的电流,在输出端接的很大的分压电位器,差不多20M欧姆,然后为了滤除纹波也并接了电容,导致电容的电很难放掉,测得的电压不准。
最后用五天的时间我们完成了数控电源。
作品照片后续会上传……