数据采集器的设计实验报告.docx
- 文档编号:13236248
- 上传时间:2023-06-12
- 格式:DOCX
- 页数:25
- 大小:232.40KB
数据采集器的设计实验报告.docx
《数据采集器的设计实验报告.docx》由会员分享,可在线阅读,更多相关《数据采集器的设计实验报告.docx(25页珍藏版)》请在冰点文库上搜索。
数据采集器的设计实验报告
数据采集器的设计实验报告
————————————————————————————————作者:
————————————————————————————————日期:
单片机项目实践报告
数据采集器的设计
班级:
计应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下运行程序,液晶屏上的
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据 采集 设计 实验 报告