數(shù)模轉(zhuǎn)換器ADC0804與單片機連接的原理圖:
這是TX-1C實驗板上的ADC0804和單片機連接的電路原理圖。
左邊的是ADC0804,右邊的是74HC573鎖存器,鎖存器同時又連接了單片機沒畫出。ADC0804的引腳CSAD是片選引腳,因為是低電平有效所以當(dāng)
送0時,我們就可以選中它工作了。RD也是低電平有效,是讀信號的,WR也是低電平有效,當(dāng)送0時就可以啟動A/D開始轉(zhuǎn)換了。INTR是轉(zhuǎn)換結(jié)
束引腳,同樣也是低電平有效,當(dāng)INTR為0時,表示轉(zhuǎn)換結(jié)束了。DB0-DB7是轉(zhuǎn)換后的數(shù)字信號輸出端口。AGND和DGND是接地的。CLK R和
CLK IN(即19和4引腳)是用來給ADC0804產(chǎn)生內(nèi)部時鐘脈沖的(接了一個RC震蕩電路)6和7端口是模擬信號的輸入端,比如我們滑動電位器就
能使模擬信號發(fā)生改變,這樣經(jīng)過A/D轉(zhuǎn)換后,輸出的數(shù)字信號也就改變了。20引腳是接參考電平的。
下面這個程序是用單片機控制ADC0804進行模數(shù)轉(zhuǎn)換,當(dāng)擰動實驗板上的電位器(也就是一個滑動變阻器)時,數(shù)碼管的前三位以十進制方式動態(tài)顯示A/D轉(zhuǎn)換后的數(shù)字量。代碼如下:
#include <reg52.h> //52系列單片機頭文件
#include <intrins.h> //因為下面的程序用到了_nop_()函數(shù),因此包含這個頭文件
#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); //延時函數(shù)聲明
void display(uchar,uchar,uchar) //顯示函數(shù)聲明
/*--------------------------模數(shù)轉(zhuǎn)換核心程序--------------------------------*/
void main()
{
uchar a,A1,A2,A3,adval;
wela=1; //打開位選鎖存器,這樣就把單片機的P0口與鎖存器連通了
P0=0x7f; //這里因為片選 接的是P0口的第7位,P0=0x7f即把第七位置0,片選選定,也即是選定ADC0804工作
wela=0; //關(guān)閉位選鎖存器
while(1) //進入死循環(huán)不停地做模數(shù)轉(zhuǎn)換
{
adwr=1; /*-----------------------------------------*/
_nop_();
adwr=0; / *啟動AD轉(zhuǎn)換(根據(jù)時序圖來的)*/
_nop_();
adwr=1; /*-----------------------------------------*/
for(a=10;a>0;a--)
{
display(A1,A2,A3); //兼具顯示和延時的作用,因為轉(zhuǎn)換需要經(jīng)過一定的時間,用這個for循環(huán)可以起到延時的作用
}
P1=0xff; //讀取P1口之前先給其寫全1
adrd=1; //rd置1(根據(jù)時序圖可知)
_nop_(); //延時一個機器周期(根據(jù)時序圖可知)
adrd=0; //rd置0(根據(jù)時序圖可知)
_nop_(); //延時一個機器周期
adval=P1; //A/D轉(zhuǎn)換后的數(shù)據(jù)賦給adval
adrd=1; //轉(zhuǎn)換后的數(shù)字信號(二進制的信號應(yīng)該已經(jīng)譯成了十進制了)讀出(也是根據(jù)時序圖可知)
A1=adval/100; /*-----------------------------------------*/
A2=adval%100/10; /*分離轉(zhuǎn)換后的十進制數(shù),用來給數(shù)碼管顯示*/
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) //顯示子函數(shù)
{
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,這樣一直選定其工作。對轉(zhuǎn)換沒有影響。再看WR的時序圖WR先是高-->低-->高,從低-->高這個過程中至少要延時tw(WR)L(ns),程序中用的的_nop()_函數(shù)就是延時一個機器周期,本實驗板得機器周期為1000ns遠大于tw(WR)L(ns)。再看RD
RD的時序是高-->低-->高,RD為低后延時tACC后就有數(shù)據(jù)了,adval=P1; //A/D轉(zhuǎn)換后的數(shù)據(jù)賦給adval
于是再把wR拉高這樣就把數(shù)據(jù)讀走了。因為INTR是自動變化的,所以不需要人為設(shè)定。。(以上個人理解不知道是否正確^-^)
呵呵,不同的轉(zhuǎn)換器時序圖應(yīng)該也不一樣,程序代碼也有差別,但本質(zhì)是一樣的。