图2-2工作时序图
根据RC暂态电路理论可知,TW的时间宽度计算公式为:
TW=ln3RCX=1.1RCX
由该公式可知,单稳态的暂态1持续时间与待测电容CX的容量成正比。
把输出信号VO送到单片机的INT0引脚,控制定时器0计算出暂态1期间的标准时钟个数,就可实现脉冲宽度测量,从而计算出电容容量。
硬件电路设计
2.2.1单片机电路设计
为使单片机正常工作,除电源供电部分外,还需提供晶振电路和复位电路。
具体电路如下:
图2-3单片机工作电路
由图2-3可知,9脚外接的是按键复位电路,18,19脚外接的是晶振电路,这样,就构成了单片机正常工作的必备电路。
同时,为使P0口正常工作,并增加其带负载能力,P0口需接了上拉电阻(在图中未画出)。
2.2.2555时钟芯片与单片机连接
图2-4是555时钟芯片构成的单稳态触发电路,6脚和7脚接在一起,R2和C4构成商店复位电路,2脚用于接收单片机口产生的低脉冲,3脚接于脚,用于门控制计时器0的启动与停止。
从而将电容容量转为脉冲宽度。
图2-4555芯片与单片机的连接
2.2.3低脉冲产生电路
如图2-5所示,按键接于口,即外部中断1接口,因此低脉冲是利用中断实现的,口产生低脉冲,可在软件中的外部中断1函数中实现,整个过程为,需要测量时,按键,产生外部中断,利用外部中断,用软件再在口产生一个低脉冲,之所以利用中断实现该功能,是为了增加产品的可靠性,因为按键的时间是比较长的,直接用按键产生低脉冲可能导致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显示电路
至此,整个电容测量仪的硬件设计部分就设计好了,接下来,需要的就是与之相匹配的软件支持了。
软件设计
软件编程平台选择最常用的keil软件。
由于该程序并未涉及到底层的驱动问题,因此选择方便快捷的C语言编程。
在编程中,将该程序分为三个模块:
延时模块,1602显示模块及主函数模块。
方便调试与理解。
具体程序见附录二。
总体程序较长,但并不复杂,可根据需要重点看主函数,与硬件电路结合起来,注重程序后紧跟的注释,理解起来是比较容易的,在此就不再一一详细分析。
量程范围设置
由于量程的选择是非常重要的一个环节,在这里单独讨论量程的选择。
系统采用单片机片内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
altiumdesigner原理图设计及PCB制作
2.4.1原理图设计
图2-11原理图设计
2.4.2PCB制作
图2-12PCB设计
在此并没有布双层板,红色的线仅仅只是为了标志出跳线。
2.4.3设计结果
图2-13设计结果实物图
各个按键功能如图中文字说明。
3系统测试
由于该作品需实现的功能仅为测电容,在此不列出其他的测试。
测量100pf的电容
在此以100pf电容测试为例,演示整个测试过程。
测试标称值为101的电容,即测量电容值为100pf的电容。
104的电容实物如图2-14所示。
测试结果如图2-15所示。
若量程选择错误,测试结果如图2-16所示。
图2-14100nf的电容实物
图2-152nf电容正常测试
图2-16量程错误情况下的测试
测量的电容
再以测试电容为例,测试结果如图2-18所示。
图2-18测试的电容
测试结果
将测量的一系列电容的电容值与标准值比较。
比较结果如表3-1。
表3-1测量值与标准值比较
标准值
测量值
误差
100pf
1%
2nf
2nf
0%
0%
100uf
1%
由表3-1中数据可知,平均误差是%,低于设计扩展要求的%,测量范围是10pf~500uf,基本满足设计要求的10pf~10000uf。
测量结果由液晶直观显示。
综合以上分析,该设计满足整体设计要求。
误差分析
由于产生的%左右的误差,在这里简要分析一下误差产生的原因。
电容测量的误差主要由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个;2个;1个;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个文件:
,,,,
(a)程序清单:
#ifndef__delay_h__
#define__delay_h__
#defineucharunsignedchar
#defineuintunsignedint
voiddelay_us(uintcnt);
voiddelay_ms(uintcnt);
#endif
(b)程序清单:
#include""
voiddelay_us(uintcnt)
{
uchari;
for(;cnt>0;cnt--)
{
for(i=0;i<12;i++)
{
;
}
}
}
voiddelay_ms(uintcnt){
uchari;
for(;cnt>0;cnt--)
{
for(i=0;i<125;i++)
{
;
}
}
}
(c)程序清单:
#ifndef__1602_h__
#define__1602_h__
#include<>
sbitRS=P2^2;免tw的值被更//改即不需要测量时,一直保持
EX1=1;//开外部中断1
}
else//反之,证明没有计数,无电容,默认值tw置0
{
tw=0;
}
}
ftemp=tw/;//计算电容值根据公式tw=*R*C
c=(unsignedlongint)(ftemp)*100;//扩大了一百倍便于后续程序
//取两位小数点
process(c);//调用数据处理函数,根据不同的R值进行处理
}
if(flag==1)//数据处理结束每次处理结束,证明需要更新显示的数据
{
if(tw>=50000||ledclc==0)//量程超出
{
dispchar3(zimu1);//量程太高
ledclc=0;
}
elseif(tw<=100&&ledclc==1)//量程太低
{
dispchar3(zimu5);
ledclc=0;
}
else
{
dispchar1(zimu2);
disp(temp);
}
flag=0;
}
keyscan();
}
}
voidtimer0()interrupt1//定时器0中断用于超量程提示
{
ledclc=0;
}
voidexint1()interrupt2//外部中断0用于产生低脉冲,启动555定时器
{
unsignedchara;
tr=1;//tr端一个负脉冲
a=1;
while(--a);
tr=0;
a=20;
while(--a);
tr=1;//tr端负脉冲结束大约40us的负脉冲
need=1;//表示需要测量
ledclc=1;//关闭先前的超量程提示
EX1=0;//暂时关闭外部中断,一次测量结束,再开放外部中断
}
voidprocess(unsignedlongintc)
{
if(R==1)//10M的电阻量程10pf~5000pf
{
c=c/10;
lcd_pos(0x4a);
LCD_write_Data('');
LCD_write_Data('p');
LCD_write_Data('f');
LCD_write_Data('');
LCD_write_Data('');
}
if(R==2)//100k的电阻量程5nf~500nf
{
c=c/100;
lcd_pos(0x4a);
LCD_write_Data('');
LCD_write_Data('n');
LCD_write_Data('f');
LCD_write_Data('');
LCD_write_Data('');
}
if(R==3)//1k欧姆的电阻量程~50uf
{
c=c/1000;//扩大了一百倍单位c=tw/500uf
lcd_pos(0x4a);
LCD_write_Data('');
LCD_write_Data('u');
LCD_write_Data('f');
LCD_write_Data('');
LCD_write_Data('');
}
if(R==4)//100欧姆的电阻量程50uf~500uf
{
c=c/100;//扩大了一百倍单位c=tw/500uf
lcd_pos(0x4a);
LCD_write_Data('');
LCD_write_Data('u');
LCD_write_Data('f');
LCD_write_Data('');
LCD_write_Data('');
}
temp[0]=c/100000;//千位
temp[1]=c/10000%10;//百位
temp[2]=c/1000%10;//十位
temp[3]=c/100%10;//个位
temp[4]=c/10%10;
temp[5]=c%10;
flag=1;
}
voidkeyscan()
{
if(key1==0)
{
delay_ms(10);
if(key1==0)//b3按下
{
while(key1==0);
R=1;//10M的电阻量程10pf~5000pf(5nf)
con1=1;
con3=1;
con2=0;
ledclc=1;
dispchar1(zimu3);
dispchar2(zimu4);
}
}
if(key2==0)//b4按下
{
delay_ms(10);
if(key2==0)
{
while(key2==0);
R=2;//100k的电阻量程5nf~500nf