课程名称: 数字万用表的设计专业:电子信息工程班级:0学号:姓名:指导教师:目录1 、设计任务 (3)1.1设计目的 (3)1.2设计指标及要求 (3)2、设计思路与总体框图 (3)3、系统硬件电路的设计 (4)3.1主控芯片 (4)3.2模数转换部分 (4)3.3 电阻测量输入电路 (6)3.4电压测量输入电路 (7)3、5电流输入测量电路 (9)3.6 自锁开关 (10)4、软件设计 (10)4.1主程序设计 (10)4.2 A/D转换子模块 (11)5、系统调试 (11)5.1硬件调试 (11)5.2 硬件故障 (11)5.3硬件调试方法 (12)5.4软件调试 (12)5.5软件故障 (12)5.6软件调试方法 (12)6 实验数据处理 (12)6.1实验数据 (12)6.2实验数据分析 (13)7总结与体会 (13)7.1总结 (14)7.2体会 (14)8 参考文献 (14)9 附录——程序 (14)1、设计任务1.1设计目的采用A/D转换器ADC0804和STC89C51单片机,设计一台数字多用表,能进行电压、电流和电阻的测量,测量结果通过LCD液晶显示器显示,通过按键进行测量功能转换。
1.2设计指标及要求电压测量范围0~20V,测量误差约为 0.05V,电流测量范围1~200mA,测量误差约为±0.5mA,电阻测量范围0~1000Ω,测量误差约为±2Ω。
2、设计思路与总体框图1.方案选择用单片机STC89C51与ADC0804设计一个数字万用表,配合分流电阻、分压电阻、基准电阻可以测量直流电压值,直流电流、直流电阻,四位数码显示。
实现各级量程的直流电压测量,其量程范围为0—20(V)。
实现不同量程的直流电流测量,其量程范围为0—200(mA)。
实现不同量程的电阻测量,其量程范围为0—1000(Ω)。
ADC0804是带有8位A/D转换器、8路多路开关以及微处理机兼容的控制逻辑的CMOS组件。
它是逐次逼近式A/D转换器,可以和单片机直接接口。
首先,利用P1 口数据地址复用,将地址通过P1口输入到单片机中。
然后,充分利用单片机强大的运算转化功能将其转成适当的二进制信号控制数显以确保正确的显示被测量的读数。
2.总体框图图一:总体框图3、系统硬件电路的设计3.1主控芯片本电压表采用STC89C52为主控芯片,电路如下图所接:3.2模拟转换部分该电压表采用的ADC0804,此芯片优点是并行输出,速率快,缺点是只有8位,精度不高。
下来ADC0804芯片图:单片机的P2.0 ~P2.2引脚通过一个转换开关接地,通过判断P2.0 ~P2..2引脚电平的高低,决定是否进行电阻测量、电压测量或电流测量。
为了方便,将数字地和模拟地都直接接到了一起,DB0~DB7为并行输出口,CS,RD,WR为控制芯片模数转换及读取芯片数据和写数据的引脚,ADC0804可以自己产生时钟,只要在CLKR和CLKIN端接入电阻(10K)和电容(理论为150pf本人接的220pf),可产生脉冲信号。
VREF为参考电压端,VIN+和VIN-为电压输入端。
当电压加在VIN+和VIN-端时,在DB0~DB7可输出八位到单片机,本处参考电压为5V,则当输入电压U时,输出数据为temp,则U/temp=5/255.3.3数字多用表电阻输入电路图-二图-二所示为数字多用表的电阻测量输入电路。
运算放大器的反馈电阻Rx作为待测电阻,通过1K电阻R10接到5V电源上,那么放大器的输出电压Rv=5*Rx/(Rp+R15+R0+Rx),将Rv送给ADC0804,转换后得到数字量为Dv=Rv*255/5。
单片机读取A/D转换数据,再经过逆向运算可得Rx=Dv*(R1p+R0+R15)/[(5-Dv)*255],注意此时得到的Rx是二进制数,需要转化成十进制数后才能送给1602显示,程序中采取用4字节无符号除法,连续进行4次除以10的除法,依次取得4位数值,并且电阻测量范围只保证在0~1KΩ范围内误差不超过2Ω,如果要测量其他电阻,则需该改Rp 的值。
3.4数字多用表的电压测量输入电路图-四图-四所示为数字多用表的交流电压测量输入电路,ACV量程为0~12V待测电压经交流电压测量图过低通滤波器滤除干扰,再经过同向放大器送给ADC0804,电压测量输入范围0~12V,ADC084的分辨率为8位,测量误差为12/255=0.05V。
D5为整流管,D4起保护作用。
R24、C6组成平滑滤波器。
C5、C4为隔直电容。
Uout=Uac(有效值)图-五直流电压测量图图-五直流电压测量电路。
DCV量程为0~12V。
Uout=R8*U/(R7+R8+R11),所以,U=(R7+R8+R11)* Uout/R8。
R7和R8为分压电阻,大小都为10M。
R11为匹配电阻,保证等值分压。
R13为限流电阻,大小为1M。
3.5数字万用表的电流测量输入电路图-六电流测量电路图图-六是数字万用表电流测量输入电路。
电流测量范围为1-200mA,因为ADC0804是电压转化器,必须将电压才能进行测量,这可以通过串接电阻RP来实现,注意RP必须很小(如0.1Ω),否则营销电流数值,由于待测电流和RL都很小,RL两端的电压也很小,必须将其放大到ADC0804能够分辨的范围之内。
R12为限流电阻,大小为1M。
D2,D3为双向限幅过压保护二极管,起过流保护作用。
3.6 自锁开关图-七自锁开关图用来控制测量哪一种变量,同时用来检测正测的信息,通过导线送入到单片机。
上面接10K的限流电阻。
4、软件设计4.1主程序主程序包括初始化部分调用A/D转换子程序和调用显示程序,如下图所示:4.2 A/D转换子模块:A/D转换子程序用于对ADC0804八路输入模拟电压进行A/D转换,并将转换的数值存入八个相应的存储单元中,如下图:5、系统调试基于单片机的数字电压表在组装好以后,便可进入系统的在线调试,起主要任务是排除样机硬件故障并完善其硬件结构,试运行所设计的程序,排除程序错误,优化程序结构,使系统达到预期的功能,进而固化软件。
5.1硬件调试单片机应用系统的硬件和软件调试时交叉进行的,但通常是先排除样机中明显的硬件故障,尤其是电源故障,才能安全和仿真器相连,进行综合调试。
5.2 硬件电路故障(1)错线开路短路;(2)元器件损坏(3)电源故障5.3 硬件调试方法本设计调试中所用的调试方法是静态测试:在样机加电之前,首先用万用表等工具,根据硬件电器原理图和装配图仔细检查样机线路的正确性,并核对元器件的型号规格和安装是否符合要求。
第二步是加电后检查各插件上引脚的点位,仔细测量各电位是否正常。
第三步是在不加电的情况下,除单片机以外,插上所有的元器件,最后用仿真适配器将样机的单片机插座盒仿真器的仿真接口相连,为联机调试做准备。
5.4 软件调试5.5 软件电路故障(1)当以断点或连续方式运行时,目标系统没有按规定的功能进行操作或什么结果也没有,这是由于程序转移到意外之外或在某处死循环所造成的。
(2)结果不正确5.6 软件调试方法软件调试所使用的方法有:计算程序的调试方法,I/O处理程序的调试法,综合调试法6、实验数据处理6.1实验数据0—12直流电压为 0—12交流电压为次数标准值电压示值满度误差次数标准值电压示值满度误差1 12 23 34 45 56 67 78 89 910 1011 1112 1213 1314 1415 151617181920实验数据0-1K电阻为 0-200mA电流为次数标准值电压示值满度误差次数标准值电压示值满度误差1 12 23 34 45 56 67 78 89 910 1011 1112 1213 1314 1415 1516171819206.2实验数据分析直流0-12V量程精度为满度误差为交流0-21V量程精度为满度误差为电流0-200mA量程精度为满度误差为7、总结与体会数字多用表的课程设计,从确定方案、查找资料、仿真电路图,到最后电路设计实践,耗时2个星期。
数字多用表的设计方案采取STC89C51单片机结合A/D转换器,从而实现对电阻、电流和电压的测量的方案,从而实现电阻、电流和电压的数字化测量。
本次课程设计,虽然方案基本出来了,但是在硬件制作方面出现了几个问题,这也暴露出我们知识方面的一欠缺。
不足主要体现在以下几个方面:(1)ADC0804的第10脚的时钟信号,我们是通过单片机编程实现的但是由于频率过低,只有500KHz,造成1602液晶显示器显示不稳定而出现闪烁现象。
最终验收时是通过从外部信号发生器输入2MHz时钟信号解决的。
(2)万用板焊接时,由于布线不太合理,使得背面线很零乱。
并给后面的线路检查带来了不少麻烦。
(3)51单片机基础知识不扎实,电路分析遇到比较多的问题历经两个星期的课程设计后我深得做课程设计同时也是对课本知识的巩固和加强,由于课本上的知识太多,平时课间的学习并不能很好的理解和运用各个元件的功能,而且考试内容有限,所以在这次课程设计过程中,我们了解了很多元件的功能,并且对于其在电路中的使用有了更多的认识。
虽然最终的结果让人失望,但在此期间我们也曾一度热情高涨。
从开始时满8、参考文献《单片机原理及应用》张毅刚主编高等教育出版社《单片机原理实用教程》徐爱钧编著电子工业出版社《电子技术基础》康华光主编高等教育出版社《集成电路原理及应用》谭博学、苗汇静主编电子工业出版社9、附录——程序主程序:#include<reg52.h> //头文件#include<intrins.h>//头文件#include<definedvm.h>#include<delay.h>#include<warning.h>#include<1602.h>#include<keyscan.h>#include<AD.h>#include<display.h>void main(){while(1){write_com(0x01);lcd_init();display_voltage();}}1、宏定义和定义变量:#define uchar unsigned char //宏定义#define uint unsigned intuchar table[]=" measurement: ";uchar range20[]="RANGE0~20V: ";uchar range200[]="RANGE0~200mA: ";uchar range2000[]="RANGE0~2K:";uchar warning[]="Please Choice! ";/*uchar error[]="error!"; */uint measure[10];sbit key3=P2^7;sbit key0=P2^2;sbit key1=P2^1;sbit key2=P2^0;sbit lcd_rs=P2^3; // 定义液晶的rs端口sbit lcd_rw=P2^4; // 定义液晶的rw端口sbit lcd_en=P2^5;sbit back=P2^6;sbit spk=P2^7; // 定义液晶的en端口sbit cs=P3^2; // 定义AD的cs端口sbit rd=P3^1; //定义AD的rd端口sbit wr=P3^0;//sbit dula=P3^7;sbit INTR=P3^7; //定义AD的wr端口uint temp,i,A1,A2,A3,A4; //定义变量uint date;2、延时部分:void delay(uint z){uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}void delay_lcd()//1602指令之间延时{uint x=5;while(x--);}3、AD转换和数据传送:void AD_init() //初始化ADC0804{cs=0;wr=1;_nop_();wr=0;_nop_();wr=1;}uint AD_switch() //AD转换部分{uint temp;P1=0xff;rd=1;_nop_();rd=0;_nop_();temp=P1;//将转后的原始值返给单片机P1口return temp;}uint AD_smooth()//软件滤波{uint xx,i,temp;AD_init();for(i=0;i<20;i++){measure[i]=AD_switch();delay(10); //每隔10us ADC转换并采集一次数据,将得} //到的数据放到数组中,采集十个数据for(xx=0;xx<20;xx++) //将十个数据冒泡法排序for(i=xx;i<20;i++){if(measure[xx]>measure[i]){temp=measure[i];measure[i]=measure[xx];measure[xx]=temp;}}for(i=6;i<16;i++)//去掉了三个最小值和两个最大值,{ //取中间五个数的平均值xx+=measure[i];}xx=xx/10;return xx; //将滤过波后的值存入单片机}4、1602子程序:void write_com(uchar com)//写指令{delay(5);lcd_en=0;lcd_rs=0;lcd_rw=0;_nop_();lcd_en=1;P0=com;lcd_en=0;lcd_rs=0;}void write_date(uchar date)//写数据{delay(5);lcd_en=0;lcd_rs=1;lcd_rw=0;_nop_();lcd_en=1;P0=date;lcd_en=0;lcd_rs=0;}void lcd_init()//初始化{back=0;delay(15);lcd_en=0;write_com(0x38);write_com(0x38);write_com(0x38);write_com(0x06);write_com(0x0c);write_com(0x01);}5、键盘扫描:uint keyscan(){if(key0==0&&key1==1&&key2==1&&key3==1)return 1;else if(key0==1&&key1==0&&key2==1&&key3==1)return (2);else if(key0==1&&key1==1&&key2==0&&key3==1)return (3);else if(key0==1&&key1==1&&key2==1&&key3==0)return (4);else if(key0==1&&key1==1&&key2==1&&key3==1)return(5);else return (6);}6、数据整理及显示:void display20V(uint temp)//量程为20V时的显示状态{uint num0,num1,num2,num3;if(temp<7) temp=0;else temp=temp-7;num0=temp/51;num1=temp%51*10/51;num2=temp%51*10%51*10/51;num3=temp%51*10%51*10%51*10/51;write_com(0x80+0x40+11);write_date(num0+0x30);delay_lcd();write_com(0x80+0x40+12);write_date('.');delay_lcd();write_com(0x80+0x40+13);write_date(num1+0x30);delay_lcd();write_com(0x80+0x40+14);write_date(num2+0x30);delay_lcd();write_com(0x80+0x40+15);write_date(num3+0x30);delay_lcd();}void display200mA(uint temp)//电流200mA时的显示状态{uint num0,num1,num2,num3;if(temp<7) temp=0;else temp=temp-7;num0=temp/510;num1=temp%51*10/510;num2=temp%51*10%51*10/510;num3=temp%51*10%51*10%51*10/510;write_com(0x80+0x40+11);write_date(num0+0x30);delay_lcd();write_com(0x80+0x40+12);write_date('.');delay_lcd();write_com(0x80+0x40+13);write_date(num1+0x30);delay_lcd();write_com(0x80+0x40+14);write_date(num2+0x30);delay_lcd();write_com(0x80+0x40+15);write_date(num3+0x30);delay_lcd();void display2000(uint temp)//量程为2000欧时的显示状态{uint num0,num1,num2,num3;if(temp<7) temp=0;else temp=temp-7;num0=temp/51;num1=temp%51*10/5.1;num2=temp%51*10%51*10/5.1;num3=temp%51*10%51*10%51*10/5.1;write_com(0x80+0x40+11);write_date(num0+0x30);delay_lcd();write_com(0x80+0x40+12);write_date('.');delay_lcd();write_com(0x80+0x40+13);write_date(num1+0x30);delay_lcd();write_com(0x80+0x40+14);write_date(num2+0x30);delay_lcd();write_com(0x80+0x40+15);write_date(num3+0x30);delay_lcd();void display_voltage(){uint numx,temp,temp0,temp1;//float temp;numx=keyscan();temp0=numx;for(i=0;i<16;i++){write_com(0x80+i);write_date(table[i]);delay_lcd();}if(numx==1){for(i=0;i<11;i++){write_com(0x80+0x40+i);write_date(range20[i]);delay_lcd();}}else if(numx==2){for(i=0;i<11;i++){write_com(0x80+0x40+i);write_date200mA(range[i]);delay_lcd();}}else if(numx==3){for(i=0;i<11;i++){write_com(0x80+0x40+i);write_date(range2000[i]);delay_lcd();}}else if(numx==4){for(i=0;i<11;i++){write_com(0x80+0x40+i);write_date(range20[i]);delay_lcd();}}else if(numx==5){for(i=0;i<16;i++){write_com(0x80+0x40+i);write_date(warning[i]);delay_lcd();}}else break;while(temp0<=4&&numx!=5&&numx!=6){temp=AD_smooth();if(temp<5) temp=0;if(numx==1)display20V(temp);numx=keyscan();//if(numx==5) break;if(numx==2)display200mA(temp);if(num==3)display2000(temp)if(num==4)display20V(temp)numx=keyscan();while((temp1-temp<7||temp-temp1<7)&&temp1==numx) {temp=AD_smooth();numx=keyscan();}}。