信号采集输入电路的设计与实现
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验课程名称:监测控制系统应用实验四
实验项目名称:信号采集输入电路的设计与实现实验成绩:
实验者:专业班级:电信130 班
同组者:实验日期:周四3~4节课一.实验目的
1.掌握模拟量的输入接口电路的设计。
2.熟悉市面上常用的AD转换芯片的性能及特点
3.掌握AD转换芯片硬件连接方法和基本编程方法。
4.掌握模拟量采集的软件编程技巧
二.实验内容
1.用信号发生器产生各种输出电压信号,设计一信号采集系统实时测量该信号发生器的输出并显示出来。
2.信号发生器分别输出直流、方波、正弦波信号供系统采集,研究信号采集系统如何保证准确性、精度、实时性。
具体任务:
1、模拟量采集系统的设计
开发板有AD转换芯片的,依托开发板设计模拟量采集系统的硬件和软件,实验时用实验室的信号发生器产生模拟量。
开发板上没有AD转换芯片的,自由设计模拟量采集系统的硬件和软件,实验时,在proteus环境下,用信号发生器产生模拟量,仿真实验。
2、采集系统准确性实验
让信号发生器分别输出1V、3V、5V、7V、9V、11V、13V的直流电压,记录采集系统的采集值。
观察测量值与实际值的差距,从硬件和软件两方面分析原因,改进系统,直至达到满意的测量结果,记录相应的测量结果。
思考采集系统的精度如何提高,给出答案。
(选做:对于用proteus仿真实验的同学,调整系统设计,使测量精度提高一个档次,记录实验结果)
3、采集系统实时性实验
让信号发生器输出方波信号,观察采集系统显示器显示的采集值是否跟踪输入信号的
值跳变。
加大方波信号的频率,直到系统不能跟踪测量,记录采集系统能够跟踪测量的频率范围。
分析得出提高你的采集系统实时性的措施有哪些,改进系统,直至达到满意的效果,记录此时采集系统能够跟踪测量的频率范围。
让信号发生器输出连续的正弦波信号,观察此时已经进行了准确性和实时性优化的系统的采集结果,如果效果不好,分析原因并改进。
三.探究内容:
AD转换结束后可以通过查询或中断的方式读取转换结果,针对本实验任务,是采用查询方式好还是中断方式好?
四.实验原理
1. PCF8591芯片
PCF8591是单片、单电源低功耗8位CMOS数据采集器件,具有4个模拟输入、一个输出和一个串行I2C总线接口。
3个地址引脚A0、A1和A2用于编程硬件地址,允许将最多8个器件连接至I2C总线而不需要额外硬件。
器件地址、控制和数据通道通过两线双向I2C总线传输。
器件功能包括多路复用模拟量输入、片上跟踪和保持功能、8位模数转换和8位数模转换。
最大转换速率取决于I2C总线的最高速率。
我实现的AD转换是使用通道0将滑动变阻器两端的电压
AIN0~AIN3:模拟信号输入端。
A0~A2:引脚地址端。
VDD、VSS:电源端。
(2.5~6V)
SDA、SCL:I2C 总线的数据线、时钟线。
OSC:外部时钟输入端,内部时钟输出端。
EXT:内部、外部时钟选择线,使用内部时钟时EXT 接地。
AGND:模拟信号地。
AOUT:D/A 转换输出端。
VREF:基准电源端。
地址:I2C总线系统中的每一片PCF8591通过发送有效地址到该器件来激活。
该地址包括固定部分和可编程部分。
可编程部分必须根据地址引脚A0、A1和A2来设置。
在I2C 总线协议中地址必须是起始条件后作为第一个字节发送。
地址字节的最后一位是用于设置以后数据传输方向的读/写位。
(见下图)
控制字:发送到PCF8591的第二个字节将被存储在控制寄存器,用于控制器件功能。
控制寄存器的高板字节用于允许模拟输出,和将模拟输入编程为单端过查分输入。
低半字节选择一个有高板字节定义的模拟输入通道。
如果自动增量标志置1,每次A/D转换后通道号将自动增加。
如果自动增量模式是使用内部振荡器的应用中所需要的,那么控制字中模拟输出允许标志应置1。
这要求内部振荡器持续运行,因此要防止振荡器启动延时的转换错误结果。
模拟输出标志可以在其他时候复位以减少静态功耗。
D/A转换:发送给PCF8591的第三个字节被存储到DAC数据寄存器,并使用片上D/A 转换器转换成对应的模拟电压。
这个D/A转换器由连接至外部参考电压的具有256个接头的电阻分压电路和选择开关组成。
模拟输出电压由自动清零单位增益放大器缓冲。
这个缓冲放大器可通过设置控制寄存器的模拟输出允许标志来开户或关闭。
在激活状态,输出电压保持到新的数据字节被发送。
A/D转换:A/D转换器采用逐次逼近转换技术。
在A/D转换周期将来临时片上D/A抓换器和高增益比较器。
一个A/D转换周期总是开始于发送一个有效读模式地址给PCF8591之后。
A/D转换周期在应答时钟脉冲的后沿被触发,并在传输前一次转换结果时执行。
一旦一个转换周期被触发,所选通道的输入电压采样将保存到芯片被转换为对应的8位二进制码。
PCF8591是一个单片集成、单独供电、低功耗、8-bit CMOS数据获取器件。
PCF8591具有4个模拟输入、1个模拟输出和1个串行I2C总线接口。
PCF8591的3个地址引脚A0,A1和A2可用于硬件地址编程,允许在同个I2C总线上接入8个PCF8591器件,而无需额外的硬件。
在PCF8591器件上输入输出的地址、控制和数据信号都是通过双线双向I2C总线以串行的方式进行传输。
PCF8591的功能包括多路模拟输入、内置跟踪保持、8-bit模数转换和8-bit数模转换。
PCF8591的最大转化速率由I2C总线的最大速率决定。
下图为PCF8591内部结构图:
PCF8591内部结构图
开发板上PCF连线图2. 实验电路
3. 流程图设计
输入为4v方波时:
当输入为3V的DC波形时
在输入为最高电压为4V,最低电
压为1V的方波时,采集到的值为
4.004V和0.989V,在误差允许范
围内,调节方波的频率,最大可以
跟踪到99Hz的方波信号,在方波
频率为100Hz时,便不能正常测
量。
在输入为最高电压为3V,最低电压为0V的DC波形时,采集到的值在0V~3V之间,能够很好的实现跟踪测量,调节波形频率,最大可以跟踪到99Hz的波形信号,在频率为100Hz时,便不能正常测量。
量程扩展实验中,数码管前面两位
表示整数部分电压,后面两位表示
小数部分电压,当输入为最高电压
10V,最低电压1V的方波时,测量
值为9.89V和0.95V,跟踪频率最大
99Hz
六.结果分析:
在实验中,分别对方波,正弦波做了跟踪测量,测量值和实际值均在测量范围内。
由实验探究知,测量的方波信号和正弦波信号频率在99Hz以及99Hz以下时,可以很好的实现实时跟踪测量。
在PCF8591器件上输入输出的地址、控制和数据信号都是通过双线双向I2C总线以串行的方式进行传输。
PCF8591的功能包括多路模拟输入、内置跟踪保持、8-bit 模数转换和8-bit数模转换。
PCF8591的最大转化速率由I2C总线的最大速率决定。
由此可以推论出此次设计中,PCF8591的I2C总线的最大跟踪频率在100Hz以下。
由于PCF8591的外部参考电压是5V,所以最大能够测量的外部输入电压近似为5V(比5V稍小,转换范围在0~5*(1-2^8)V),实验中要求测到5V以上的电压值,需要对外部输入电压进行分压处理,只需选择合适的电阻就行。
此次选择的电阻为5k和10k,将输入电压降低到原电压的1/3,这样便可将测量范围扩大三倍的目的。
附录:
实验程序
/*******************************初始化*******************************/ #ifndef__XPT2046_H_
#define __XPT2046_H_
//---包含头文件---//
#include<reg51.h>
#include<intrins.h>
//---重定义关键词---//
#ifndef uchar
#define uchar unsigned char
#endif
#ifndef uint
#define uint unsigned int
#endif
#ifndef ulong
#define ulong unsigned long
#endif
//---定义使用的IO口---//
sbit CLK = P1^0;//时钟
sbit CS = P1^1;//片选
sbit DIN = P1^2;//输入
sbit DOUT = P1^3;//输出
uint Read_AD_Data(uchar cmd);
uint SPI_Read(void);
void SPI_Write(uchar dat);
#endif
/*******************总线初始化及AD/DA转换函数初始化********************/
#include"XPT2046.h"
/**************************************************************************** *函数名:TSPI_Start
*输入:无
*输出:无
*功能:初始化触摸SPI
****************************************************************************/
void SPI_Start(void)
{
CLK = 0;
CS = 1;
DIN = 1;
CLK = 1;
CS = 0;
}
/**************************************************************************** *函数名:SPI_Write
*输入:dat:写入数据
*输出:无
*功能:使用SPI写入数据
****************************************************************************/
void SPI_Write(uchar dat)
{
uchar i;
CLK = 0;
for(i=0; i<8; i++)
{
DIN = dat >> 7; //放置最高位
dat <<= 1;
CLK = 0;//上升沿放置数据
CLK = 1;
}
}
/**************************************************************************** *函数名:SPI_Read
*输入:无
*输出:dat:读取到的数据
*功能:使用SPI读取数据
****************************************************************************/
uint SPI_Read(void)
{
uint i, dat=0;
CLK = 0;
for(i=0; i<12; i++)//接收12位数据
{
dat <<= 1;
CLK = 1;
CLK = 0;
dat |= DOUT;
}
return dat;
}
/**************************************************************************** *函数名:Read_AD_Data
*输入:cmd:读取的X或者Y
*输出:endValue:最终信号处理后返回的值
*功能:读取触摸数据
****************************************************************************/ uint Read_AD_Data(uchar cmd)
{
uchar i;
uint AD_Value;
CLK = 0;
CS = 0;
SPI_Write(cmd);
for(i=6; i>0; i--); //延时等待转换结果
CLK = 1;//发送一个时钟周期,清除BUSY
_nop_();
_nop_();
CLK = 0;
_nop_();
_nop_();
AD_Value=SPI_Read();
CS = 1;
return AD_Value;
}
/**************************main函数********************************/
#include"reg51.h"
#include"XPT2046.h"
//--定义使用的IO--//
#define GPIO_DIG P0
//--定义全局变量--//
unsigned char code DIG_CODE[17]={
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
unsigned char table[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
//0、1、2、3、4、5、6、7、8、9、A、b、C、d、E、F的显示码
unsigned char DisplayData[8];//用来存放要显示的8位数的值
void DigDisplay(void);
void main(void)
{
uint temp,count;
while(1)
{
if(count==50)
{
count=0;
temp = Read_AD_Data(0xE4)*1.22;// AIN3 外部输入,并转化为对应的数字量}
count++;
DisplayData[0]=0;//只使用4位数码管显示
DisplayData[1]=0;
DisplayData[2]=0;
DisplayData[3]=0;
DisplayData[4]=DIG_CODE[temp%10000/1000]; //整数部分
DisplayData[5]=DIG_CODE[temp%1000/100]; //第一位小数
DisplayData[6]=DIG_CODE[temp%100/10]; //第二位小数
DisplayData[7]=DIG_CODE[temp%10/1]; //第三位小数
DigDisplay(); //调用显示函数
}
}
void DigDisplay(void)//长延时
{
unsigned char i;
unsigned int j;
for(i=0;i<8;i++)
{
P2=table[i];
GPIO_DIG=DisplayData[i]; //发送段码
j=50;//扫描间隔时间设定
while(j--);
GPIO_DIG=0x00;//消隐
}
}。