STC15系列單片機(jī)內(nèi)部集成了8路10位高速A/D轉(zhuǎn)換器。STC15系列單片機(jī)的A/D轉(zhuǎn)換口在P1口(P1.7-P1.0),有8路10位高速A/D轉(zhuǎn)換器,速度到300KHz(30萬次/秒)。8路電壓輸入型A/D,可做溫度檢測、電池電壓檢測、按鍵掃描、頻譜檢測等。
一、A/D轉(zhuǎn)換器的結(jié)構(gòu)
STC15系列單片機(jī)ADC由多路選擇開關(guān)、比較器、逐次比較寄存器、10位DAC、轉(zhuǎn)換結(jié)果寄存器(ADC_RES和ADC_RESL)以及ADC_CONTR構(gòu)成。
STC15系列單片機(jī)的ADC是逐次比較型ADC。逐次比較型ADC由一個(gè)比較器和D/A轉(zhuǎn)換器構(gòu)成,通過逐次比較邏輯,從最高位(MSB)開始,順序地對每一輸入電壓與內(nèi)置D/A轉(zhuǎn)換器輸出進(jìn)行比較,經(jīng)過多次比較,使轉(zhuǎn)換所得的數(shù)字量逐次逼近輸入模擬量對應(yīng)值。逐次比較型A/D轉(zhuǎn)換器具有速度高,功耗低等優(yōu)點(diǎn)。
從上圖可以看出,通過模擬多路開關(guān),將通過ADC0 ~ 7的模擬量輸入送給比較器。用數(shù)/模轉(zhuǎn)換器(DAC)轉(zhuǎn)換的模擬量與輸入的模擬量通過比較器進(jìn)行比較,將比較結(jié)果保存到逐次比較寄存器,并通過逐次比較寄存器輸出轉(zhuǎn)換結(jié)果。A/D轉(zhuǎn)換結(jié)束后,最終的轉(zhuǎn)換結(jié)果保存到ADC轉(zhuǎn)換結(jié)果寄存器ADC_RES和ADC_RESL,同時(shí),置位ADC控制寄存器ADC_CONTR中的A/D轉(zhuǎn)換結(jié)束標(biāo)志位ADC_FLAG,以供程序查詢或發(fā)出中斷申請。模擬通道的選擇控制由ADC控制寄存器ADC_CONTR中的CHS2~CHS0確定。ADC的轉(zhuǎn)換速度由ADC控制寄存器中的SPEED1和SPEED0確定。在使用ADC之前,應(yīng)先給ADC上電,也就是置位ADC控制寄存器中的ADC_POWER位。
當(dāng)CLK_DIV.5(PCON2.5)/ADRJ = 0時(shí),A/D轉(zhuǎn)換結(jié)果寄存器格式如下:
當(dāng)ADRJ=0時(shí),如果取10位結(jié)果,則按下面公式計(jì)算:
當(dāng)ADRJ=0時(shí),如果取8位結(jié)果,按下面公式計(jì)算:
當(dāng)CLK_DIV.5(PCON2.5)/ADRJ = 1時(shí),A/D轉(zhuǎn)換結(jié)果寄存器格式如下:
當(dāng)ADRJ=1時(shí),如果取10位結(jié)果,則按下面公式計(jì)算:
式中,Vin為模擬輸入通道輸入電壓,Vcc為單片機(jī)實(shí)際工作電壓,用單片機(jī)工作電壓作為模擬參考電壓。
二、與A/D轉(zhuǎn)換相關(guān)的寄存器
與STC15系列單片機(jī)A/D轉(zhuǎn)換相關(guān)的寄存器列于下表所示。
2.1 P1口模擬功能控制寄存器P1ASF
STC15系列單片機(jī)的A/D轉(zhuǎn)換口在P1口(P1.7-P1.0),有8路10位高速A/D轉(zhuǎn)換器速度可達(dá)到到300KHz(30萬次/秒)。8路電壓輸入型A/D,可做溫度檢測、電池電壓檢測、按鍵掃描、頻譜檢測等。上電復(fù)位后P1口為弱上拉型I/O口,用戶可以通過軟件設(shè)置將8路中的任何一路設(shè)置為A/D轉(zhuǎn)換,不需作為A/D使用的P1口可繼續(xù)作為I/O口使用(建議只作為輸入)。需作為A/D使用的口需先將P1ASF特殊功能寄存器中的相應(yīng)位置為‘1’,將相應(yīng)的口設(shè)置為模擬功能。P1ASF存器的格式如下:
P1ASF : P1口模擬功能控制寄存器(該寄存器是只寫寄存器,讀無效)
2.2 ADC控制寄存器ADC_CONTR
ADC_CONTR寄存器的格式如下:
ADC_CONTR : ADC控制寄存器
對ADC_CONTR寄存器進(jìn)行操作,建議直接用MOV賦值語句,不要用‘與’和‘或’語句。
ADC_POWER: ADC 電源控制位。
0:關(guān)閉ADC 電源;
1:打開A/D轉(zhuǎn)換器電源.
建議進(jìn)入空閑模式和掉電模式前,將ADC電源關(guān)閉,即ADC_POWER =0,可降低功耗。
啟動A/D轉(zhuǎn)換前一定要確認(rèn)A/D電源已打開,A/D轉(zhuǎn)換結(jié)束后關(guān)閉A/D電源可降低功耗,也可不關(guān)閉。初次打開內(nèi)部A/D轉(zhuǎn)換模擬電源,需適當(dāng)延時(shí),等內(nèi)部模擬電源穩(wěn)定后,再啟動A/D轉(zhuǎn)換。
建議啟動A/D轉(zhuǎn)換后,在A/D轉(zhuǎn)換結(jié)束之前,不改變?nèi)魏蜪/O口的狀態(tài),有利于高精度A/D轉(zhuǎn)換,如能將定時(shí)器/串行口/中斷系統(tǒng)關(guān)閉更好。
SPEED1,SPEED0:模數(shù)轉(zhuǎn)換器轉(zhuǎn)換速度控制位
ADC_FLAG: 模數(shù)轉(zhuǎn)換器轉(zhuǎn)換結(jié)束標(biāo)志位,當(dāng)A/D轉(zhuǎn)換完成后,ADC_FLAG = 1,要由軟件清0。不管是A/D 轉(zhuǎn)換完成后由該位申請產(chǎn)生中斷,還是由軟件查詢該標(biāo)志位A/D轉(zhuǎn)換是否結(jié)束,當(dāng)A/D轉(zhuǎn)換完成后,ADC_FLAG = 1,一定要軟件清0。
ADC_START:模數(shù)轉(zhuǎn)換器(ADC)轉(zhuǎn)換啟動控制位,設(shè)置為“1”時(shí),開始轉(zhuǎn)換,轉(zhuǎn)換結(jié)束后為0。
CHS2/CHS1/CHS0:模擬輸入通道選擇,CHS2/CHS1/CHS0
2.3 ADC轉(zhuǎn)換結(jié)果調(diào)整寄存器位——ADRJ
ADC轉(zhuǎn)換結(jié)果調(diào)整寄存器位——ADRJ位于寄存器CLK_DIV/PCON中,用于控制ADC轉(zhuǎn)換結(jié)果存放的位置。
ADRJ:ADC轉(zhuǎn)換結(jié)果調(diào)整
0:ADC_RES[7:0]存放高8位ADC結(jié)果,ADC_RESL[1:0]存放低2位ADC結(jié)果
1:ADC_RES[1:0]存放高2位ADC結(jié)果,ADC_RESL[7:0]存放低8位ADC結(jié)果
2.4 A/D轉(zhuǎn)換結(jié)果寄存器ADC_RES、ADC_RESL
特殊功能寄存器ADC_RES和ADC_RESL寄存器用于保存A/D轉(zhuǎn)換結(jié)果,其格式如下:
CKKO_DIV寄存器的ADRJ位是A/D轉(zhuǎn)換結(jié)果寄存器(ADC_RES,ADC_RESL)的數(shù)據(jù)格式調(diào)整控制位。
當(dāng)ADRJ=0時(shí),10位是A/D轉(zhuǎn)換結(jié)果的高8位存放在在ADC_RES中,低2位存放在ADC_RESL的低2位中。
2.5 中斷允許寄存器IE
IE : 中斷允許寄存器 (可位尋址)
EA : CPU的中斷開放標(biāo)志
EA=1,CPU開放中斷,
EA=0,CPU屏蔽所有的中斷申請。
EA的作用是使中斷允許形成多級控制。即各中斷源首先受EA控制;其次還受各中斷源自己的中斷允許控制位控制。
EADC : A/D轉(zhuǎn)換中斷允許位
EADC=1,允許A/D轉(zhuǎn)換中斷,
EADC=0,禁止A/D轉(zhuǎn)換中斷。
2.6 A/D轉(zhuǎn)換典型應(yīng)用線路
三、測試程序
3.1 中斷方式
#include "stc15.h"
#include "intrins.h"
#include "delay.h"
#define uchar unsigned char
#define uint unsigned int
#define FOSC 11059200L //系統(tǒng)頻率
#define BAUD 9600 //串口波特率
void UatrInit();
void SendData(uchar dat);
void SendString(char *s);
void AdInit();
uchar num[10] = {'0','1','2','3','4','5','6','7','8','9'};
uint adc_result = 0;
void main()
{
P1M0 = 0x02;
P1M1 = 0x00;
UatrInit();
AdInit();
EA = 1; // CPU開放中斷
while (1);
}
// 初始化串口
void UatrInit()
{
SCON = 0x50; //8位可變波特率 串口工作模式1
T2L = (65536 - (FOSC/4/BAUD)); //設(shè)置波特率重裝值
T2H = (65536 - (FOSC/4/BAUD)) >?>8;
AUXR = 0x14; //T2為1T模式, 并啟動定時(shí)器2
AUXR |= 0x01; //選擇定時(shí)器2為串口1的波特率發(fā)生器
ES = 1; //使能串口1中斷
}
// 初始化ADC
void AdInit()
{
P1ASF = 0x01; // P1.0作為模擬功能A/D使用
ADC_RES = 0;
ADC_RESL = 0; // 結(jié)果寄存器清零
ADC_CONTR = 0x88; // 打開ADC的電源 540個(gè)周期轉(zhuǎn)換一次 選擇P1.0作為A/D輸入來用
delayus(20);
EADC = 1; // 允許A/D轉(zhuǎn)換中斷
}
// ADC中斷服務(wù)函數(shù)
void adc_isr() interrupt 5
{
ADC_CONTR &= !0x10; // 清除ADC中斷標(biāo)志
adc_result = ADC_RES*4 + ADC_RESL; // 獲取ADC結(jié)果,高2位在前
SendData(num[adc_result/1000]); // 千
SendData(num[adc_result%1000/100]); // 百
SendData(num[adc_result%100/10]); // 十
SendData(num[adc_result%10]); // 個(gè)
// SendData(ADC_RES);
// SendData(ADC_RESL);
SendString("\\r\\n"); // 換行
ADC_CONTR =