微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 51单片机ADC0804模数转换学习

51单片机ADC0804模数转换学习

时间:08-02 来源:互联网 点击:

数模转换器ADC0804与单片机连接的原理图:

这TX-1C实验板上的ADC0804和单片机连接的电路原理图。

左边的是ADC0804,右边的是74HC573锁存器,锁存器同时又连接了单片机没画出。ADC0804的引脚CSAD是片选引脚,因为是低电平有效所以当

送0时,我们就可以选中它工作了。RD也是低电平有效,是读信号的,WR也是低电平有效,当送0时就可以启动A/D开始转换了。INTR是转换结

束引脚,同样也是低电平有效,当INTR为0时,表示转换结束了。DB0-DB7是转换后的数字信号输出端口。AGND和DGND是接地的。CLK R和

CLK IN(即19和4引脚)是用来给ADC0804产生内部时钟脉冲的(接了一个RC震荡电路)6和7端口是模拟信号的输入端,比如我们滑动电位器就

能使模拟信号发生改变,这样经过A/D转换后,输出的数字信号也就改变了。20引脚是接参考电平的。

下面这个程序是用单片机控制ADC0804进行模数转换,当拧动实验板上的电位器(也就是一个滑动变阻器)时,数码管的前三位以十进制方式动态显示A/D转换后的数字量。代码如下:
#include reg52.h> //52系列单片机头文件
#include intrins.h> //因为下面的程序用到了_nop_()函数,因此包含这个头文件
#define uchar unsigned char
#define uint unsigned int
sbit dula=P2^6; //申明U1锁存器的锁存端
sbit wela=P2^7; //申明U2锁存器的锁存端
sbit adwr=P3^6; //定义AD的WR(写信号)端口
sbit adrd=P3^7; //定义AD的RD(读信号)端口
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
void delayms(uint); //延时函数声明
void display(uchar,uchar,uchar) //显示函数声明

/*--------------------------模数转换核心程序--------------------------------*/
void main()
{

uchar a,A1,A2,A3,adval;
wela=1; //打开位选锁存器,这样就把单片机的P0口与锁存器连通了
P0=0x7f; //这里因为片选 接的是P0口的第7位,P0=0x7f即把第七位置0,片选选定,也即是选定ADC0804工作
wela=0; //关闭位选锁存器

while(1) //进入死循环不停地做模数转换
{
adwr=1; /*-----------------------------------------*/
_nop_();
adwr=0; / *启动AD转换(根据时序图来的)*/
_nop_();
adwr=1; /*-----------------------------------------*/

for(a=10;a>0;a--)
{
display(A1,A2,A3); //兼具显示和延时的作用,因为转换需要经过一定的时间,用这个for循环可以起到延时的作用
}

P1=0xff; //读取P1口之前先给其写全1

adrd=1; //rd置1(根据时序图可知)
_nop_(); //延时一个机器周期(根据时序图可知)
adrd=0; //rd置0(根据时序图可知)
_nop_(); //延时一个机器周期
adval=P1; //A/D转换后的数据赋给adval
adrd=1; //转换后的数字信号(二进制的信号应该已经译成了十进制了)读出(也是根据时序图可知)

A1=adval/100; /*-----------------------------------------*/
A2=adval%100/10; /*分离转换后的十进制数,用来给数码管显示*/
A3=adval%10; /*-----------------------------------------*/

}
}
/*-------------------------------------------------------------------------------*/

void delayms(uint xms)
{
uint i,j;
for(i=xms;i>0;i--) //i=xms即延时约xms毫秒
for(j=110;j>0;j--);
}

void display(uchar bai,uchar shi,uchar ge)//显示子函数
{
dula=1;
P0=table[bai];
dula=0;
P0=0xff;
wela=1;
P0=0x7e;
wela=0;
delayms(5);

dula=1;
P0=table[shi];
dula=0;
P0=0xff;
wela=1;
P0=0x7d;
wela=0;
delayms(5);

dula=1;
P0=table[ge];
dula=0;
P0=0xff;
wela=1;
P0=0x7b;
wela=0;
delayms(5);
}
程序中所说的时序图如下:

从时序图可知首先要选定片选,即置CS=0,程序中一直让cs为0,这样一直选定其工作。对转换没有影响。再看WR的时序图WR先是高-->低-->高,从低-->高这个过程中至少要延时tw(WR)L(ns),程序中用的的_nop()_函数就是延时一个机器周期,本实验板得机器周期为1000ns远大于tw(WR)L(ns)。再看RD

RD的时序是高-->低-->高,RD为低后延时tACC后就有数据了,adval=P1; //A/D转换后的数据赋给adval
于是再把wR拉高这样就把数据读走了。因为INTR是自动变化的,所以不需要人为设定。。(以上个人理解不知道是否正确^-^)

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top