基于AT89C51与TCL2543的双通道采集电压表的设计
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
基于AT89C51与TCL2543的双通道采集电压表的设计
姓名:
学号:
专业:测控技术与仪器
2014年3月
基于AT89C51与TLC2543的数字电压表仿真设计
摘要:本文所设计的是一种以单片机AT89C51作为核心的数字电压表,利用美国ti公司生产的12位串行模数转换器件TLC2543来进行模数转换,并将所测电压值在四位一体七段数码管上显示出来,本文主要针对双通道的数据采集与显示,继而推广多通道数据采集的方法,重点分析介绍了基于AT89C51数字电压表的硬件设计和软件设计。
关键词:AT89C51 模数转换 TLC2543 双通道
1.引言
随着当今科学技术的不断发展和进步,电压测量已经成为电子工作和生活当中必不可少的手段,而且对测量的精度和范围也越来越高。
数字电压表主要是利用AD转换技术,将连续变化的模拟电压量转换成离散的数字量并加以显示出来的仪器。
本文将重点介绍TLC2543 AD转换器以及由它们构成的基于单片机的数字电压表的工作原理。
本文介绍了以AT89C51单片机为核心、以TLC2543为转换芯片采样、以四位一体七段数码管显示的具有一定精度电压测量的数字电压表。
2.硬件设计
该系统主要包括以下几个模块:时钟模块、复位模块、控制模块、A/D转换模块、以及显示模块,其中时钟模块和复位模块是必不可少的部分呢。
时钟模块选择频率为11.0592mhz的晶振,由于是在proteus仿真,则频率大小通过软件设置来完成。
复位模块包括上电复位和手动复位两种方式,按钮s1就是用来实现手动复位操作的。
控制模块比较简单,主要是以单片机AT89C51为控制核心,但是它要通过软件编写程序再载入单片机中,才能实现处理和控制功能。
A /D转换模块是本系统中最为关键的部分,它要实现将采集到的连续变化的模拟电压量转换成离散的数字量的功能,为此我们选择了TLC2543芯片,它是美国ti公司生产的12位串行模数转换器件,使用开关电容逐次逼近技术完成A/D转换过程。
由于是串行输入结构,可以节省AT89c51的I/O资源,且价格适中,分辨率较高,在仪器仪表中广泛应用。
显示模块采用四位一体7端BCD数码管来动态扫描显示。
AT89C51的P0口作为四位 LED 数码管动态显示的段码控制,P2.0~P2.3引脚作为四位LED数码管动态显示的位码控制。
3.AT89C51与TLC2543的简介
3.1AT89C51单片机
接口分配电路设计如右图2所示:
P0口:P0口为一个8位
漏级开路双向I/O口,被定
义为高阻输入。
P0能够用于
外部程序数据存储器,它可
以被定义为数据/ 地址的第
八位。
在这里P0口作为输出
和数码管显示的输入端相连,
且P0外部被阻值为1KΏ的
图2 单片机接口电路
电阻拉高。
P2口:这里只用到了P2.0~P2.3四个端口,其中P2.1~P2.3都是作为数码管显示的位选端口。
3..2 LC2543的使用方法。
3.2.1 控制字的格式
控制字为从DATAINPUT端串行输入的8位数据,它规定了TLC2543要转换的模拟量通道、转换后的输出数据长度、输出数据的格式。
3.2.2 转换过程
上电后,片选CS必须从高到低,才能开始一次工作周期,此时EOC为高,输入数据寄存器被置为0,输出数据寄存器的内容是随机的。
开始时,CS片选为高,I/O CLOCK、DATA INPUT被禁止,DATA OUT 呈高阻状,EOC为高。
4.软件设计
系统程序的内容一般包括:延时子程序、显示子程序、数据采集子程序、主程序等等。
主程序流程图见下图所示。
从单通道数据采集改为双通道数据采集,可以用中断来控制,也可以通过改写程序,使通道0采集的数据转换显示结束时,通道1所采集的数据通过A/D转换后正好显示,且显示时间均可人为的设定为能够被人眼分辨的频率。
开始
同时进行 同时
双通道数据采集主流程图
上电初始化
采集0通道的数据 A/D 模数转换 延时储存 数码管显示
采集通道1的数据
延时储存
数码管显示
A/D 模数转换
结束
5.仿真结果如下图
图1 系统硬件电路仿真图(通道0采集的数据)
图2 系统硬件电路仿真图(通道1采集的数据)
6 数据分析
6.1在上图1当中数码管显示的测量电压值是通道0采集的,数值是2.499V,而虚拟电压表的值是+2.50v;在上图2当中数码管显示的测量电压值是通道1采集的数值是 3.399V,而虚拟电压表的值是+3.40v经过多次测验,可以发现所设计的数字电压表的最大误差是0.001v,二者在同一个数码管上交替出现,满足任务要求。
7.结语
本次对数字电压表的软硬件设计,主要是在proteus中硬件仿真,将keil软件编译生成的hex程序文件加载到核心芯片中来实现的。
所设计的数字电压表可以测量0~5v的电压值,经过反复的测试和比较,得知所测电压值的最大误差是0.001v。
它具有结构简单、精度高、实用性强、操作简单的优点
参考文献
[1]刘敏娜,潘宏侠,王乔.基于51单片机的数字电压表仿真设计[j].山西电子技术,2011年第2期.
[2]郑锋.51单片机典型应用开发范例大全[m].北京:中国铁道出版社,2011
C语言源程序如下
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit CLK=P1^0;
sbit SDI=P1^1;
sbit SDO=P1^2;
sbit _cs=P1^3;
sbit EOC=P1^4;
sbit KEY=P3^2;
uchar a1,b1,c1,d1;
float sum,sum1;
double
sum_final1;
double
sum_final;
uchar duan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; uchar wei[]={0xf7,0xfb,0xfd,0xfe};
void delay(unsigned char b)
{
unsigned char a;
for(;b>0;b--)
for(a=22;a>0;a--);
}
void display(uchar a,uchar b,uchar c,uchar d) {
P0=duan[a]|0x80;
P2=wei[0];
delay(10);
P2=0xff;
P0=duan[b];
P2=wei[1];
delay(10);
P2=0xff;
P0=duan[c];
P2=wei[2];
delay(10);
P2=0xff;
P0=duan[d];
P2=wei[3];
delay(10);
P2=0xff;
}
uint read1(uchar port)
{
uchar i,al=0,ah=0; unsigned long ad; CLK=0;
_cs=0;
port<<=4;
for(i=0;i<4;i++) {
SDI=port&0x80; CLK=1;
CLK=0;
port<<=1;
}
SDI=0;
for(i=0;i<8;i++) {
CLK=1;
CLK=0;
}
_cs=1;
delay(5);
_cs=0;
for(i=0;i<4;i++) {
CLK=1;
ah<<=1;
if(SDO) ah|=0x01; CLK=0;
}
for(i=0;i<8;i++) {
CLK=1;
al<<=1;
if(SDO) al|=0x01; CLK=0;
}
_cs=1;
ad=(uint)ah;
ad<<=8;
ad|=al;
return(ad);
}
uint read2(uchar port) {
uchar i,bl=0,bh=0; unsigned long ad; CLK=0;
_cs=0;
port<<=4;
for(i=0;i<4;i++) {
SDI=port&0x80; CLK=1;
CLK=0;
port<<=1;
}
SDI=0;
for(i=0;i<8;i++) {
CLK=1;
CLK=0;
}
_cs=1;
delay(5);
_cs=0;
for(i=0;i<4;i++)
{
CLK=1;
bh<<=1;
if(SDO) bh|=0x01; CLK=0;
}
for(i=0;i<8;i++) {
CLK=1;
bl<<=1;
if(SDO) bl|=0x01; CLK=0;
}
_cs=1;
ad=(uint)bh;
ad<<=8;
ad|=bl;
return(ad);
}
void main()
{
uchar j;
sum=0;sum1=0;
sum_final=0;
sum_final1=0;
while(1)
{
if(KEY==0)
{
for(j=0;j<128;j++)
{
sum1+=read2(1);
display(a1,b1,c1,d1);
}
sum=sum1/128;
sum1=0;
sum_final1=(sum/4095)*5;
sum_final=sum_final1*1000;
a1=(int)sum_final/1000;
b1=(int)sum_final%1000/100;
c1=(int)sum_final%1000%100/10; d1=(int)sum_final%10;
display(a1,b1,c1,d1);
}
else
{
for(j=0;j<128;j++)
{
sum1+=read1(1);
display(a1,b1,c1,d1);
}
sum=sum1/128;
sum1=0;
sum_final1=(sum/4095)*5;
sum_final=sum_final1*1000;
a1=(int)sum_final/1000;
b1=(int)sum_final%1000/100;
c1=(int)sum_final%1000%100/10; d1=(int)sum_final%10;
display(a1,b1,c1,d1);
}
}
}。