数据采集器的设计实验报告.docx

上传人:b****0 文档编号:25877884 上传时间:2023-06-16 格式:DOCX 页数:25 大小:232.40KB
下载 相关 举报
数据采集器的设计实验报告.docx_第1页
第1页 / 共25页
数据采集器的设计实验报告.docx_第2页
第2页 / 共25页
数据采集器的设计实验报告.docx_第3页
第3页 / 共25页
数据采集器的设计实验报告.docx_第4页
第4页 / 共25页
数据采集器的设计实验报告.docx_第5页
第5页 / 共25页
点击查看更多>>
下载资源
资源描述

数据采集器的设计实验报告.docx

《数据采集器的设计实验报告.docx》由会员分享,可在线阅读,更多相关《数据采集器的设计实验报告.docx(25页珍藏版)》请在冰豆网上搜索。

数据采集器的设计实验报告.docx

数据采集器的设计实验报告

数据采集器的设计实验报告

 

 

————————————————————————————————作者:

————————————————————————————————日期:

 

单片机项目实践报告

 

数据采集器的设计

 

班级:

计应102

姓名:

潘琴

学号:

1008143233

 

一、项目名称:

数据采集器的设计

二、项目目的:

了解A/D转换的基本概念、并行A/D转换芯片ADC0809的内部结构、与单片机的接口方式,在此基础上完成数据采集器的设计与调试。

以及SPI总线的串行A/D转换芯片TLC549、串行D/A转换器件TLC5615,完成数字电压表、信号发生器的设计。

最后是用单片机的定时器/计数器实现频率与周期的测量,将被测信号的周期或频率在液晶屏上显示出来。

三、项目过程:

1、数据采集器的设计

1、1、ADC0808/0809的内部结构

STARTCLK

IN0

IN1

IN2

IN3

IN4

IN5

IN6

IN7

EOC

A

B

C

ALE

Vcc

GND

D0

D1

D2

D3

D4

D5

D6

D7

Vref(+)Vref(—)OE

图1、ADC0808/0809内部逻辑结构

1、2、数据采集器的设计过程

在Proteus环境下,用ADC0808设计一个数据采集器,通过串行口与上位机相连,如果串行口收到了上位机的采集命令(0x41),就将8路模拟量转换为数字量,通过串行口以ASCII码的形式发送给上位机.

1、2、1、硬件电路

如图所示,ADC0808的时钟信号CLK由Proteus的虚拟信号源提供,时钟频率的设置为600kHz;8路模拟量中IN0接Vcc,IN7接地,其他6路通过电位器分压获得;单片机串行口的数据收发线与虚拟终端连接.需要说明的是Proteus中ADC0808的数据线,OUT1表示最高位,OUT8表示最低位.

1、2、2、程序设计

程序的流程如图所示,主程序首先完成对串行口和外部中断的初始化,并等待上位机的采集命令,一旦收到采集命令,就启动对IN0的转换。

转换完成,ADC0808通过EOC向单片机发出中断请求,单片机响应中断,读取转换结果,并将其保存到数组adbuf中。

然后启动下一通道的转换,当8路模拟量全部采集完成时,主程序再将存放在数组adbuf中的8路数字量转换为ASCII码,通过串行口发送出去,为了能在虚拟终端上得到清楚的显示格式,相邻两路数字量之间输出空格码,每行显示8个数字量后,输出回车、换行码。

数据采集器的程序:

#include

h〉

#include〈absacc.h〉

#defineuintunsignedint

#defineucharunsignedchar

ucharidataadbuf[8];//存放A/D转换结果

uintaddr;//IN0~IN7的通道地址

ucharn;//通道计数

voidinit_serial(void)

{SCON=0x50;//0101,00008位数据位,无奇偶校验

TMOD=0x20;//定时器T1工作于方式2

PCON=PCON&0x7f;//SMOD=0

TH1=—3;//装入时间常数,波特率为9600

TL1=-3;

TR1=1;}/启动定时器T1

voidsend(uchardat)

{SBUF=dat;

while(TI==0);

TI=0;}

voidint0(void)interrupt0

{adbuf[n]=XBYTE[addr];//读取并保存当前转换结果

addr++;//指向下一通道的地址

n++;//计数器加工厂

if(n〈8)

XBYTE[addr]=0;//启动对一一通道的转换

else

EX0=0;}

voidgetadc(void)

{n=0;

addr=0x7ff8;//指向IN0通道的地址

XBYTE[addr]=0;//启动对当前通道的转换

EX0=1;//允许外部中断0中断

while(n〈8);}//等待8路模拟量转换完成

voidmain()

{uchari;

init_serial();//初始化串行口

IT0=1;//外部中断0下降沿触发

EA=1;//开中断

while

(1)

{while(RI==0);//等待接收完一个字符

RI=0;//清除接收标志

i=SBUF;//读取收到的字符

if(i==0x41)

{getadc();//依次完成对8个通道模拟量的转换

for(i=0;i<8;i++)

{send(adbuf[i]/100+0x30);//发送百位的ASCLL码

adbuf[i]=adbuf[i]%100;

send(adbuf[i]/10+0x30);//发送十位的ASCLL码

send(adbuf[i]%10+0x30);//发送个位的ASCLL码

send(0x20);//发送空格码

send(0x20);}

send(0x0d);//发送回车、换行

send(0x0a);}

1、2、3、调试方法与步骤

在Keil下建立项目,输入源程序,编译后进入调试方式全速运行,在虚拟终端的窗口中输入大写字母“A",此时8路模拟量转换结果会在一行中显示出来,依次为IN0、IN1、…、IN7,由于IN0接+5V,IN7接地,因此对应的显示值为255和000,而IN1~IN6的值由电位器RV1中心抽头的位置确定,调节RV1,然后在虚拟终端的窗口中输入大写字母“A”,IN1~IN6的值将随之变化.

如果在虚拟终端的窗口无任何显示,首先应检查串行口的初始化是否正确、虚拟终端的波特率是否与串行口一致、串行口能否收到采集命令“A"。

如果串行口能收到采集命令,应检查外部中断的初始化是否正确、启动信号START、转换结束信号EOC、输出允许信号OE的连接是否正确,ADC0808的时钟CLOCK设置不正确,也将无法完成A/D转换。

如果程序能够将IN0~IN7的转换结果存入数组adbuf,应重点检查串行口数据发送函数send()。

2、数字电压表的设计

2、1、8位串行A/D转换器TLC549

REF+

REF—

AIN

CS

CLK

DO

TLC549内部结构

2、2、数字电压表的设计过程

利用TCL549转换器设计一个简易数字电压表,用4位LED显示器将被测电压显示出来,测量范围为0。

000~5.000V(电路连接:

将ACS、ACLK、ADO分别与P10~P12相连).

2、2、1、硬件电路

如图所示,将TLC549的CS、CLK、DO接到单片机的三条I/O口线,REF+、REF-直接接到Vcc、GND,模拟输入AIN接电位器的中心抽头,调节电位器即或改变被测输入电压值.

2、2、2程序设计

程序首先读取A/D转换结果存入adin,其值在0~255之间,对应的电压值u=adin/255*5000(mV),然后将u转换为4位BCD码送显示缓存,并调用显示程序将显示出来,小数点固定在最高位.数字电压表的设计程序:

#include

h>

#defineucharunsignedchar

#defineulongunshgnedlong

ucharcodesegtab[]=

{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,

0x88,0x83,0xc6,0xa1,0x86,0x8e,0x89,0x8c,0xff};

uchardbuf[4]={0,0,0,0};

sbitAD_CS=P1^0;

sbitAD_CLK=P1^1;

sbitAD_DAT=P1^2;

bdataucharadin;

sbitadin0=adin^0;

voiddelay(void)

{uchari;

for(i=0;i<20;i++);}

uchargetad(void)//A/D转换程序

{uchari;

AD_CS=0;//令CS为低选中TLC549

delay();//延时

for(i=0;i<8;i++)//循环读取8位A/D转换结果

{AD_CLK=0;//令CLK引脚为低

adin=adin<〈1;//先读取高位,后读取低位

adin=AD_DAT;//读取数据线的一位数据

AD_CLK=1;}//令CLK恢复为高位

AD_CS=1;

returnadin;}

voiddisp(void)

{uchari,n,bsel;

bsel=0xfe;//首先点亮最低位

for(n=0;n〈4;n++)

{P2=bsel;//位选口

P0=segtab[dbuf[n]];//将显示缓存的数据转换为字段码显示

if(n==3)P0=P0&0x7f;//点亮最高位的小数点

bsel=(bsel<〈1)+1;//准备显示下一位

for(i=1;i〈200;i++);//延时

P0=0xff;}//熄灭所有字段

voidmain()

{ulongu;

uchari;

while

(1)

{u=(ulong)getad()*5000/255;//将转换结果换成电压值

for(i=0;i<3;i++)//转换为4位BCD码送显示缓存

{dbuf[i]=u%10;

u=u/10;}

dbuf[3]=u;

disp();}//显示电压值

2、2、3、调试方法

在Keil下建立项目,输入源程序,编译后进入高度方式全速运行,数码管将以“X.XXX”的格式显示当前测量的电压值,调节电位器,数码管上的电压值将随之而变化.

如果数码管没有显示,应首先检查显示及显示函数。

注意,将电压值u转换成BCD码送显示缓存如果出问题,也会影响显示结果。

如果数码管能正常显示,但显示的电压值与实际值不同,一般A/D转换程序有问题,可重点检查getad()函数,如果电位器W的中心抽头从最低调到最高,该函数返回的A/D转换结果也相应地由0x00变化到0xFF,说明A/D转换是对的,应检查语句“u=(ulong)getad()*5000/255;”以及随后的BCD码转换程序.

3、信号发生器的设计

3、1、串行D/A转换器TLC5615

REFIN

AGND

Vcc

CS

SCLK

DIN

DOUT

OUT

TLC5615内部结构

3、2、用TLC5615设计信号发生器的过程

3、2、1、在Proteus环境下,用TLC5615设计一个锯齿波发生器。

(1)、硬件电路

如图所示,将TLC5615的SCLK、CS、DOUT分别与单片机的P1。

0、P1。

1、P1.2相连,基准电压接+5V。

(2)、程序设计

为了产生锯齿波,可定义一个用于计数的字符变量n,其值由0开始加1,每次加1后就将其输出,由TLC5615转换为相应的电压值,当n为255时,再加1又回到0,这样就实现了一个周期的转换.程序如下:

#include〈reg51.h〉

#include

h〉

#defineucharunsignedchar

#defineuintunsignedint

sbitSCLK=P1^0;//时钟输入

sbitCS=P1^1;//片选信号

sbitDIN=P1^2;//串行数据输入

voiddatout(uintdat)//向TL5615输出16位数据

{uchari;

CS=1;//初始化片选信号为高

SCLK=0;//初始化时钟为低

CS=0;//选中TL5615

for(i=0;i<16;i++)

{dat=dat<<1;//将最高位移入进位位CY

DIN=CY;//将数据送到DIN引脚

SCLK=1;//SCLK产生上升沿

SCLK=0;}//SCLK恢复为低

CS=1;}//片选信号恢复为高

voidmain(void)

{uchari=0;

while

(1)

{i=i++;

datout(i〈〈2);}

在Keil下建立项目,输入源程序,编译后进入调试方式全速运行,示波器显示的波形如图所示。

1、在Proteus环境下,设计一个正弦波发生器。

#include

#include〈intrins。

h>

#defineucharunsignedchar

#defineuintunsignedint

sbitSCLK=P1^0;

sbitCS=P1^1;

sbitDIN=P1^2;

ucharcodewavetab[60]={

0x80,0x8D,0x9A,0xA7,0xB4,0xBF,0xCB,0xD5,

0xDF,0xE7,0xEE,0xF4,0xF9,0xFD,0xFF,0xFF,

0xFF,0xFD,0xF9,0xF4,0xEE,0xE7,0xDF,0xD5,

0xCB,0xC0,0xB4,0xA7,0x9A,0x8D,0x80,0x72,

0x65,0x58,0x4C,0x40,0x34,0x2A,0x21,0x18,

0x11,0x0B,0x06,0x02,0x00,0x00,0x00,0x02,

0x06,0x0A,0x10,0x18,0x20,0x2A,0x34,0x3F,

0x4B,0x58,0x65,0x72};

voiddatout(uintdat)

{uchari;

CS=1;//初始化片选信号为高

SCLK=0;//初始化时钟为低

CS=0;//选中TL5615

for(i=0;i〈16;i++)

{dat=dat<<1;//将最高位移入进位位CY

DIN=CY;//将数据送到DIN引脚

SCLK=1;//SCLK产生上升沿

SCLK=0;}//SCLK恢复为低

CS=1;}//片选信号恢复为高}

voidmain(void)

{uinti=0;

for(i=0;i<60;i++)//从波表读取数字量输出

datout(wavetab[i]<<2);

}

运行程序,Proteus的虚拟示波器将观察到如图所示的波形.

4、频率与周期的测量

4、1、频率的测量

4、1、1、频率测量的过程

(1)、硬件电路

在Proteus环境下,设计的频率计电路如图所示,将定时器T0设置在定时方式2,定时时间为250us,满4000次中断正好1s,定时器T1工作于计数方式1,其初值为0。

在启动定时器T0开始定时后,随即送到T1(P3.5)引脚的被测脉冲进行计数,当T0定时满1s后,立即停止T1计数,关闭定时器T0,T1的计数值即为被测信号的频率。

(2)、程序设计

频率测量模块的程序:

#include〈reg52.h>

#include

h>

#defineucharunsignedchar

#defineuintunsignedint

externvoidinit_lcd(void);

externvoiddisp_str(ucharx,uchary,uchar*p);

sbitFS=P3^5;//被测信号FS输入端

bitRDY=0;//测量完成标志

uintmsn;//定时中断计数

uintcount(void)//测量FS的频率

{RDY=0;

TMOD=0X5a;//T0:

定时方式2,T1:

计数方式1;

TH0=TL0=—250;//T0定时时间为250us

msn=4000;//4000次中断正好1s

TH1=TL1=0X00;//T1工作于计数方式,初值为0

ET0=1;//允许T0中断

EA=1;//开中断

while(FS==1);//等待被测信号变低

while(FS==0);//等待被测信号变高

TR0=1;//T0开始定时

TR1=1;//T1开始计数

while(RDY==0);//等待1s

TR1=0;//关闭T1、T0

TR0=0;

return(TH1*256+TL1);//返回计数值

}

voidtimer0(void)interrupt1using1

{msn—-;

if(msn==0)//如果1s已到

RDY=1;}//设置测量完成标志位

voidmain()

{uintf;

ucharstr[9]="f=Hz”;

uchari;

init_lcd();//液晶屏初始化

while

(1)

{f=count();//测量频率

_nop_();

for(i=6;i〉2;i-—)//测量结果转换为5位ASCII码

{str[i]=f%10+0x30;

f=f/10;}

str[2]=f+0x30;

for(i=2;i〈6;i++)//用空格码替换高位的0

{if(str[i]!

='0')break;

str[i]='’;}

disp_str(0,3,str);}//显示测量结果

}

液晶显示模块1602DRV.C:

#include

h〉

#include〈intrins.h>

#defineucharunsignedchar

#defineuintunsignedint

sbitRS=P3^3;//数据/命令寄存器选择控制端

sbitRW=P3^1;//读写控制端

sbitE=P3^0;//使能控制端

sfrLCD=0x80;//P0作为总线端口

sbitBF=LCD^7;//就绪线BF,低电平有效

voidlcd_cmd(ucharcmd)//向液晶屏发送指令

{LCD=cmd;

RS=0;

RW=0;

E=1;

_nop_();

E=0;

while

(1)

{LCD=0xff;

RS=0;

RW=1;

E=0;

_nop_();

E=1;

if(BF==0)break;}

voidlcd_dat(uchardat)//向液晶屏写入数据

{LCD=dat;

RS=1;

RW=0;

E=1;

_nop_();

E=0;

while

(1)

{LCD=0xff;

RS=0;

RW=1;

E=0;

_nop_();

E=1;

if(BF==0)break;

dat=LCD;}

}

voidinit_lcd(void)//初始化液晶屏

{lcd_cmd(0x01);//清屏幕

lcd_cmd(0x3c);//设置双行显示,5*10点阵

lcd_cmd(0x0c);}//开显示,关闭光标

voiddisp_str(ucharx,uchary,uchar*p)//在x行、y列显示字符串p

{if(x==0)

lcd_cmd(0x80+y);//设置写入地址

else

lcd_cmd(0xc0+y);//设置写入地址

while(*p)//将字符依次发送到液晶屏

lcd_dat(*p++);

(3)、调试方法

将被测信号FS用Proteus的虚拟信号源DCLOCK代替,设置其频率,切换以Keil下,全速运行程序,此时液晶屏的显示将如图所示。

停止程序的运行,回到Proteus修改DCLOCK的频率,再次切换到Keil下运行程序,液晶屏上的测量结果将随之变化。

如果液晶屏没有显示,可将语句“f=count();”注销,然后再编译运行,如果仍没有显示,就检查1602DRV。

C模块中I/O口的定义是否与线路一致,直到能正常显示时,再将注销的

语句恢复.

如果液晶屏仍没有显示,说明调用count()函数没有返回,可能是RDY变量始终无效,此时应检查定时器T0的初始化是否正确,电路的连接有无错误。

4、2、周期的测量

4、2、1、周期测量的过程

(1)、硬件电路

在Proteus环境下,用定时器/计数器测量周期的电路如图所示,用D触发器对被测量信号进行分频,这要周期的测量也变成了脉宽的测量。

(2)、程序设计(液晶屏显示模块程序与频率测量模块一样)

周期测量模块程序:

#include

#defineucharunsignedchar

#defineuintunsignedint

externvoiddisp_str(ucharx,uchary,uchar*p);

externvoidinit_lcd(void);

sbitCLR=P1^0;//触发器清0控制位

uintTs;//存放测量结果

bitRDY=0;//测量就绪标志

voidcontrol(void)

{IT0=1;//下降沿触发INT0

EX0=1;//允许外部中断0中断

TH0=0;//定时器初值为0

TL0=0;

TMOD=0x09;//定时器T0工作方式1,由TR0及INT0控制T0定时启停

CLR=0;CLR=1;//D触发器清0

TR0=1;//允许T0定时

EA=1;}//开中断,由被测信号的上升沿启动定时

voidint_0(void)interrupt0using1

{TR0=0;//关闭定时器T0

EA=0;//关中断

Ts=TH0*256+TL0;

RDY=1;}

voidmain()

{ucharstr[9]=”T=us";//用于测量结果输出

uchari;

init_lcd();

while

(1)

{control();//初始化定时器及中断

while(RDY==0);//等待INT0引脚下降沿

RDY=0;

for(i=6;i>2;i——)//测量结果转换为5位ASCII码

{str[i]=Ts%10+0x30;

Ts=Ts/10;}

str[2]=Ts+0x30;

for(i=2;i〈6;i++)//用空格码替换高位的0

{if(str[i]!

=’0')break;

str[i]=’’;}

disp_str(0,3,str);}//显示测量结果

(3)、调试方法

将被测信号FS用Proteus的虚拟信号源DCLOCK代替,设置其周期,如图所示,切换到Keil下,全速运行程序,此时液晶屏的显示将如图所示。

停止程序的运行,回到Proteus修改DCLOCK的周期,再次切换到Keil下运行程序,液晶屏上的

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 人文社科 > 法律资料

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1