智能仪器DA转换实验.docx

上传人:b****9 文档编号:25780749 上传时间:2023-06-13 格式:DOCX 页数:20 大小:159.15KB
下载 相关 举报
智能仪器DA转换实验.docx_第1页
第1页 / 共20页
智能仪器DA转换实验.docx_第2页
第2页 / 共20页
智能仪器DA转换实验.docx_第3页
第3页 / 共20页
智能仪器DA转换实验.docx_第4页
第4页 / 共20页
智能仪器DA转换实验.docx_第5页
第5页 / 共20页
点击查看更多>>
下载资源
资源描述

智能仪器DA转换实验.docx

《智能仪器DA转换实验.docx》由会员分享,可在线阅读,更多相关《智能仪器DA转换实验.docx(20页珍藏版)》请在冰豆网上搜索。

智能仪器DA转换实验.docx

智能仪器DA转换实验

实验二D/A转化实验

一、实验目的:

(1)掌握D/A转换与单片机的接口方法。

(2)了解D/A芯片PCF8591转换性能及编程方法。

(3)了解单片机系统中扩展D/A转换芯片的基本方法。

二、实验内容

利用实验仪上的PCF8591做D/A转换实验,写入DA的数模值,然后累加该值,显示该值到数码管,延时100m后循环写入变化后的DA值,观察LED9的变化。

三、实验说明

D/A转换器大致分有三类:

一是双积分D/A转换器,优点是精度高,抗干扰性好,价格便宜,但速度慢;二是逐次逼近式D/A转换器,精度、速度、价格适中;三是并行D/A转换器,速度快,价格也昂贵。

实验用PCF8591属第二类,PCF8591是一个单片集成、单独供电、低功耗、8-bitCMOS数据获取器件。

PCF8591具有4个模拟输入、1个模拟输出和1个串行I²C总线接口。

PCF8591的3个地址引脚A0,A1和A2可用于硬件地址编程,允许在同个I2C总线上接入8个PCF8591器件,而无需额外的硬件。

在PCF8591器件上输入输出的地址、控制和数据信号都是通过双线双向I2C总线以串行的方式进行传输。

四、硬件原理图与链接:

J31与J32用于切换AD输入端口,因为只有两个电位器,但有4个输入端口,所以同时只能使用2个,这两个插针用于切换输入端口。

J33是AD输入模拟LED灯选择开关,用跳帽跳上后LED起作用。

五、实验步骤

(1)单片机P0口与J3相连,用作数码管显示

(2)单片机P2.2与J3(B)相连,P2.2与J2(A)相连。

(3)跳帽J50连接,给数码管供电。

(4)单片机P2.0与J8(SCL)相连,最为时钟输出,单片机P2.1与J8(SDL)相连最为数据输入输出。

(5)J31中DA0与W4用跳帽相连,选择DA通道。

(6)利用keil软件编写程序,并且用STC程序下载工具下载程序。

(7)观察LED9的变化。

链接图:

六、实验程序

main函数:

/*-----------------------------------------------

名称:

IIC协议PCF8591AD/DA转换

论坛:

编写:

shifang

修改:

内容:

使用DA输入,数码管显示输出数字量,LED显示模拟电压大小

------------------------------------------------*/

#include

#include"i2c.h"

#include"delay.h"

#include"display.h"

#defineAddWr0x90//写数据地址

#defineAddRd0x91//读数据地址

externbitack;

unsignedcharReadADC(unsignedcharChl);

bitWriteDAC(unsignedchardat);

/*------------------------------------------------

主程序

------------------------------------------------*/

main()

{

unsignedcharnum=0;

unsignedintval=0;

Init_Timer0();

while

(1)//主循环

{

num=ReadADC(0);

WriteDAC(num);

//num++;//连续累加,值从0-255反复循环,并显示在数码管上,

val=1.963*num;//(5/256*100)

TempData[0]=dofly_DuanMa[val/100]|0x80;

TempData[1]=dofly_DuanMa[(val%100)/10];

TempData[2]=dofly_DuanMa[(val%100)%10];

DelayMs(100);

}

}

unsignedcharReadADC(unsignedcharChl)

{

unsignedcharVal;

Start_I2c();//启动总线

SendByte(AddWr);//发送器件地址

if(ack==0)return(0);

SendByte(0x40|Chl);//发送器件子地址

if(ack==0)return(0);

Start_I2c();

SendByte(AddWr+1);

if(ack==0)return(0);

Val=RcvByte();

NoAck_I2c();//发送非应位

Stop_I2c();//结束总线

return(Val);

}

/*------------------------------------------------

写入DA转换数值

输入参数:

dat表示需要转换的DA数值,范围是0-255

------------------------------------------------*/

bitWriteDAC(unsignedchardat)

{

Start_I2c();//启动总线

SendByte(AddWr);//发送器件地址

if(ack==0)return(0);

SendByte(0x40);//发送器件子地址

if(ack==0)return(0);

SendByte(dat);//发送数据

if(ack==0)return(0);

Stop_I2c();

i2c函数:

/*-----------------------------------------------

名称:

IIC协议

论坛:

编写:

shifang

修改:

内容:

函数是采用软件延时的方法产生SCL脉冲,固对高晶振频率要作一定的修改....(本例是1us机器

周期,即晶振频率要小于12MHZ)

------------------------------------------------*/

#include"i2c.h"

#include"delay.h"

#define_Nop()_nop_()//定义空指令

bitack;//应答标志位

sbitSDA=P2^1;

sbitSCL=P2^0;

/*------------------------------------------------

启动总线

------------------------------------------------*/

voidStart_I2c()

{

SDA=1;//发送起始条件的数据信号

_Nop();

SCL=1;

_Nop();//起始条件建立时间大于4.7us,延时

_Nop();

_Nop();

_Nop();

_Nop();

SDA=0;//发送起始信号

_Nop();//起始条件锁定时间大于4μ

_Nop();

_Nop();

_Nop();

_Nop();

SCL=0;//钳住I2C总线,准备发送或接收数据

_Nop();

_Nop();

}

/*------------------------------------------------

结束总线

------------------------------------------------*/

voidStop_I2c()

{

SDA=0;//发送结束条件的数据信号

_Nop();//发送结束条件的时钟信号

SCL=1;//结束条件建立时间大于4μ

_Nop();

_Nop();

_Nop();

_Nop();

_Nop();

SDA=1;//发送I2C总线结束信号

_Nop();

_Nop();

_Nop();

_Nop();

}

/*----------------------------------------------------------------

字节数据传送函数

函数原型:

voidSendByte(unsignedcharc);

功能:

将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对

此状态位进行操作.(不应答或非应答都使ack=0假)

发送数据正常,ack=1;ack=0表示被控器无应答或损坏。

------------------------------------------------------------------*/

voidSendByte(unsignedcharc)

{

unsignedcharBitCnt;

for(BitCnt=0;BitCnt<8;BitCnt++)//要传送的数据长度为8位

{

if((c<

elseSDA=0;

_Nop();

SCL=1;//置时钟线为高,通知被控器开始接收数据位

_Nop();

_Nop();//保证时钟高电平周期大于4μ

_Nop();

_Nop();

_Nop();

SCL=0;

}

_Nop();

_Nop();

SDA=1;//8位发送完后释放数据线,准备接收应答位

_Nop();

_Nop();

SCL=1;

_Nop();

_Nop();

_Nop();

if(SDA==1)ack=0;

elseack=1;//判断是否接收到应答信号

SCL=0;

_Nop();

_Nop();

}

/*----------------------------------------------------------------

字节数据传送函数

函数原型:

unsignedcharRcvByte();

功能:

用来接收从器件传来的数据,并判断总线错误(不发应答信号),

发完后请用应答函数。

------------------------------------------------------------------*/

/*unsignedcharRcvByte()

{

unsignedcharretc;

unsignedcharBitCnt;

retc=0;

SDA=1;//置数据线为输入方式

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

{

_Nop();

SCL=0;//置时钟线为低,准备接收数据位

_Nop();

_Nop();//时钟低电平周期大于4.7us

_Nop();

_Nop();

_Nop();

SCL=1;//置时钟线为高使数据线上数据有效

_Nop();

_Nop();

retc=retc<<1;

if(SDA==1)retc=retc+1;//读数据位,接收的数据位放入retc中

_Nop();

_Nop();

}

SCL=0;

_Nop();

_Nop();

return(retc);

}

*/

/*----------------------------------------------------------------

应答子函数

原型:

voidAck_I2c(void);

----------------------------------------------------------------*/

/*voidAck_I2c(void)

{

SDA=0;

_Nop();

_Nop();

_Nop();

SCL=1;

_Nop();

_Nop();//时钟低电平周期大于4μ

_Nop();

_Nop();

_Nop();

SCL=0;//清时钟线,钳住I2C总线以便继续接收

_Nop();

_Nop();

}*/

/*----------------------------------------------------------------

非应答子函数

原型:

voidNoAck_I2c(void);

----------------------------------------------------------------*/

/*voidNoAck_I2c(void)

{

SDA=1;

_Nop();

_Nop();

_Nop();

SCL=1;

_Nop();

_Nop();//时钟低电平周期大于4μ

_Nop();

_Nop();

_Nop();

SCL=0;//清时钟线,钳住I2C总线以便继续接收

_Nop();

_Nop();

}

*/

/*----------------------------------------------------------------

向无子地址器件发送字节数据函数

函数原型:

bitISendByte(unsignedcharsla,ucahrc);

功能:

从启动总线到发送地址,数据,结束总线的全过程,从器件地址sla.

如果返回1表示操作成功,否则操作有误。

注意:

使用前必须已结束总线。

----------------------------------------------------------------*/

/*bitISendByte(unsignedcharsla,unsignedcharc)

{

Start_I2c();//启动总线

SendByte(sla);//发送器件地址

if(ack==0)return(0);

SendByte(c);//发送数据

if(ack==0)return(0);

Stop_I2c();//结束总线

return

(1);

}

*/

/*----------------------------------------------------------------

向有子地址器件发送多字节数据函数

函数原型:

bitISendStr(unsignedcharsla,unsignedcharsuba,ucahr*s,unsignedcharno);

功能:

从启动总线到发送地址,子地址,数据,结束总线的全过程,从器件

地址sla,子地址suba,发送内容是s指向的内容,发送no个字节。

如果返回1表示操作成功,否则操作有误。

注意:

使用前必须已结束总线。

----------------------------------------------------------------*/

/*bitISendStr(unsignedcharsla,unsignedcharsuba,unsignedchar*s,unsignedcharno)

{

unsignedchari;

for(i=0;i

{

Start_I2c();//启动总线

SendByte(sla);//发送器件地址

if(ack==0)return(0);

SendByte(suba);//发送器件子地址

if(ack==0)return(0);

SendByte(*s);//发送数据

if(ack==0)return(0);

Stop_I2c();//结束总线

DelayMs

(1);//必须延时等待芯片内部自动处理数据完毕

s++;

suba++;

}

return

(1);

}

*/

/*----------------------------------------------------------------

向无子地址器件读字节数据函数

函数原型:

bitIRcvByte(unsignedcharsla,ucahr*c);

功能:

从启动总线到发送地址,读数据,结束总线的全过程,从器件地

址sla,返回值在c.

如果返回1表示操作成功,否则操作有误。

注意:

使用前必须已结束总线。

----------------------------------------------------------------*/

/*bitIRcvByte(unsignedcharsla,unsignedchar*c)

{

Start_I2c();//启动总线

SendByte(sla+1);//发送器件地址

if(ack==0)return(0);

*c=RcvByte();//读取数据

NoAck_I2c();//发送非就答位

Stop_I2c();//结束总线

return

(1);

}

/

/*----------------------------------------------------------------

向有子地址器件读取多字节数据函数

函数原型:

bitISendStr(unsignedcharsla,unsignedcharsuba,ucahr*s,unsignedcharno);

功能:

从启动总线到发送地址,子地址,读数据,结束总线的全过程,从器件

地址sla,子地址suba,读出的内容放入s指向的存储区,读no个字节。

如果返回1表示操作成功,否则操作有误。

注意:

使用前必须已结束总线。

----------------------------------------------------------------*/

/*bitIRcvStr(unsignedcharsla,unsignedcharsuba,unsignedchar*s,unsignedcharno)

{

unsignedchari;

Start_I2c();//启动总线

SendByte(sla);//发送器件地址

if(ack==0)return(0);

SendByte(suba);//发送器件子地址

if(ack==0)return(0);

Start_I2c();

SendByte(sla+1);

if(ack==0)return(0);

for(i=0;i

{

*s=RcvByte();//发送数据

Ack_I2c();//发送就答位

s++;

}

*s=RcvByte();

NoAck_I2c();//发送非应位

Stop_I2c();//结束总线

return

(1);

}

*/

#include"display.h"

#include"delay.h"

#defineDataPortP0//定义数据端口程序中遇到DataPort则用P0替换

//sbitLATCH1=P2^0;//定义锁存使能端口段锁存

//sbitLATCH2=P2^3;//位锁存

unsignedcharcodedofly_DuanMa[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//显示段码值0~9

unsignedcharcodedofly_WeiMa[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//分别对应相应的数码管点亮,即位码

unsignedcharTempData[8];//存储显示值的全局变量

/*------------------------------------------------

显示函数,用于动态扫描数码管

输入参数FirstBit表示需要显示的第一位,如赋值2表示从第三个数码管开始显示

如输入0表示从第一个显示。

Num表示需要显示的位数,如需要显示99两位数值则该值输入2

------------------------------------------------*/

display函数:

voidDisplay(unsignedcharFirstBit,unsignedcharNum)

{

staticunsignedchari=0;

DataPort=0;//清空数据,防止有交替重影

LATCH1=1;//段锁存

LATCH1=0;

DataPort=dofly_WeiMa[i+FirstBit];//取位码

LATCH2=1;//位锁存

LATCH2=0;

DataPort=TempData[i];//取显示数据,段码

LATCH1=1;//段锁存

LATCH1=0;

i++;

if(i==Num)

i=0;

}

/*------------------------------------------------

定时器初始化子程序

------------------------------------------------*/

voidInit_Timer0(void)

{

TMOD|=0x01;//使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响

//TH0=0x00;//给定初值

//TL0=0x00;

EA=1;//总中断打开

ET0=1;//定时器中断打开

TR0=1;//定时器开关打开

}

/*------------------------------------------------

定时器中断子程序

------------------------------------------------*/

voidTimer0_isr(void)interrupt1

{

TH0=(65536-2000)/256;//重新赋值2ms

TL0=(65536-2000)%256;

Display(0,8);

}

delay函数:

#include"delay.h"

/*------------------------------------------------

uS延时函数,含有输入参数unsignedchart,无返回值

unsignedchar是定义无符号字符变量,其值的范围是

0~255这里使用晶振12M,精确延时请使用汇编,大致延时

长度如下T=tx2+5uS

------------------------------------------

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

当前位置:首页 > 初中教育 > 语文

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

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