ADC0809更詳細的引數說明可以檢視它的晶片手冊(英文原版)
連結:https://share.weiyun.com/wyAdZUPP
密碼:eteeec
ADC0809晶片有28條引腳,採用雙列直插式封裝
模擬量輸入選擇通道表
ADC0809完成一次轉換需100us左右,可對0~5V訊號進行交換。
ALE: 正脈衝鎖存ADDA、ADDB、ADDC通道
START: 正脈衝的上升沿清除內部暫存器資料,下降沿啟動AD轉換
AD啟動後EOC由高變低;
AD轉換期間EOC保持低電平;
AD轉換結束後EOC由低變高電平。
OE: 輸入正脈衝,開啟三態門輸出
A/D轉換後得到的是數位量的資料,這些資料資料傳給微控制器進行處理,資料的關鍵問題是如何確定A/D轉換完成,因為只有完成後才能進行傳送,為此可採用等待延時方式、查詢方式和中斷方式。
對於一種A/D轉換器來說,轉換時間作為一項指標是已知和固定的。例如,若ADC0809轉換時間為128us,相當於12MHZ的51微控制器共128個機器週期。可根據此設計一個延時子程式,A/D轉換啟動後呼叫這個子程式,延時時間一到,轉換時間肯定完成,接著就可以進行資料傳送了。
A/D轉換晶片有表明完成的狀態訊號,ADC0809的EOC端就是轉換結束指示腳。因此可以用查詢方式,軟體測試EOC的轉態,即可確定轉換是否完成,然後進行資料傳送。
把表明轉換完成的轉態訊號EOC作為中斷訊號請求,將EOC訊號經過反相器返送到微控制器INT0或INT1,以中斷方式進行資料傳送。
附上之前畫好的類比電路
連結:https://share.weiyun.com/nYRBzGt0
密碼:q3mivs
使用ADC0809數模轉換器,採用查詢方式將電位上的模擬量(模擬電壓)轉換為數位量,把轉換結果送到數碼管顯示。
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
/*ADC0809埠定義*/
#define OUTPUT_PORT P1; //ADC輸出的匯流排介面
sbit EOC = P3^5; //A/D轉換結束訊號,輸出,當A/D轉換結束時,此端輸出一個高電平(轉換期間一直為低電平)
sbit START = P3^6; //A/D轉換啟動脈衝輸入端,輸入一個正脈衝(至少100ns寬)使其啟動(脈衝上升沿使0809復位,下降沿啟動A/D轉換)。
sbit CLOCK = P3^7; //時鐘脈衝輸入端
sbit OE = P3^4; //資料輸出允許訊號,輸入,高電平有效。當A/D轉換結束時,此端輸入一個高電平,才能開啟輸出三態門,輸出數位量
sbit ADD_A = P3^0; //通道A
sbit ADD_B = P3^1; //通道B
sbit ADD_C = P3^2; //通道C
//數碼管位選定義
sbit smg1 = P2^0;
sbit smg2 = P2^1;
sbit smg3 = P2^2;
sbit smg4 = P2^3;
//數碼管碼錶,共陰極
unsigned char leddata[10]={
0x3F, //"0"
0x06, //"1"
0x5B, //"2"
0x4F, //"3"
0x66, //"4"
0x6D, //"5"
0x7D, //"6"
0x07, //"7"
0x7F, //"8"
0x6F, //"9"
};
/*1毫秒延時函數*/
void Delay1ms() //@12.000MHz
{
unsigned char i, j;
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
/*毫秒延時函數*/
void delay_ms(uint time)
{
uint i;
for(i=0; i<time; i++)
{
Delay1ms();
}
}
//在數碼管顯示三位數位顯示函數,
//unsigned char i 輸入0-999以內的數位
void disply_three_digit(unsigned int i)
{
unsigned int ge,shi,bai;
bai = i / 100;
shi = i % 100 / 10;
ge = i % 10;
P0 = leddata[ge];
smg4 = 0;
delay_ms(1);
smg4 = 1;
P0 = leddata[shi];
smg3 = 0;
delay_ms(1);
smg3 = 1;
P0 = leddata[bai];
smg2 = 0;
delay_ms(1);
smg2 = 1;
}
/*系統初始化*/
void system_Init(void)
{
/*上電後P0、P1、P2全部置1*/
P0 = 0xff;
P1 = 0xff;
P2 = 0xff;
}
/***********************************************
程式名稱:InitTimer1
程式功能:定時器1初始化
程式說明:使用定時器1,工作方式2來產生一個時鐘脈衝
程式輸入:無
程式返回:無
***********************************************/
void InitTimer1(void)
{
TMOD = 0x20; //定時器T1,工作方式2,自動重灌
TH1 = 0x38;
TL1 = 0x38; //定時約200us
EA = 1; //開啟總中斷
ET1 = 1; //開定時中斷
TR1 = 1; //啟動定時器T1
}
/***********************************************
程式名稱:ADC0809_Result
程式功能:獲取ADC0809 ADC值
程式說明:因為ADC0809是並行輸出方式,所以輸出的
ADC結果反饋到微控制器的對應的OUTPUT_PORT引腳。
程式輸入:uchar adc_number(要獲取的ADC通道號1-7)
程式返回:unsigned char result 返回當前通道的ADC值
***********************************************/
uchar ADC0809_Result(uchar adc_number)
{
uchar result = 0; //定義一個臨時變數,用於存放轉換後的ADC值
/*初始化ADC0809*/
START = 0;
OE = 0;
START = 1;
/*選擇相應輸入通道*/
switch(adc_number)
{
case 1:
ADD_C = 0;
ADD_B = 0;
ADD_A = 0;
break;
case 2:
ADD_C = 0;
ADD_B = 0;
ADD_A = 1;
break;
case 3:
ADD_C = 0;
ADD_B = 1;
ADD_A = 1;
break;
case 4:
ADD_C = 0;
ADD_B = 1;
ADD_A = 1;
break;
case 5:
ADD_C = 1;
ADD_B = 0;
ADD_A = 0;
break;
case 6:
ADD_C = 1;
ADD_B = 0;
ADD_A = 1;
break;
case 7:
ADD_C = 1;
ADD_B = 1;
ADD_A = 0;
break;
case 8:
ADD_C = 1;
ADD_B = 1;
ADD_A = 1;
break;
}
/*啟動ADC轉換*/
START = 0;
while(EOC == 0); //等待EOC = 1
OE = 1; //開啟三態門輸出
result = OUTPUT_PORT;
return result; //將結果返回輸出
}
void main()
{
uchar temp = 0;
system_Init();
InitTimer1();
while(1)
{
temp = ADC0809_Result(3);//讀取通道3的AD值
disply_three_digit(temp);//將讀取到的ADC值送到數碼管
}
}
void Timer1Interrupt(void) interrupt 3
{
CLOCK = ~CLOCK; //通過定時器T1提供時鐘脈衝
}
略
電壓值 = ADC值 * (參考電壓 / 解析度最大位) * 100(保留小數點後兩位)
參考例程
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
/*ADC0809埠定義*/
#define OUTPUT_PORT P1; //ADC輸出的匯流排介面
sbit EOC = P3^5; //A/D轉換結束訊號,輸出,當A/D轉換結束時,此端輸出一個高電平(轉換期間一直為低電平)
sbit START = P3^6; //A/D轉換啟動脈衝輸入端,輸入一個正脈衝(至少100ns寬)使其啟動(脈衝上升沿使0809復位,下降沿啟動A/D轉換)。
sbit CLOCK = P3^7; //時鐘脈衝輸入端
sbit OE = P3^4; //資料輸出允許訊號,輸入,高電平有效。當A/D轉換結束時,此端輸入一個高電平,才能開啟輸出三態門,輸出數位量
sbit ADD_A = P3^0; //通道A
sbit ADD_B = P3^1; //通道B
sbit ADD_C = P3^2; //通道C
//數碼管位選定義
sbit smg1 = P2^0;
sbit smg2 = P2^1;
sbit smg3 = P2^2;
sbit smg4 = P2^3;
//數碼管碼錶,共陰極
unsigned char leddata[10]={
0x3F, //"0"
0x06, //"1"
0x5B, //"2"
0x4F, //"3"
0x66, //"4"
0x6D, //"5"
0x7D, //"6"
0x07, //"7"
0x7F, //"8"
0x6F, //"9"
};
unsigned char leddata2[10]={
0xBF,//"0."
0x86,//"1."
0xDB,//"2."
0xCF,//"3."
0xE6,//"4."
0xED,//"5."
0xFD,//"6."
0x87,//"7."
0xFF,//"8."
0xEF,//"9."
};
/*1毫秒延時函數*/
void Delay1ms() //@12.000MHz
{
unsigned char i, j;
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
/*毫秒延時函數*/
void delay_ms(uint time)
{
uint i;
for(i=0; i<time; i++)
{
Delay1ms();
}
}
//在數碼管顯示三位數位顯示函數,
//unsigned char i 輸入0-999以內的數位
void disply_three_digit(unsigned int i)
{
unsigned int ge,shi,bai;
bai = i / 100;
shi = i % 100 / 10;
ge = i % 10;
P0 = leddata[ge];
smg4 = 0;
delay_ms(1);
smg4 = 1;
P0 = leddata[shi];
smg3 = 0;
delay_ms(1);
smg3 = 1;
P0 = leddata2[bai];
smg2 = 0;
delay_ms(1);
smg2 = 1;
}
/*系統初始化*/
void system_Init(void)
{
/*上電後P0、P1、P2全部置1*/
P0 = 0xff;
P1 = 0xff;
P2 = 0xff;
}
/***********************************************
程式名稱:InitTimer1
程式功能:定時器1初始化
程式說明:使用定時器1,工作方式2來產生一個時鐘脈衝
程式輸入:無
程式返回:無
***********************************************/
void InitTimer1(void)
{
TMOD = 0x20; //定時器T1,工作方式2,自動重灌
TH1 = 0x38;
TL1 = 0x38; //定時約200us
EA = 1; //開啟總中斷
ET1 = 1; //開定時中斷
TR1 = 1; //啟動定時器T1
}
/***********************************************
程式名稱:ADC0809_Result
程式功能:獲取ADC0809 ADC值
程式說明:因為ADC0809是並行輸出方式,所以輸出的
ADC結果反饋到微控制器的對應的OUTPUT_PORT引腳。
程式輸入:uchar adc_number(要獲取的ADC通道號1-7)
程式返回:unsigned char result 返回當前通道的ADC值
***********************************************/
uchar ADC0809_Result(uchar adc_number)
{
uchar result = 0; //定義一個臨時變數,用於存放轉換後的ADC值
/*初始化ADC0809*/
START = 0;
OE = 0;
START = 1;
/*選擇相應輸入通道*/
switch(adc_number)
{
case 1:
ADD_C = 0;
ADD_B = 0;
ADD_A = 0;
break;
case 2:
ADD_C = 0;
ADD_B = 0;
ADD_A = 1;
break;
case 3:
ADD_C = 0;
ADD_B = 1;
ADD_A = 1;
break;
case 4:
ADD_C = 0;
ADD_B = 1;
ADD_A = 1;
break;
case 5:
ADD_C = 1;
ADD_B = 0;
ADD_A = 0;
break;
case 6:
ADD_C = 1;
ADD_B = 0;
ADD_A = 1;
break;
case 7:
ADD_C = 1;
ADD_B = 1;
ADD_A = 0;
break;
case 8:
ADD_C = 1;
ADD_B = 1;
ADD_A = 1;
break;
}
/*啟動ADC轉換*/
START = 0;
while(EOC == 0); //等待EOC = 1
OE = 1; //開啟三態門輸出
result = OUTPUT_PORT;
return result; //將結果返回輸出
}
void main()
{
uint temp = 0;
system_Init();
InitTimer1();
while(1)
{
temp = ADC0809_Result(3); //讀取通道3的AD值
temp = temp * 0.0196078431372549 * 100; //轉換電壓=轉換ADC值 * (參考電壓 / 解析度最大位) * 100(保留小數點後兩位)
disply_three_digit(temp); //將讀取到的ADC值送到數碼管
}
}
void Timer1Interrupt(void) interrupt 3
{
CLOCK = ~CLOCK; //通過定時器T1提供時鐘脈衝
}