资源描述
s
南 湖 学 院
《数字电路课程设计》设计汇报
项目名称: 数字电压表课程设计
专业年级: 10级电信1班
所在院系: 湖南理工学院南湖学院
学生姓名: 戴 思
学 号: 2410223
完成时间: 11月12日
目 录
一、 设计任务
二、 硬件设计
三、 软件设计
四、 系统调试
五、试验数据处理
六、设计安装及调试中体会
七、参考文件
附录:源程序代码
一、 设计任务
基于51单片机,以ADC0804芯片实现模数转换,由1602液晶屏显示,含有量程变换功效。
量程转换模块
ADC0804模数转换模块
单片机控制模块
1602LED显示模块
上电复位
串口通信
ADC0804
1602LED显示
电源电路
AT89C51
P0
P2
P1
P3
二、硬件设计
2.1主控芯片
本电压表采取STC89C52为主控芯片,电路以下图所接:
晶振电路和复位电路略去,端口和上面各图接口是一致。
2.2模拟转换部分
该电压表采取ADC0804,此芯片优点是并行输出,速率快,缺点是只有8位,精度不高。下来ADC0804芯片图:
为了方便,将数字地和模拟地全部直接接到了一起,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.在自然状态下,最多也只能测5V电压,为了扩大量程,本人加了衰减网络,见下图:
接到ADC芯片上面一直是VIN和地之前电压,为了调精度,在上面加了滑动变阻器。此处R22选择是470K欧,首先选10K,因为内阻过小,造成在5V以下电压测量不正确,choice和GND两端为外加电压,这么,有部分电压会在R20或R21上分压,只在确保在R22两端不超出5V,就可实现多量程电压测量。
2.3显示模块
本处用1602液晶显示,1602优点是价格廉价,可显示基础字符,对于做电压表这么东西已足够。电路以下:
三、软件设计
3.1主程序
主程序包含初始化部分 调用A/D转换子程序和调用显示程序,以下图所表示:
3.2 A/D转换子模块:
0804地址加1
A/D转换子程序用于对ADC0804八路输入模拟电压进行A/D转换,并将转换数值存入八个对应存放单元中,以下图: 开始
开启一次转换
取数据(OE=1)
A/D转换结束?
地址小于8
返回
四、系统调试
基于单片机数字电压表在组装好以后,便可进入系统在线调试,起关键任务是排除样机硬件故障并完善其硬件结构,试运行所设计程序,排除程序错误,优化程序结构,使系统达成预期功效,进而固化软件。
4.1硬件调试
单片机应用系统硬件和软件调试时交叉进行,但通常是先排除样机中显著硬件故障,尤其是电源故障,才能安全和仿真器相连,进行综合调试。
4.1.1 硬件电路故障
(1)错线 开路 短路;
(2)元器件损坏
(3)电源故障
4.1.2 硬件调试方法
本设计调试中所用调试方法是静态测试:
在样机加电之前,首先用万用表等工具,依据硬件电器原理图和装配图仔细检验样机线路正确性,并查对元器件型号 规格和安装是否符合要求。第二步是加电后检验各插件上引脚点位,仔细测量各电位是否正常。第三步是在不加电情况下,除单片机以外,插上全部元器件,最终用仿真适配器将样机单片机插座盒仿真器仿真接口相连,为联机调试做准备。
4.2软件调试
4.2.1软件电路故障
(1)当以断点或连续方法运行时,目标系统没有按要求功效进行操作或什么结果也没有,这是因为程序转移到意外之外或在某处死循环所造成。
(2)结果不正确
4.2.2软件调试方法
软件调试所使用方法有:计算程序调试方法,I/O处理程序调试法,综合调试法。
五、试验数据处理
5.1试验数据
0-5V量程为
0-50V量程
次数
标准值
电压示值
满度误差
次数
标准值
电压示值
满度误差
1
0.76
0.725
0.70%
1
1.34
1.5
0.52%
2
1.11
1.078
0.64%
2
2.35
2.5
0.30%
3
1.66
1.627
0.66%
3
4.42
4.7
0.56%
4
1.99
1.960
0.60%
4
7.17
7.1
0.14%
5
2.17
2.156
0.28%
5
10.6
10.1
1.00%
6
2.46
2.450
0.20%
6
13.0
12.9
0.20%
7
2.70
2.686
0.28%
7
14.6
14.4
0.40%
8
2.85
2.843
0.14%
8
16.7
16.1
1.00%
9
3.03
3.019
0.22%
9
18.2
17.6
1.20%
10
3.15
3.156
-0.12%
10
19.5
18.9
1.20%
11
3.09
3.098
-0.16%
11
21.7
21.2
1.00%
5.2试验数据分析
0-5V量程精度为0.001V, 满度误差均<1.00%,为一级电压表
0-50V量程精度为0.1V,满度误差均<2.50%,为2.5级电压表
六、设计安装及调试中体会
数字电压表作为一个实用电子系统,已经得到广泛应用。掌握数字电压表基础原理,研究并不停改善系统功效。这些是我们初涉者们努力方向。本系统采取石英晶体振荡器、分频器、计数器、显示器和校时电路组成。由LED数码管来显示译码器所输出信号。实现了数字钟时、分、秒显示,手动较时、校分功效。有很强现实应用性能。而数字钟设计开拓了我们视野,锻炼了我们动手能力。
我想就整个制作数字电压表过程做部分总结。怎样设计原理图,怎样检错,怎样进行PCB单面板布线,怎样制作单面板,怎样调试电路,每一步骤全部不能忽略,而且每一步骤全部应为下一步骤做计划,不应开始没弄好就想下面怎么做这么做就行了,这么给后期工作带来难度更大。
第一步也是最关键一步就是原理图设计,首先要确保原理图是正确,不然后面做全部是无用功,画原理图即使不难,不过绝对不能忽略。接着导入PCB板,而导入PCB板时必需确保无误。而手工布线时,摆放好元件也是很关键,为布线提供方便。而布线时又要考虑到板子做出来效果,将焊盘尽可能调大,线尽可能布粗,电源线和地线要比信号线稍微粗一点,而且尽可能避免线经过焊盘,以免焊接时出现短路。布线很烦很乱很耗时间,很轻易泄气,不过一定要坚持,不然前功尽弃。制作PCB板时要避免出现断线,断线给调试带来很大不便,腐蚀工作也要做好。焊接器件时要使板子进尽可能美观,而且焊好每一个结点。调试是收尾工作,却也是决定成败关键,调试成功了便制作成功了,假如调试不成功,则看不到效果。这也是最让人遗憾。调试最是让人头痛也是最耗时间事情。这也是动手能力最强工作,需要耐心,需要毅力,这个过程也能使我们更深入熟悉电路板,并了解电路设计原理,不然是没法调试,要一级一级地调试,其实只要前期做得好,调试工作就不难。该清楚每一级输出情形,根据这个情形去调试,直到满足要求,而要考虑到原因很多。我认为最先要做是确保测量仪器是好,不然会做很多无用功甚至陷入深渊,接着首要是确保地线跟电源线正确输入。要检验电路,要检验焊盘是否焊好,要测试元件是好是坏,要检验有没有断线等等。
总而言之整个工作很费时,很麻烦,不过当看到自己数字电压表实现时候却是最快乐一件事。而学我们这个专业同学又必需要掌握这么难得机会,还有老师指导,还有同学能够讨论。从这次课程设计中我获益匪浅。同时也总结了几点。首先电路设计是细致活,切不可大意,要有足够耐心和毅力,同时这也是建立在爱好之上。
七、参考文件
1、 华中科技大学电子技术课程组编,康华光主编,电子技术基础数字部分(第五版).高等教育出版社,
2、 谢自美主编.电子线路设计试验第三版.华中科技大学出版社,
3、 张肃文,陆兆熊.高频电子线路(第三版).北京高等教育出版社,1993年
附录一:源程序代码
主程序:
#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 int
uchar table[]=" measurement: ";
uchar range5[]="RANGE0~20V: ";
uchar range50[]="RANGE0~2A: ";
uchar range500[]="RANGE0~100K:";
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; // 定义ADcs端口
sbit rd=P3^1; //定义ADrd端口
sbit wr=P3^0;
//sbit dula=P3^7;
sbit INTR=P3^7; //定义ADwr端口
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 display5V(uint temp)//量程为5V时显示状态
{
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 display50V(uint temp)//量程为50V显示状态
{
uint num0,num1,num2,num3;
//if(temp<7) temp=0;
//else temp=temp-7;
temp=(temp+temp*4/10)*11;
num0=temp/510;
num1=temp%510*10/510;
num2=temp%510*10%510*10/510;
num3=temp%510*10%510*10%51*10/510;
write_com(0x80+0x40+11);
write_date(num0+0x30);
delay_lcd();
write_com(0x80+0x40+12);
write_date(num1+0x30);
delay_lcd();
write_com(0x80+0x40+13);
write_date('.');
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||numx==4)
{
for(i=0;i<11;i++)
{
write_com(0x80+0x40+i);
write_date(range5[i]);
delay_lcd();
}
}
else if(numx==2)
{
for(i=0;i<11;i++)
{
write_com(0x80+0x40+i);
write_date(range50[i]);
delay_lcd();
}
}
else if(numx==3)
{
for(i=0;i<11;i++)
{
write_com(0x80+0x40+i);
write_date(range500[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 beep();
while(temp0<=4&&numx!=5&&numx!=6)
{
temp=AD_smooth();
if(temp<5) temp=0;
if(numx==1)
display5V(temp);
numx=keyscan();
//if(numx==5) break;
if(numx==2)
display50V(temp);
numx=keyscan();
while((temp1-temp<7||temp-temp1<7)&&temp1==numx)
{
temp=AD_smooth();
numx=keyscan();
}
}
while(numx==6||numx==5)
{
numx=keyscan();
while(numx==6)
{
numx=keyscan();
beep();
}
}
}
展开阅读全文