《基于51单片机的数字电容测量仪设计.doc》由会员分享,可在线阅读,更多相关《基于51单片机的数字电容测量仪设计.doc(35页珍藏版)》请在三一办公上搜索。
1、 电子系统设计创新与实习报告设计课题 基于单片机的电容测量仪设计 学 院 信息科学与工程 学生姓名 学 号 专业班级 队 友 指导教师 设计时间 2014.6.4-2014.7.3 本设计详细介绍了一种基于单片机的数字式电容测量仪设计方案及实现方法。设计的主要方法是采用555芯片构成单稳态触发器,将电容容量转换为脉冲宽度。通过单片机的计时器测量脉宽, 根据已知的R值,通过单片机的运算功能,计算出电容容量,最后,再通过单片机的普通I/O口控制液晶屏显示出电容容量的计算结果。系统的测量范围为10pF 500uF, 具有多个量程,可根据用户需要由用户选择,与用户的交互是通过键盘实现,不同量程的实现是
2、通过单片机的I/O口控制继电器的吸合与断开来选择不同的R值,从而实现不同的量程。同时,本设计注重设计方法及流程,首先根据原理设计电路,再通过protues仿真,利用keil编程,进而借助altium designer 制作PCB,最后到焊接元器件,调试直至成功。1 系统方案设计1.1 设计说明及要求1.1.1 设计说明框图中的外接电容是定时电路中的一部分。当外接电容的容量不同时,与定时电路所对应的时间也有所不同,即C=f(t),而时间与脉冲数目成正比,脉冲数目可以通过计数译码获得。 1.1.2 设计要求(1)基本要求 自制稳压电源。 被测电容的容量在10pF至10000F范围内 设计四个的测量
3、量程。 显示测量结果,测量误差小于2.5%。 数字显示:显示分辨率:每档满量程的0.1%;电容测量:电压可选择5V,25V,50V;为实现该设计,达到相应的设计要求,本次设计中考虑了三种设计方案,三种设计方案中主要区别在于硬件电路和软件设计的不同,对于本设计,三种方案均能够实现,最后根据设计要求、可行性和设计成本的考虑选择了基于STC89C52单片机和555芯片构成的单稳态触发电路测量电容的方案。现在一一介绍论证如下。1.3方案根据积分电路原理可得C=Ui*dt/R*Uo,将经过RC充电电路后,输出的与电容对应的电压值输入到ADC0809中,经过处理后,将相应的数值传到单片机里,再通过公式运算
4、,求得相应的电容C值,在LCD上显示。图1-2 方案电容测量框图1.5 三种方案作简单的比较比较上述三种方案可知,方案和采用了A/D转换器,价格比较昂贵;而且根据公式可知,再换算电压与电容值时,时间参数t起着至关重要的作用,对t的计算要精确,不然误差值会很大,所以调试起来有一定难度;方案电路简单,原理清晰,易于实现,易于控制,本设计就是基于方案展开的。2.2 硬件电路设计2.2.1 单片机电路设计为使单片机正常工作,除电源供电部分外,还需提供晶振电路和复位电路。具体电路如下: 图2-3 单片机工作电路由图2-3可知,9脚外接的是按键复位电路,18,19脚外接的是晶振电路,这样,就构成了单片机正
5、常工作的必备电路。同时,为使P0口正常工作,并增加其带负载能力,P0口需接了上拉电阻(在图中未画出)。2.2.2 555时钟芯片与单片机连接图2-4是555时钟芯片构成的单稳态触发电路,6脚和7脚接在一起,R2和C4构成商店复位电路,2脚用于接收单片机P3.7口产生的低脉冲,3脚接于P3.2脚,用于门控制计时器0的启动与停止。从而将电容容量转为脉冲宽度。图2-4 555芯片与单片机的连接2.2.3 低脉冲产生电路如图2-5所示,按键接于P3.3口,即外部中断1接口,因此低脉冲是利用中断实现的,P3.7口产生低脉冲,可在软件中的外部中断1函数中实现,整个过程为,需要测量时,按键,产生外部中断,利
6、用外部中断,用软件再在P3.7口产生一个低脉冲,之所以利用中断实现该功能,是为了增加产品的可靠性,因为按键的时间是比较长的,直接用按键产生低脉冲可能导致T1 Tw ,导致测量错误。而利用中断,可以直接在中断函数中产生一个固定时间的低脉冲,保证了测量条件,避免发生错误。图2-5 按键产生低脉冲电路2.2.4 键盘电路如图2-6所示键盘电路主要用于与用户进行交互,如用户需要选择量程时,就必须交互。键盘分为独立键盘和矩阵键盘,这里只需要实现量程的选择,共四个量程,故无需矩阵键盘,4个独立按键就完全够用了。图2-6 键盘电路2.2.5 指示灯电路如图2-7所示,指示灯主要用于给用户以提示,如当前量程提
7、示,超量程提示等等。 D2用于超量程提示,D6用于电源提示。图2-7 指示灯电路2.2.6 量程选择电路在图2-4中可以看到,在RC充电回路中,R值是固定的,不可变的,那么量程也显然是不可变的,因此,需要在此加入可调节充电回路电阻的电路部分,这里,利用继电器可以简单实现。具体电路如图2-8所示,利用继电器时需特别注意,由于单片机输出电流是很小的,不足以驱动继电器吸合,因此要加驱动电路,在这里,选择ULN2003芯片来实现。当然,也可以利用典型的三极管驱动来实现,虽然选择的是芯片实现驱动,在这里也将典型的三极管驱动电路列于此。如图2-9所示。图2-8 实现量程选择电路图2-9 利用三极管的驱动电
8、路2.2.7 液晶显示电路 如图2-10所示,lcd接与P1口,用于显示电容值以及一些相应的测量信息。图2-10 lcd显示电路至此,整个电容测量仪的硬件设计部分就设计好了,接下来,需要的就是与之相匹配的软件支持了。2.3 软件设计软件编程平台选择最常用的keil软件。由于该程序并未涉及到底层的驱动问题,因此选择方便快捷的C语言编程。在编程中,将该程序分为三个模块:延时模块,1602显示模块及主函数模块。方便调试与理解。具体程序见附录二。总体程序较长,但并不复杂,可根据需要重点看主函数,与硬件电路结合起来,注重程序后紧跟的注释,理解起来是比较容易的,在此就不再一一详细分析。2.4 量程范围设置
9、由于量程的选择是非常重要的一个环节,在这里单独讨论量程的选择。系统采用单片机片内16 位的定时器测量TW 的宽度, 标准计数脉冲的周期为1 微秒时, 为确保计数器不发生溢出, 要求TW 1 微秒。当TW 100 微秒以上时, 可忽略量化误差的影响。为满足10pF 500uF 的测量范围, 可通过设置不同充电电阻R 的阻值来实现。理论计算的电阻R 阻值、理论量程范围以及系统选择的量程范围如表2-1 所示。系统分为四个量程, 可测量10pF 500uF 的电容。表2-1 R值与量程范围的关系R值(欧姆)理论量程范围选择的范围10M9pF 5. 9nF10pF 5nF100K900pF 590nF5
10、nF 500nF1K90nF 59uF0. 5uF 50uF100900nF 590uFF 50uF 500uF2.5 altium designer 原理图设计及PCB制作2.4.1 原理图设计图2-11 原理图设计2.4.2 PCB制作图2-12 PCB设计在此并没有布双层板,红色的线仅仅只是为了标志出跳线。2.4.3 设计结果图2-13 设计结果实物图各个按键功能如图中文字说明。3系统测试由于该作品需实现的功能仅为测电容,在此不列出其他的测试。3.1 测量100pf的电容在此以100pf电容测试为例,演示整个测试过程。测试标称值为101的电容,即测量电容值为100pf的电容。104的电容
11、实物如图2-14所示。测试结果如图2-15所示。若量程选择错误,测试结果如图2-16所示。图2-14 100nf的电容实物图2-15 2nf电容正常测试图2-16 量程错误情况下的测试3.2 测量4.7uf的电容再以测试4.7uf电容为例,测试结果如图2-18所示。图2-18 测试4.7uf的电容3.3 测试结果将测量的一系列电容的电容值与标准值比较。比较结果如表3-1。表3-1 测量值与标准值比较标准值测量值误差100pf99.10pf1%2nf2nf0%4.7uf4.70uf0%100uf100.66uf1%由表3-1中数据可知,平均误差是0.5%,低于设计扩展要求的2.5%,测量范围是1
12、0pf500uf,基本满足设计要求的10pf10000uf。测量结果由液晶直观显示。综合以上分析,该设计满足整体设计要求。3.1 误差分析由于产生的0.5%左右的误差,在这里简要分析一下误差产生的原因。电容测量的误差主要由NE555 定时器构成的单稳态触发电路的非线性误差T 、计数器的量化误差N 和标准计数脉冲的频率偏移TC 产生2 3 。因此有:系统采用的标准计数脉冲来自单片机内核时钟, 由片外的高精度晶振与片内电路自激振荡产生,频率非常稳定, 可以忽略其频偏对测量结果的影响。量化误差N 是数字电路的特有误差, 最坏的情况下等于 1。如采用12M 的晶
13、振, 可获得1MHz 的标准计数脉冲, 量化产生的最大误差为1 微秒。通过设置充电电阻R 的阻值, 使TW 达到毫秒级时, 量化误差的影响非常小, 可以忽略。非线性误差是由器件的非线性特性产生的, 可通过硬件参数修正和软件算法补偿来减小。4 结论与心得体会 经过本次历经4周的实习,使得我又进一步对单片机系统,尤其测量电容的电路系统有了深一步认识。在做前期准备工作时,老师不希望我们用555芯片做这个实验,因为如果是555芯片震荡电路来测量的话,虽然制作原理简单,但测量值会很不稳定,测范围也不够广。可出于坚信化繁为简的信念,在没做过实物的情况下,我们还是硬着头皮还是想验证下事实是不是如此(如果不成
14、功再改换方案)。 起初查阅了很多资料,比如伏安法中的自由轴法制作测量电容电路,LC震荡侧电容电路等,老师也推荐了方案二中的积分法测量电路,但因为在进行理论计算时,因为积分测容法中C=Ui*dt/Uo*R,而我们无法精确确定ADC在输出口的传输时间(哪怕是几十us),所以有种无法掌控误差的感觉,再加上出于成本考虑,所以没有首选这种方法。而对于利用555芯片单稳态触发这种法案的分析,我则很相信,这个电路是可以实现测量功能的,并且只要输出稳定,我就可以做相应补偿。 在经过一系列的仿真,实物制造和调整后,最初做出来的板子并不能运行的,后面反复彻查后,才发现原来自己的设计出现了差漏,少连或错连了一些关键
15、线路,于是又重新修整过。经过修正后的电路中终于可以开始进行测量了,起初的测量只有在nf档和10uf以下档位下,测量值是基本满足要求的,而PF裆和100uf以上的档位并不满足已要求的,甚至不够稳定,所以我开始将挡位缩小,将10pf10000uf的要求,缩减为100Pf500uf,果然修正后的电路,测量稳定了。再经过软件补偿后,最终获得了在精度上可以满足要求的方案。(Ps:因为最初设计的时候只选择了4个挡位,而手上电容最大才470uf,出于“最稳定测量”的考虑,所以才改的100pf500uf挡位。即:本方案也可能可以测量500uf以上的电容,只要将其中的100欧姆电阻改小即可。)5 参考文献【1】
16、 单片机基础第三版 李广弟 朱月秀 冷祖祁 编著 北京航天大学出版社,2007【2】 数字式电容测量仪设计 张玉芹, 洪远泉 廊坊师范学院学报(自然科学版) 2011 年6 月 第11 卷第3 期【3】梁艳霞,基于单片机控制的电容测试仪设计,总裁,2009.【4】徐思成,一种基于单品啊及只能电容测试仪的设计与实现,现代电子技术,2010【5】陶春明,单片机使用技术,北京:人民邮电出版社,2008【6】何立民,单片机应用程序设计,北京:北京航空航天大学出版社。【7】陈世良,吴凌燕,丁国臣,基于AT89C2051单片机的数字电容表设计,2009【8】童诗白,华成英,模拟电子技术基础第三版,北京,高
17、等教育出版社,2007【9】熊筱芳,郭学提,基本89C51单片机的数字电容表设计,自动化应用技术,2008【10】何光明,杨健宇,C语言程序设计与应用开发, 北京:清华大学出版社,2006.6 附录 附录1 元器件清单(1)晶振12M一个(2)stc89c52芯片一片(3)30pf 2个;10uf 1个;470uf 1个;0.33uf 2个;4.7uf 1个;1nf 1个(4)40脚活动底座一个(5)lcd液晶一个(6)按键6个(7)发光二极管6个(8)9引脚排阻 1个(9)680 6个;10k 1个;1k 2个;1k滑动变阻器 1个;10M 1个;100k 1个;100 1个;2k 1个;2
18、00 1个;(10) 开关1个(11) 整流桥1个(12)7805稳压芯片1片(13) 继电器 3个(14) ULN2003 1片(10)排针若干,杜邦线若干附录2 程序清单分5个文件:delay.h,delay.c,1602.c ,1602.h,main.c(a) delay.h程序清单:#ifndef _delay_h_#define _delay_h_#define uchar unsigned char#define uint unsigned intvoid delay_us(uint cnt);void delay_ms(uint cnt);#endif(b) delay.c 程序
19、清单:#include delay.hvoid delay_us(uint cnt)uchar i;for(;cnt0;cnt-)for(i=0;i0;cnt-)for(i=0;i125;i+);(c) 1602.h程序清单:#ifndef _1602_h_#define _1602_h_#include sbit RS = P22; /定义端口 sbit RW = P21;sbit EN = P20;#define RS_CLR RS=0 #define RS_SET RS=1#define RW_CLR RW=0 #define RW_SET RW=1 #define EN_CLR EN=
20、0#define EN_SET EN=1unsigned char pro_data(unsigned char mda);void LCD_write_com(unsigned char com);void LCD_write_Data(unsigned char Data); void LCD_init(void); void lcd_pos(unsigned char pos); void disp(unsigned char *p);void dispchar1(unsigned char *p);void dispchar2(unsigned char *p);void dispch
21、ar3(unsigned char *p);#endif(d) 1602.c程序清单:#include 1602.h#include delay.h void LCD_write_com(unsigned char com) RS_CLR; RW_CLR; EN_SET; com = pro_data(com); P1 = com; delay_us(5); EN_CLR; void LCD_write_Data(unsigned char Data) RS_SET; RW_CLR; EN_SET; Data = pro_data(Data); P1 = Data; delay_us(5);
22、EN_CLR; void LCD_init(void) LCD_write_com(0x38); / 显示模式设置 delay_ms(5); LCD_write_com(0x38); delay_ms(5); LCD_write_com(0x38); delay_ms(5); LCD_write_com(0x38); LCD_write_com(0x08); / 显示关闭 LCD_write_com(0x01); / 显示清屏 LCD_write_com(0x06); / 显示光标移动设置 delay_ms(5); LCD_write_com(0x0c); / 显示开及光标设置void lcd
23、_pos(unsigned char pos)LCD_write_com(0x80|pos); void disp(unsigned char *p) / 第二行显示数据unsigned char i;lcd_pos(0x43);for(i=0;i6;i+) if(4=i)LCD_write_Data(0x2e);LCD_write_Data(0+(*p);p+; void dispchar1(unsigned char *p) / 第一行显示需要显示的提示字符串lcd_pos(0x00);while(*p != 0)LCD_write_Data(*p);p+; lcd_pos(0x4c);L
24、CD_write_Data(f); void dispchar2(unsigned char *p) / 第二行显示需要显示的提示字符串lcd_pos(0x40);while(*p != 0)LCD_write_Data(*p);p+; void dispchar3(unsigned char *p) / 第一行显示 第二行清空unsigned char i;lcd_pos(0x00);while(*p != 0)LCD_write_Data(*p);p+; lcd_pos(0x40);for(i=0;i16;i+)LCD_write_Data( ); unsigned char pro_da
25、ta(unsigned char mda) /数据处理函数,将高位和低位互换unsigned char enddat;unsigned char i;enddat = 0;for(i=0;i8;i+)enddat = enddat 1;return enddat;(e)main.c程序清单:#include #include 1602.h#include delay.hsbit vo = P32; / 用于检测P3.2口的值,计算时间。 计时器0的开与断sbit tr = P37; / 产生一个低电平脉冲 / 超量程提示灯sbit ledclc = P27;sbit con1 = P00; /
26、 用于控制继电器,实现档位选择sbit con2 = P01;sbit con3 = P02;sbit key1 = P03; / 独立按键部分,用于用户选择量程sbit key2 = P04;sbit key3 = P05;sbit key4 = P06;sbit led1 = P23; / 量程提示灯sbit led2 = P24;sbit led3 = P25;sbit led4 = P26;unsigned int tw; / 用于获取定时器的数值float ftemp; / 用于计算电容值的中间变量unsigned long int c;/ 存放电容值unsigned char ne
27、ed; / 需要测量时置1,一次测量结束置0unsigned char R; / 表示不同的档位unsigned char flag; / 数据处理结束置1unsigned char temp8; / 存放电容值的各个位 unsigned char zimu1 = range is higher; /量程太高unsigned char zimu2 = The value of Cap;unsigned char zimu3 = please press key;unsigned char zimu4 = to measure ;unsigned char zimu5 = range is lo
28、wer ;void process(unsigned long int c); / 数据处理函数void keyscan(); / 键盘扫描函数void ledlight(unsigned char R); /量程指示灯函数void init_timer0() / 定时器0 初始化 TMOD = 0x09; / gate置1,方式1,16位计时,定时器由P3.2控制开断TH0 = 0x00;TL0 = 0x00;EA = 1;ET0 = 1; TR0 = 1;void init_INT1 () / 定时器0 初始化EA = 1;IT1 = 1; / 下降沿触发EX1 = 1; void mai
29、n() 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 != 0x00 | TL0 != 0x00) / 是计数结束 若有读数,用tw 存下 tw = TH0 =50000 | le
30、dclc = 0)/ 量程超出dispchar3(zimu1); / 量程太高ledclc = 0;else if(tw=100 & ledclc = 1) /量程太低dispchar3(zimu5);ledclc = 0;else dispchar1(zimu2);disp(temp); flag = 0;keyscan(); void timer0() interrupt 1 / 定时器0中断 用于超量程提示 ledclc = 0;void exint1() interrupt 2 / 外部中断0 用于产生低脉冲,启动555定时器unsigned char a;tr = 1; / tr端一
31、个负脉冲a = 1;while(-a);tr = 0;a = 20;while(-a);tr = 1; / tr端负脉冲结束 大约40us的负脉冲need = 1;/ 表示需要测量ledclc = 1; / 关闭先前的超量程提示EX1 = 0; / 暂时关闭外部中断,一次测量结束,再开放外部中断void process(unsigned long int c)if(R = 1) / 10M 的电阻 量程10pf 5000pfc = c /10; lcd_pos(0x4a); LCD_write_Data( );LCD_write_Data(p);LCD_write_Data(f);LCD_wr
32、ite_Data( );LCD_write_Data( );if(R = 2) / 100k 的电阻 量程5nf 500nfc = 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欧姆 的电阻 量程0.5uf 50ufc = c /1000; / 扩大了一百倍 单位 c = tw/500 uf lcd_pos(0x4a); LCD_write_Data( );LCD_write_Data(u)
33、;LCD_write_Data(f);LCD_write_Data( );LCD_write_Data( ); if(R = 4) /100欧姆 的电阻 量程50uf 500ufc = c /100; / 扩大了一百倍 单位 c = tw/500 uf lcd_pos(0x4a); LCD_write_Data( );LCD_write_Data(u);LCD_write_Data(f);LCD_write_Data( );LCD_write_Data( ); temp0 = c / 100000; / 千位temp1 = c / 10000 % 10; / 百位temp2 = c / 100
34、0 % 10; / 十位temp3 = c / 100 %10; / 个位temp4 = c / 10 % 10; temp5 = c % 10;flag = 1;void keyscan()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
35、 = 0)while(key2=0);R = 2; / 100k 的电阻 量程5nf 500nfcon1 = 0;con3 = 1;con2 = 0;ledclc = 1;dispchar1(zimu3);dispchar2(zimu4);if(key3 = 0) / b5按下delay_ms(10);if(key3 = 0)while(key3=0);R = 3; con1 = 0; / 1k欧姆 的电阻 量程0.5uf 50ufcon2 = 0;con3 = 0;ledclc = 1;dispchar1(zimu3);dispchar2(zimu4);if(key4 = 0) / b6按下delay_ms(10);if(key4 = 0)while(key4=0);R = 4;con1 = 0; / 100欧姆 的电阻 量程50uf 500ufcon2 = 1;con3 = 0;ledclc = 1;dispchar1(zimu3);dispchar2(zimu4);ledlight(R);void ledlight(unsigned char R)if(1 = R)led1 = 1;led2 = 1;led3 = 1;led4 = 0;if