基于51单片机的数字电容测量仪.docx
《基于51单片机的数字电容测量仪.docx》由会员分享,可在线阅读,更多相关《基于51单片机的数字电容测量仪.docx(26页珍藏版)》请在冰豆网上搜索。
基于51单片机的数字电容测量仪
电子系统设计创新与实习报告
设计课题基于单片机的电容测量仪设计
学院信息科学与工程
学生
学号
专业班级
队友
指导教师
设计时间2014.6.4-2014.7.3
本设计详细介绍了一种基于单片机的数字式电容测量仪设计方案及实现方法。
设计的主要方法是采用555芯片构成单稳态触发器,将电容容量转换为脉冲宽度。
通过单片机的计时器测量脉宽,根据的R值,通过单片机的运算功能,计算出电容容量,最后,再通过单片机的普通I/O口控制液晶屏显示出电容容量的计算结果。
系统的测量围为10pF~500uF,具有多个量程,可根据用户需要由用户选择,与用户的交互是通过键盘实现,不同量程的实现是通过单片机的I/O口控制继电器的吸合与断开来选择不同的R值,从而实现不同的量程。
同时,本设计注重设计方法及流程,首先根据原理设计电路,再通过protues仿真,利用keil编程,进而借助altiumdesigner制作PCB,最后到焊接元器件,调试直至成功。
1系统方案设计
1.1设计说明及要求
1.1.1设计说明
框图中的外接电容是定时电路中的一局部。
当外接电容的容量不同时,与定时电路所对应的时间也有所不同,即C=f(t),而时间与脉冲数目成正比,脉冲数目可以通过计数译码获得。
1.1.2设计要求
〔1〕根本要求
①自制稳压电源。
②被测电容的容量在10pF至10000μF围
③设计四个的测量量程。
④显示测量结果,测量误差小于2.5%。
数字显示:
显示分辨率:
每档满量程的0.1%;
电容测量:
电压可选择5V,25V,50V;
为实现该设计,到达相应的设计要求,本次设计中考虑了三种设计方案,三种设计方案中主要区别在于硬件电路和软件设计的不同,对于本设计,三种方案均能够实现,最后根据设计要求、可行性和设计本钱的考虑选择了基于STC89C52单片机和555芯片构成的单稳态触发电路测量电容的方案。
现在一一介绍论证如下。
1.3方案Ⅱ
根据积分电路原理可得C=Ui*dt/R*Uo,将经过RC充电电路后,输出的与电容对应的电压值输入到ADC0809中,经过处理后,将相应的数值传到单片机里,再通过公式运算,求得相应的电容C值,在LCD上显示。
图1-2方案Ⅱ电容测量框图
1.5三种方案作简单的比拟
比拟上述三种方案可知,方案Ⅰ和ⅠⅠ采用了A/D转换器,价格比拟昂贵;而且根据公式可知,再换算电压与电容值时,时间参数t起着至关重要的作用,对t的计算要准确,不然误差值会很大,所以调试起来有一定难度;方案Ⅲ电路简单,原理清晰,易于实现,易于控制,本设计就是基于方案Ⅲ展开的。
2.2硬件电路设计
2.2.1单片机电路设计
为使单片机正常工作,除电源供电局部外,还需提供晶振电路和复位电路。
具体电路如下:
图2-3单片机工作电路
由图2-3可知,9脚外接的是按键复位电路,18,19脚外接的是晶振电路,这样,就构成了单片机正常工作的必备电路。
同时,为使P0口正常工作,并增加其带负载能力,P0口需接了上拉电阻〔在图中未画出〕。
2.2.2555时钟芯片与单片机连接
图2-4是555时钟芯片构成的单稳态触发电路,6脚和7脚接在一起,R2和C4构成商店复位电路,2脚用于接收单片机P3.7口产生的低脉冲,3脚接于P3.2脚,用于门控制计时器0的启动与停顿。
从而将电容容量转为脉冲宽度。
图2-4555芯片与单片机的连接
2.2.3低脉冲产生电路
如图2-5所示,按键接于P3.3口,即外部中断1接口,因此低脉冲是利用中断实现的,P3.7口产生低脉冲,可在软件中的外部中断1函数中实现,整个过程为,需要测量时,按键,产生外部中断,利用外部中断,用软件再在P3.7口产生一个低脉冲,之所以利用中断实现该功能,是为了增加产品的可靠性,因为按键的时间是比拟长的,直接用按键产生低脉冲可能导致T1>Tw,导致测量错误。
而利用中断,可以直接在中断函数中产生一个固定时间的低脉冲,保证了测量条件,防止发生错误。
图2-5按键产生低脉冲电路
2.2.4键盘电路
如图2-6所示键盘电路主要用于与用户进展交互,如用户需要选择量程时,就必须交互。
键盘分为独立键盘和矩阵键盘,这里只需要实现量程的选择,共四个量程,故无需矩阵键盘,4个独立按键就完全够用了。
图2-6键盘电路
2.2.5指示灯电路
如图2-7所示,指示灯主要用于给用户以提示,如当前量程提示,超量程提示等等。
D2用于超量程提示,D6用于电源提示。
图2-7指示灯电路
2.2.6量程选择电路
在图2-4中可以看到,在RC充电回路中,R值是固定的,不可变的,那么量程也显然是不可变的,因此,需要在此参加可调节充电回路电阻的电路局部,这里,利用继电器可以简单实现。
具体电路如图2-8所示,利用继电器时需特别注意,由于单片机输出电流是很小的,缺乏以驱动继电器吸合,因此要加驱动电路,在这里,选择ULN2003芯片来实现。
当然,也可以利用典型的三极管驱动来实现,虽然选择的是芯片实现驱动,在这里也将典型的三极管驱动电路列于此。
如图2-9所示。
图2-8实现量程选择电路
图2-9利用三极管的驱动电路
2.2.7液晶显示电路
如图2-10所示,lcd接与P1口,用于显示电容值以及一些相应的测量信息。
图2-10lcd显示电路
至此,整个电容测量仪的硬件设计局部就设计好了,接下来,需要的就是与之相匹配的软件支持了。
2.3软件设计
软件编程平台选择最常用的keil软件。
由于该程序并未涉及到底层的驱动问题,因此选择方便快捷的C语言编程。
在编程中,将该程序分为三个模块:
延时模块,1602显示模块及主函数模块。
方便调试与理解。
具体程序见附录二。
总体程序较长,但并不复杂,可根据需要重点看主函数,与硬件电路结合起来,注重程序后紧跟的注释,理解起来是比拟容易的,在此就不再一一详细分析。
2.4量程围设置
由于量程的选择是非常重要的一个环节,在这里单独讨论量程的选择。
系统采用单片机片16位的定时器测量TW的宽度,标准计数脉冲的周期为1微秒时,为确保计数器不发生溢出,要求TW<65毫秒。
同时,为减小量化误差对结果的影响,要求TW>1微秒。
当TW>100微秒以上时,可忽略量化误差的影响。
为满足10pF~500uF的测量围,可通过设置不同充电电阻R的阻值来实现。
理论计算的电阻R阻值、理论量程围以及系统选择的量程围如表2-1所示。
系统分为四个量程,可测量10pF~500uF的电容。
表2-1R值与量程围的关系
R值〔欧姆〕
理论量程围
选择的围
10M
9pF~5.9nF
10pF~5nF
100K
900pF~590nF
5nF~500nF
1K
90nF~59uF
0.5uF~50uF
100
900nF~590uF
F50uF~500uF
2.5altiumdesigner原理图设计及PCB制作
2.4.1原理图设计
图2-11原理图设计
2.4.2PCB制作
图2-12PCB设计
在此并没有布双层板,红色的线仅仅只是为了标志出跳线。
2.4.3设计结果
图2-13设计结果实物图
各个按键功能如图中文字说明。
3系统测试
由于该作品需实现的功能仅为测电容,在此不列出其他的测试。
3.1测量100pf的电容
在此以100pf电容测试为例,演示整个测试过程。
测试标称值为101的电容,即测量电容值为100pf的电容。
104的电容实物如图2-14所示。
测试结果如图2-15所示。
假设量程选择错误,测试结果如图2-16所示。
图2-14100nf的电容实物
图2-152nf电容正常测试
图2-16量程错误情况下的测试
3.2测量4.7uf的电容
再以测试4.7uf电容为例,测试结果如图2-18所示。
图2-18测试4.7uf的电容
3.3测试结果
将测量的一系列电容的电容值与标准值比拟。
比拟结果如表3-1。
表3-1测量值与标准值比拟
标准值
测量值
误差
100pf
99.10pf
1%
2nf
2nf
0%
4.7uf
4.70uf
0%
100uf
100.66uf
1%
由表3-1中数据可知,平均误差是0.5%,低于设计扩展要求的2.5%,测量围是10pf~500uf,根本满足设计要求的10pf~10000uf。
测量结果由液晶直观显示。
综合以上分析,该设计满足整体设计要求。
3.1误差分析
由于产生的0.5%左右的误差,在这里简要分析一下误差产生的原因。
电容测量的误差主要由NE555定时器构成的单稳态触发电路的非线性误差T、计数器的量化误差N和标准计数脉冲的频率偏移TC产生[2][3]。
因此有:
系统采用的标准计数脉冲来自单片机核时钟,由片外的高精度晶振与片电路自激振荡产生,频率非常稳定,可以忽略其频偏对测量结果的影响。
量化误差N是数字电路的特有误差,最坏的情况下等于1。
如采用12M的晶振,可获得1MHz的标准计数脉冲,量化产生的最大误差为1微秒。
通过设置充电电阻R的阻值,使TW到达毫秒级时,量化误差的影响非常小,可以忽略。
非线性误差是由器件的非线性特性产生的,可通过硬件参数修正和软件算法补偿来减小。
4结论与心得体会
经过本次历经4周的实习,使得我又进一步对单片机系统,尤其测量电容的电路系统有了深一步认识。
在做前期准备工作时,教师不希望我们用555芯片做这个实验,因为如果是555芯片震荡电路来测量的话,虽然制作原理简单,但测量值会很不稳定,测围也不够广。
可出于坚信化繁为简的信念,在没做过实物的情况下,我们还是硬着头皮还是想验证下事实是不是如此〔如果不成功再改换方案〕。
起初查阅了很多资料,比方伏安法中的自由轴法制作测量电容电路,LC震荡侧电容电路等,教师也推荐了方案二中的积分法测量电路,但因为在进展理论计算时,因为积分测容法中C=Ui*dt/Uo*R,而我们无法准确确定ADC在输出口的传输时间〔哪怕是几十us〕,所以有种无法掌控误差的感觉,再加上出于本钱考虑,所以没有首选这种方法。
而对于利用555芯片单稳态触发这种法案的分析,我那么很相信,这个电路是可以实现测量功能的,并且只要输出稳定,我就可以做相应补偿。
在经过一系列的仿真,实物制造和调整后,最初做出来的板子并不能运行的,后面反复彻查后,才发现原来自己的设计出现了差漏,少连或错连了一些关键线路,于是又重新修整过。
经过修正后的电路中终于可以开场进展测量了,起初的测量只有在nf档和10uf以下档位下,测量值是根本满足要求的,而PF裆和100uf以上的档位并不满足已要求的,甚至不够稳定,所以我开场将挡位缩小,将10pf~10000uf的要求,缩减为100Pf~500uf,果然修正后的电路,测量稳定了。
再经过软件补偿后,最终获得了在精度上可以满足要求的方案。
〔Ps:
因为最初设计的时候只选择了4个挡位,而手上电容最大才470uf,出于“最稳定测量〞的考虑,所以才改的100pf~500uf挡位。
即:
本方案也可能可以测量500uf以上的电容,只要将其中的100欧姆电阻改小即可。
〕
5参考文献
【1】"单片机根底"第三版广弟朱月秀冷祖祁编著航天大学,2007
【2】"数字式电容测量仪设计"玉芹,洪远泉师学院学报(自然科学版)2011年6月第11卷第3期
【3】梁艳霞,基于单片机控制的电容测试仪设计,总裁,2009.
【4】徐思成,一种基于单品啊及只能电容测试仪的设计与实现,现代电子技术,2010
【5】春明,单片机使用技术,:
人民邮电,2008
【6】何立民,单片机应用程序设计,:
航空航天大学。
【7】世良,吴凌燕,丁国臣,基于AT89C2051单片机的数字电容表设计,2009
【8】童诗白,华成英,模拟电子技术根底第三版,,高等教育,2007
【9】熊筱芳,郭学提,根本89C51单片机的数字电容表设计,自动化应用技术,2008
【10】何光明,健宇,C语言程序设计与应用开发,:
清华大学,2006.
6附录
附录1元器件清单
〔1〕晶振12M一个
〔2〕stc89c52芯片一片
〔3〕30pf2个;10uf1个;470uf1个;0.33uf2个;4.7uf1个;1nf1个
〔4〕40脚活动底座一个
〔5〕lcd液晶一个
〔6〕按键6个
〔7〕发光二极管6个
〔8〕9引脚排阻1个
〔9〕680Ω6个;10k1个;1k2个;1k滑动变阻器1个;10M1个;100k1个;100Ω1个;2k1个;200Ω1个;
〔10〕开关1个
〔11〕整流桥1个
〔12〕7805稳压芯片1片
〔13〕继电器3个
〔14〕ULN20031片
〔10〕排针假设干,杜邦线假设干
附录2程序清单
分5个文件:
delay.h,delay.c,1602.c,1602.h,main.c
(a)delay.h程序清单:
*ifndef__delay_h__
*define__delay_h__
*defineucharunsignedchar
*defineuintunsignedint
voiddelay_us(uintt);
voiddelay_ms(uintt);
*endif
(b)delay.c程序清单:
*include"delay.h"
voiddelay_us(uintt)
{
uchari;
for(;t>0;t--)
{
for(i=0;i<12;i++)
{
;
}
}
}
voiddelay_ms(uintt){
uchari;
for(;t>0;t--)
{
for(i=0;i<125;i++)
{
;
}
}
}
(c)1602.h程序清单:
*ifndef__1602_h__
*define__1602_h__
*include
sbitRS=P2^2;//定义端口
sbitRW=P2^1;
sbitEN=P2^0;
*defineRS_CLRRS=0
*defineRS_SETRS=1
*defineRW_CLRRW=0
*defineRW_SETRW=1
*defineEN_CLREN=0
*defineEN_SETEN=1
unsignedcharpro_data(unsignedcharmda);
voidLCD_write_(unsignedchar);
voidLCD_write_Data(unsignedcharData);
voidLCD_init(void);
voidlcd_pos(unsignedcharpos);
voiddisp(unsignedchar*p);
voiddispchar1(unsignedchar*p);
voiddispchar2(unsignedchar*p);
voiddispchar3(unsignedchar*p);
*endif
(d)1602.c程序清单:
*include"1602.h"
*include"delay.h"
voidLCD_write_(unsignedchar)
{
RS_CLR;
RW_CLR;
EN_SET;
=pro_data();
P1=;
delay_us(5);
EN_CLR;
}
voidLCD_write_Data(unsignedcharData)
{
RS_SET;
RW_CLR;
EN_SET;
Data=pro_data(Data);
P1=Data;
delay_us(5);
EN_CLR;
}
voidLCD_init(void)
{
LCD_write_(0*38);//显示模式设置
delay_ms(5);
LCD_write_(0*38);
delay_ms(5);
LCD_write_(0*38);
delay_ms(5);
LCD_write_(0*38);
LCD_write_(0*08);//显示关闭
LCD_write_(0*01);//显示清屏
LCD_write_(0*06);//显示光标移动设置
delay_ms(5);
LCD_write_(0*0c);//显示开及光标设置
}
voidlcd_pos(unsignedcharpos)
{
LCD_write_(0*80|pos);
}
voiddisp(unsignedchar*p)//第二行显示数据
{
unsignedchari;
lcd_pos(0*43);
for(i=0;i<6;i++)
{
if(4==i)
{
LCD_write_Data(0*2e);
}
LCD_write_Data('0'+(*p));
p++;
}
}
voiddispchar1(unsignedchar*p)//第一行显示需要显示的提示字符串
{
lcd_pos(0*00);
while(*p!
='\0')
{
LCD_write_Data(*p);
p++;
}
lcd_pos(0*4c);
LCD_write_Data('f');
}
voiddispchar2(unsignedchar*p)//第二行显示需要显示的提示字符串
{
lcd_pos(0*40);
while(*p!
='\0')
{
LCD_write_Data(*p);
p++;
}
}
voiddispchar3(unsignedchar*p)//第一行显示第二行清空
{
unsignedchari;
lcd_pos(0*00);
while(*p!
='\0')
{
LCD_write_Data(*p);
p++;
}
lcd_pos(0*40);
for(i=0;i<16;i++)
{
LCD_write_Data('');
}
}
unsignedcharpro_data(unsignedcharmda)//数据处理函数,将高位和低位互换
{
unsignedcharenddat;
unsignedchari;
enddat=0;
for(i=0;i<8;i++)
{
enddat=enddat<<1;
if(mda&0*01==1)
{
enddat=enddat|0*01;
}
else
{
enddat=enddat|0*00;
}
mda=mda>>1;
}
returnenddat;
}
(e)main.c程序清单:
*include
*include"1602.h"
*include"delay.h"
sbitvo=P3^2;//用于检测P3.2口的值,计算时间。
计时器0的开与断
sbittr=P3^7;//产生一个低电平脉冲
//超量程提示灯
sbitledclc=P2^7;
sbitcon1=P0^0;//用于控制继电器,实现档位选择
sbitcon2=P0^1;
sbitcon3=P0^2;
sbitkey1=P0^3;//独立按键局部,用于用户选择量程
sbitkey2=P0^4;
sbitkey3=P0^5;
sbitkey4=P0^6;
sbitled1=P2^3;//量程提示灯
sbitled2=P2^4;
sbitled3=P2^5;
sbitled4=P2^6;
unsignedinttw;//用于获取定时器的数值
floatftemp;//用于计算电容值的中间变量
unsignedlongintc;//存放电容值
unsignedcharneed;//需要测量时置1,一次测量完毕置0
unsignedcharR;//表示不同的档位
unsignedcharflag;//数据处理完毕置1
unsignedchartemp[8];//存放电容值的各个位
unsignedcharzimu1[]="rangeishigher";//量程太高
unsignedcharzimu2[]="ThevalueofCap";
unsignedcharzimu3[]="pleasepresskey";
unsignedcharzimu4[]="tomeasure";
unsignedcharzimu5[]="rangeislower";
voidprocess(unsignedlongintc);//数据处理函数
voidkeyscan();//键盘扫描函数
voidledlight(unsignedcharR);//量程指示灯函数
voidinit_timer0()//定时器0初始化
{
TMOD=0*09;//gate置1,方式1,16位计时,定时器由P3.2控制开断
TH0=0*00;
TL0=0*00;
EA=1;
ET0=1;
TR0=1;
}
voidinit_INT1()//定时器0初始化
{
EA=1;
IT1=1;//下降沿触发
E*1=1;
}
voidmain()
{
ledclc=1;//超量程提示灯熄灭
need=0;//一开场无需测量
con1=con2=con3=0;
flag=0;
init_timer0();//初始化
init_INT1();
LCD_init();
dispchar1(zimu3);
dispchar2(zimu4);
while
(1)
{
if(need==1)
{//当需要测量时
if(vo==0)//vo==0时检测计数器的值可能还没开场计数,可能计数完毕
{
if(TH0!
=0*00||TL0!
=0*00)/