6.2 模數轉換的ADC實驗
6.2.1、實例功能
AVR的模數轉換器ADC具有下列特點:
在本實例中,我們將編寫程序實現將模數轉換后獲得的電壓值通過單片機的串口發送到計算機,然后通過計算機上的串口助手顯示測量的電壓值。
本實例共有3個功能模塊,分別描述如下:
● 單片機系統:使用單片機的串口實現將模數轉換后獲得的電壓值通過串口發送到計算機。
● 外圍電路:RS232電平轉換電路,DB9串行接口插座,模擬電壓輸入采集電路。
● 軟件程序:進一步熟悉單片機的串行通信,并掌握單片機的模數轉換的方法。
6.2.2、器件和原理
關于串行接口的原理已接單片機與計算機的串口的連接在上一實例中進行了描述,在本實例中不再重復。
本實例只介紹ATmega16單片機如何通過內置的模數轉換模塊采集外界輸入的模擬電壓。
1、ATmega16單片機的模數轉換器ADC介紹
由于單片機只能處理數字信號,所以外部的模擬信號量需要轉變成數字量才能進一步的由單片機進行處理。ATmega16內部集成有一個10位逐次比較(successive approximation)ADC電路。因此使用AVR可以非常方便的處理輸入的模擬信號量。
ATmega16的ADC與一個8通道的模擬多路選擇器連接,能夠對以PORTA作為ADC輸入引腳的8路單端模擬輸入電壓進行采樣,單端電壓輸入以0V(GND)為參考。另外還支持16種差分電壓輸入組合,其中2種差分輸入方式(ADC1,ADC0和ACD3,ADC2)帶有可編程增益放大器,能在A/D轉換前對差分輸入電壓進行0dB(1×),20dB(10×)或46dB(200×)的放大。還有七種差分輸入方式的模擬輸入通道共用一個負極(ADC1),此時其它任意一個ADC引腳都可作為相應的正極。若增益為1×或10×,則可獲得8位的精度。如果增益為200×,那么轉換精度為7位。
AVR的ADC功能單元由獨立的專用模擬電源引腳AVcc供電。AVcc和Vcc的電壓差別不能大于±0.3V。ADC轉換的參考電源可采用芯片內部的2.56V參考電源,或采用AVcc,也可使用外部參考電源。使用外部參考電源時,外部參考電源由引腳ARFE接入。使用內部電壓參考源時,可以通過在AREF引腳外部并接一個電容來提高ADC的抗噪性能。
ADC功能單元包括采樣保持電路,以確保輸入電壓在ADC轉換過程中保持恒定。ADC通過逐次比較(successive approximation)方式,將輸入端的模擬電壓轉換成10位的數字量。最小值代表地,最大值為AREF引腳上的電壓值減1個LSB。可以通過ADMUX寄存器中REFSn位的設置,選擇將芯片內部參考電源(2.56V)或AVcc連接到AREF,作為A/D轉換的參考電壓。這時,內部電壓參考源可以通過外接于AREF引腳的電容來穩定,以改進抗噪特性。
模擬輸入通道和差分增益的選擇是通過ADMUX寄存器中的MUX位設定的。任何一個ADC的輸入引腳,包括地(GND)以及內部的恒定能隙(fixed bandgap)電壓參考源,都可以被選擇用來作為ADC的單端輸入信號。而ADC的某些輸入引腳則可選擇作為差分增益放大器的正、負極輸入端。當選定了差分輸入通道后,差分增益放大器將兩輸入通道上的電壓差按選定增益系數放大,然后輸入到ADC中。若選定使用單端輸入通道,則增益放大器無效。
通過設置ADCSRA寄存器中的ADC使能位ADEN來使能ADC。在ADEN沒有置“1”前,參考電壓源和輸入通道的選定將不起作用。當ADEN位清“0”后,ADC將不消耗能量,因此建議在進入節電休眠模式前將ADC關掉。
ADC將10位的轉換結果放在ADC數據寄存器中(ADCH和ADCL)。默認情況下,轉換結果為右端對齊(RIGHT ADJUSTED)的。但可以通過設置ADMUX寄存器中ADLAR位,調整為左端對齊(LEFT ADJUSTED)。如果轉換結果是左端對齊,并且只需要8位的精度,那么只需讀取ADCH寄存器的數據作為轉換結果就達到要求了。否則,必須先讀取ADCL寄存器,然后再讀取ADCH寄存器,以保證數據寄存器中的內容是同一次轉換的結果。因為一旦ADCL寄存器被讀取,就阻斷了ADC對ADC數據寄存器的操作。這就意味著,一旦指令讀取了ADCL,那么必須緊接著讀取一次ADCH;如果在讀取ADCL和讀取ADCH的過程中正好有一次ADC轉換完成,ADC的2個數據寄存器的內容是不會被更新的,該次轉換的結果將丟失。只有當ADCH寄存器被讀取后,ADC才可以繼續對ADCL和ADCH寄存器操作更新。
ADC有自己的中斷,當轉換完成時中斷將被觸發。盡管在順序讀取ADCL和ADCH寄存器過程中,ADC對ADC數據寄存器的更新被禁止,轉換的結果丟失,但仍會觸發ADC中斷。
2、ATmwga16單片機的模數轉換器ADC相關的I/O寄存器
1.ADC多路復用器選擇寄存器—ADMUX
REFS1、REFS2用于選擇ADC的參考電壓源,見表6.2.1。如果這些位在ADC轉換過程中被改變,新的選擇將在該次ADC轉換完成后(ADCSRA中的ADIF被置位)才生效。一旦選擇內部參考源(AVcc、2.56V)為ADC的參考電壓后,AREF引腳上不得施加外部的參考電源,只能與GND之間并接抗干擾電容。
表6.2.1 ADC參考電源選擇 |
||
REFS1 |
REFS0 |
ADC參考電源 |
0 |
0 |
外部引腳AREF,斷開內部參考源連接 |
0 |
1 |
AVcc,AREF外部并接電容 |
1 |
0 |
保留 |
1 |
1 |
內部2.56V,AREF外部并接電容 |
ADLAR位決定轉換結果在ADC數據寄存器中的存放形式。寫“1”到ADLAR位,將使轉換結果左對齊(LEFT ADJUST);否則,轉換結果為右對齊(RIGHT ADJUST)。無論ADC是否正在進行轉換,改變ADLAR位都將會立即影響ADC數據寄存器。
這5個位用于對連接到ADC的輸入通道和差分通道的增益進行選擇設置,詳見表6.2.2。注意,只有轉換結束后(ADCSRA的ADIF是“1”),改變這些位才會有效。
表6.2.2 ADC輸入通道和增益選擇 |
||||
MUX[4:0] |
單端輸入 |
差分正極輸入 |
差分負極輸入 |
增益 |
00000 |
ADC0 |
N/A |
||
00001 |
ADC1 |
|||
00010 |
ADC2 |
|||
00011 |
ADC3 |
|||
00100 |
ADC4 |
|||
00101 |
ADC5 |
|||
00110 |
ADC6 |
|||
00111 |
ADC7 |
|||
01000 |
N/A |
ADC0 |
ADC0 |
10× |
01001 |
ADC1 |
ADC0 |
10× |
|
01010 |
ADC0 |
ADC0 |
200× |
|
01011 |
ADC1 |
ADC0 |
200× |
|
01100 |
ADC2 |
ADC2 |
10× |
|
01101 |
ADC3 |
ADC2 |
10× |
|
01110 |
ADC2 |
ADC2 |
200× |
|
01111 |
ADC3 |
ADC2 |
200× |
|
10000 |
ADC0 |
ADC1 |
1× |
|
10001 |
ADC1 |
ADC1 |
1× |
|
10010 |
ADC2 |
ADC1 |
1× |
|
10011 |
ADC3 |
ADC1 |
1× |
|
10100 |
ADC4 |
ADC1 |
1× |
|
10101 |
ADC5 |
ADC1 |
1× |
|
10110 |
ADC6 |
ADC1 |
1× |
|
10111 |
ADC7 |
ADC1 |
1× |
|
11000 |
ADC0 |
ADC2 |
1× |
|
11001 |
ADC1 |
ADC2 |
1× |
|
11010 |
ADC2 |
ADC2 |
1× |
|
11011 |
ADC3 |
ADC2 |
1× |
|
11100 |
ADC4 |
ADC2 |
1× |
|
11101 |
ADC5 |
ADC2 |
1× |
|
11110 |
1.22V(VBG) |
N/A |
||
11111 |
0V(GND) |
本實例中我們需要設置ADC的參考電壓源為AVcc,即REFS0設置為1,ADC默認轉換結果為右對齊,我們不需要改變,模擬通道選擇ADC0通道單端輸入,即MUX4:0。
2.ADC控制和狀態寄存器A—ADCSRA
該位寫入“1”時使能ADC,寫入“0”關閉ADC。如在ADC轉換過程中將ADC關閉,該次轉換隨即停止。
在單次轉換模式下,置該位為“1”,將啟動一次轉換。在自由連續轉換模式下,該位寫入“1”將啟動第一次轉換。先置位ADEN位使能ADC,再置位ADSC;或置位ADSC的同時使能ADC,都會使能ADC開始進行第一次轉換。第一次ADC轉換將需要25個ADC時鐘周期,而不是常規轉換的13個ADC時鐘周期,這是因為第一次轉換需要完成對ADC的初始化。
在ADC轉換的過程中,ADSC將始終讀出為“1”。當轉換完成時,它將轉變為“0”。強制寫入“0”是無效的。
當該位被置為“1”時,允許ADC工作在自動轉換觸發工作模式下。在該模式下,在觸發信號的上升沿時ADC將自動開始一次ADC轉換過程。ADC的自動轉換觸發信號源由SFIOR寄存器中的ADTS位選擇確定。
當ADC轉換完成并且ADC數據寄存器被更新后該位被置位。如果ADIE位(ADC轉換結束中斷允許)和SREG寄存器中的I位被置“1”,ADC中斷服務程序將被執行。ADIF在執行相應的中斷處理向量時被硬件自動清零。此外,ADIF位可以通過寫入邏輯“1”來清零。
當該位和SREG寄存器中的I位同時被置位時,允許ADC轉換完成中斷。
這些位決定了XTAL時鐘與輸入到ADC的ADC時鐘之間分頻數,見表6.2.3。
表6.2.3 ADC時鐘分頻 |
|
ADPS[2:0] |
分 頻 系 數 |
000 |
2 |
001 |
2 |
010 |
4 |
011 |
8 |
100 |
16 |
101 |
32 |
110 |
64 |
111 |
128 |
本實例中我們需要使能ADC,即ADEN設置為1,我們不用自動轉換,也不需要中斷,所以,ADTE、ADIE位不需要設置。在通常情況下,ADC的逐次比較轉換電路要達到最大精度時,需要50kHz~200kHz之間的采樣時鐘。本例中使用的時鐘是12M的,所以要將時鐘64分頻,分頻后ADC頻率為188KHz,即時鐘分頻選擇ADPS[2:0]=6。
3.ADC數據寄存器—ADCL和ADCH
當ADC轉換完成后,可以讀取ADC寄存器的ADC0-ADC9得到ADC的轉換的結果。如果是差分輸入,轉換值為二進制的補碼形式。一旦開始讀取ADCL后,ADC數據寄存器就不能被ADC更新,直到ADCH寄存器被讀取為止。因此,如果結果是左對齊(ADLAR=1),且不需要大于8位的精度的話,僅僅讀取ADCH寄存器就足夠了。否則,必須先讀取ADCL寄存器,再讀取ADCH寄存器。ADMUX寄存器中的ADLAR位決定了從ADC數據寄存器中讀取結果的格式。如果ADLAR位為“1”,結果將是左對齊;如果ADLAR位為“0”(默認情況),結果將是右對齊。
4.特殊功能I/O寄存器—SFIOR
當ADCSRA寄存器中的ADATE為“1”,允許ADC工作在自動轉換觸發工作模式時,這3位的設置用于選擇ADC的自動轉換觸發源。如果禁止了ADC的自動轉換觸發(ADATE為“0”),這3個位的設置值將不起任何作用。
表10-6 ADC自動轉換觸發源的選擇 |
|
ADTS[2:0] |
觸 發 源 |
000 |
連續自由轉換 |
001 |
模擬比較器 |
010 |
外部中斷0 |
011 |
T/C0比較匹配 |
100 |
T/C0溢出 |
101 |
T/C1比較匹配B |
110 |
T/C1溢出 |
111 |
T/C1輸入捕捉 |
本例中我們不使用自動轉換功能,所以該寄存器可以不必設置。
6.2.3、電路
本實例的電路包括232電平轉換電路和電阻分壓電路,這兩種電路在前面的實例中均做過介紹,這里不再重復。
1、電路原理
在本實例中利用MAX3232芯片使單片機輸出的TTL電平轉換為標準的RS232電平,從而使計算機能夠識別。同時將計算機輸出的RS232電平轉換為單片機可以識別的TTL電平。
利用電位器產生電阻分壓電路,從而產生變化的模擬電壓加到單片機的模擬信號采集端口,供單片機采集。
2、電路連接
電路中MAX3232芯片的9、10引腳分別連接單片機的PD0、PD1端口,MAX3232的13、14引腳分別連接計算機串口線的3、2腳。
電位器RP2的動片引腳連接單片機的模擬信號采集通道PA0(ADC0)。
3、特別說明
本學習板采用的是串口插座是公頭的,所以與計算機相連的串口連接線應該是交叉串口線,而不是串口延長線。
6.2.4、程序設計
1、程序功能
程序的功能是通過單片機的串行接口,將單片機采集到的模擬電壓值發送到計算機中,通過計算機上的串口助手顯示采集的電壓值。
● 單片機串行接收中斷的編程
在本例中,我們用到了單片機的串行接收中斷,需要編寫串行接收中斷服務程序,通過查詢WINAVR(GCC)的中斷庫函數手冊,可以查找到ATmega16單片機串行接收中斷的中斷向量為USART_RXC_vect。據此我們可以編寫串行接收中斷服務程序,如下:
//接收中斷函數
ISR(USART_RXC_vect )
{
unsigned char Rev;
Rev = UDR; //從USART I/O數據寄存器-UDR中讀出數據
Usart_PutChar(Rev); //將接收到的數據發送
}
在中斷服務程序中,我們首先把單片機串口接收到的數據放入變量Rev中,然后調用上一實例中編寫的串行接口字節發送函數將變量Rev中的數據發送到計算機。
2、 單片機與計算機串行通信結果的觀察
在觀察本例運行結果時,我們同樣要用到串口助手,本例中,單片機發送串口數據采用的波特率是9600bps,數據格式是8位數據位,1位停止位,無奇偶校驗。在串口助手里面,我們也要將波特率和數據格式設置成一樣的。
3、函數說明
本實例用到了6個函數,分別是:
void Port_Init(void); //端口初始化配置
void Usart_Init(void); //USART寄存器設置
void AD_Init(void); //AD初始化
void Usart_PutChar(unsigned char cTXData); //字節發送函數
void Usart_PutString(unsigned char *pcString); // 字符串發送數據
unsigned int AD_GetData(void); //AD轉換函數
4、使用WINAVR開發環境,在本例中我們使用的是外部12M的晶振,所以需要將MAKEFILE文件中的時鐘頻率修改為12M。另外在程序燒錄到單片機的時候,熔絲位也要選擇為外部12M晶振(注意是晶振,不是外部振蕩器,一定不要選擇錯了,否則會導致單片機不能再燒寫程序)。
5、程序代碼
[code="CSHARP"]
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h> //中斷函數頭文件
//常量聲明
#define BAUD 9600 //波特率設置值
//全局變量聲明
unsigned int ADData; //AD轉換獲得的數據
//函數聲明
void Port_Init(void); //端口初始化配置
void Usart_Init(void); //USART寄存器設置
void AD_Init(void); //AD初始化
void Usart_PutChar(unsigned char cTXData); //字節發送函數
void Usart_PutString(unsigned char *pcString); // 字符串發送數據
unsigned int AD_GetData(void); //AD轉換函數
int main(void)
{
unsigned char Delay3s;
Port_Init();
Usart_Init();
AD_Init();
Usart_PutString("AD轉換測試程序");
Usart_PutString("測得ADC0通道的電壓值為:");
sei(); //使能全局中斷
while(1)
{
ADData = (int)((long)AD_GetData() * 5010 / 1024); //將獲得的AD值轉換為電壓值
//單位為mv。
Usart_PutChar(ADData / 1000 + 0x30); //得到電壓值的千位并發送
Usart_PutChar('.'); //發送小數點
Usart_PutChar(ADData % 1000 / 100 + 0x30); //得到電壓值的百位并發送
Usart_PutChar(ADData % 100 / 10 + 0x30); //得到電壓值的十位并發送
Usart_PutChar(ADData % 10 + 0x30); //得到電壓值的個位并發送
Usart_PutChar('V'); //發送電壓符號“V”
Usart_PutChar(0x0d); //
Usart_PutChar(0x0a); // AD值發送結束,回車換行
for(Delay3s = 0;Delay3s < 30;Delay3s++) //延時3S
{
_delay_ms(90);
}
}
}
//端口狀態初始化設置函數
void Port_Init()
{
PORTA = 0X00;
DDRA = 0x00; //ADC通道設置為輸入口,高阻態
}
//USART寄存器配置函數
void Usart_Init()
{
UCSRA = 0X00;
UCSRC |= (1<<URSEL) | (1 << UCSZ1) | (1 << UCSZ0); //異步,數據格式8,N,1
//UCSRC寄存器與UBRRH寄存器共用相同的I/O地址,寫 UCSRC 時, URSEL 應設置為 1。
UBRRL = (F_CPU / BAUD / 16 - 1) % 256; //波特率設置
UBRRH = (F_CPU / BAUD / 16 - 1) / 256;
UCSRB |= (1 << RXCIE) | (1 << RXEN) | (1 << TXEN); //發送使能
}
//字節發送函數
void Usart_PutChar(unsigned char cTXData)
{
while( !(UCSRA & (1 << UDRE)) ); //只有數據寄存器為空時才能發送數據
UDR = cTXData; //發送數據送USART I/O數據寄存器-UDR
}
//接收中斷函數
ISR(USART_RXC_vect )
{
unsigned char Rev;
Rev = UDR; //從USART I/O數據寄存器-UDR中讀出數據
Usart_PutChar(Rev); //將接收到的數據發送
}
void Usart_PutString(unsigned char *pcString)
{
while (*pcString)
{
Usart_PutChar(*pcString++);
}
Usart_PutChar(0x0D);
Usart_PutChar(0x0A); //結尾發送回車換行
}
//AD轉換初始化函數
void AD_Init()
{
ADMUX |= (1 << REFS0); //ADC參考電壓為AVcc,ADC結果右對齊,選擇通道ADC0
ADCSRA |= (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1); //使能AD轉換,ADC時鐘64分頻
}
//AD轉換函數
unsigned int AD_GetData()
{
ADCSRA |= (1 << ADSC); //開始AD轉換
while(!(ADCSRA & (1 << ADIF))); //等待轉換完成
ADCSRA |= (1 << ADIF); //清零ADC中斷標志位
return ADC; //返回ADC值
}
[/code]
1.預分頻與轉換時間
在通常情況下,ADC的逐次比較轉換電路要達到最大精度時,需要50kHz~200kHz之間的采樣時鐘。在要求轉換精度低于10位的情況下,ADC的采樣時鐘可以高于200kHz,以獲得更高的采樣率。
ADC模塊中包含一個預分頻器的ADC時鐘源,它可以對大于100KHz的系統時鐘進行分頻,以獲得合適的ADC時鐘提供ADC使用。預分頻器的分頻系數由ADCSRA寄存器中的ADPS位設置的。一旦寄存器ADCSRA中的ADEN位置“1”(ADC開始工作),預分頻器就啟動開始計數。ADEN位為“1”時,預分頻器將一直工作;ADEN位為“0”時,預分頻器一直處在復位狀態。
AVR的ADC完成一次轉換的時間見表6.2.5。從表中可以看出,完成一次ADC轉換通常需要13-14個ADC時鐘。而啟動ADC開始第一次轉換到完成的時間需要25個ADC時鐘,這是因為要對ADC單元的模擬電路部分進行初始化。
表6.2.5 ADC轉換和采樣保持時間 |
||
轉 換 形 式 |
采樣保持時間 |
完 成 轉 換 總 時 間 |
啟動ADC后的第一次轉換 |
13.5個ADC時鐘 |
25個ADC時鐘 |
正常轉換,單端輸入 |
1.5個ADC時鐘 |
13個ADC時鐘 |
自動觸發方式 |
2個ADC時鐘 |
13.5個ADC時鐘 |
正常轉換,差分輸入 |
1.5/2.5個ADC時鐘 |
13/14個ADC時鐘 |
當ADCSRA寄存器中的ADSC位置位,啟動ADC轉換時,A/D轉換將在隨后ADC時鐘的上升沿開始。一次正常的A/D轉換開始時,需要1.5個ADC時鐘周期的采樣保持時間(ADC首次啟動后需要13.5個ADC時鐘周期的采樣保持時間)。當一次A/D轉換完成后,轉換結果寫入ADC數據寄存器,ADIF(ADC中斷標志位)將被置位。在單次轉換模式下,ADSC也同時被清零。用戶程序可以再次置位ADSC位,新的一次轉換將在下一個ADC時鐘的上升沿開始。
當ADC設置為自動觸發方式時,觸發信號的上升沿將啟動一次ADC轉換。轉換完成的結果將一直保持到下一次觸發信號的上升沿出現,然后開始新的一次ADC轉換。這就保證了使ADC每隔一定的時間間隔進行一次轉換。在這種方式下,ADC需要2個ADC時鐘周期的采樣保持時間。
在自由連續轉換模式下,一次轉換完畢后馬上開始一次新的轉換,此時,ADSC位一直保持為“1”。
2.ADC輸入通道和參考電源的選擇
寄存器ADMUX中的MUXn和REFS1、REFS0位實際上是一個緩沖器,該緩沖器與一個MCU可以隨機讀取的臨時寄存器相連通。采用這種結構,保證了ADC輸入通道和參考電源只能在ADC轉換過程中的安全點被改變。在ADC轉換開始前,通道和參考電源可以不斷被更新,一旦轉換開始,通道和參考電源將被鎖定,并保持足夠時間,以確保ADC轉換的正常進行。在轉換完成前的最后一個ADC時鐘周期(ADCSRA的ADIF位置“1”時),通道和參考電源又開始重新更新。注意,由于A/D轉換開始于置位ADSC后的第一個ADC時鐘的上升沿,因此,在置位ADSC后的一個ADC時鐘周期內不要將一個新的通道或參考電源寫入到ADMUX寄存器中。
改變差分輸入通道時需特別當心。一旦確定了差分輸入通道,增益放大器需要125μs的穩定時間。所以在選擇了新的差分輸入通道后的125μs內不要啟動A/D轉換,或將這段時間內轉換結果丟棄。通過改變ADMUX中的REFS1、REFS0來更改參考電源后,第一次差分轉換同樣要遵循以上的時間處理過程。
在單次轉換模式下,總是在開始轉換前改變通道設置。盡管輸入通道改變發生在ADSC位被寫入“1”后的1個ADC時鐘周期內,然而,最簡單的方法是等到轉換完成后,再改變通道選擇。
在連續轉換模式下,總是在啟動ADC開始第一次轉換前改變通道設置。盡管輸入通道改變發生在ADSC位被寫入“1”后的1個ADC時鐘周期內,然而,最簡單的方法是等到第一次轉換完成后再改變通道的設置。然而由于此時新一次的轉換已經自動開始,所以,當前這次的轉換結果仍反映前一通道的轉換值,而下一次的轉換結果將為新設置通道的值。
ADC的參考電壓(VREF)決定了A/D轉換的范圍。如果單端通道的輸入電壓超過VREF,將導致轉換結果接近于0x3FF。ADC的參考電壓VREF可以選擇為AVCC或芯片內部的2.56V參考源,或者為外接在AREF引腳上的參考電壓源。
AVCC通過一個無源開關連接到ADC。內部2.56V參考源是由內部能隙參考源(VBC)通過內部的放大器產生的。注意,無論選用什么內部參考電源,外部AREF引腳都是直接與ADC相連的,因此,可以通過外部在AREF引腳和地之間并接一個電容,使內部參考電源更加穩定和抗噪。可以通過使用高阻電壓表測量AREF引腳,來獲得參考電源VREF的電壓值。由于VREF是一個高阻源,因此,只有容性負載可以連接到該引腳。
如果將一個外部固定的電壓源連接到AREF引腳,那就不能使用任何的內部參考電源,否則就會使外部電壓源短路。外部參考電源的范圍應在2.0V到AVCC-0.2V之間。參考電源改變后的第一次ADC轉換結果可能不太準確,建議拋棄該次轉換結果。
3.ADC轉換結果
A/D轉換結束后(ADIF = 1),在ADC數據寄存器(ADCL和ADCH)中可以取得轉換的結果。對于單端輸入的A/D轉換,其轉換結果為:
ADC =(VIN×1024)/ VREF
其中VIN表示選定的輸入引腳上的電壓,VREF表示選定的參考電源的電壓。0x000表示輸入引腳的電壓為模擬地,0x3FF表示輸入引腳的電壓為參考電壓值減去一個LSB。
對于差分轉換,其結果為:
ADC=(VPOS-VNEG) ×GAIN×512/VREF
例:若差分輸入通道選擇為ADC3-ADC2,10倍增益,參考電壓2.56V,左端對齊(ADMUX=0xED),ADC3引腳上電壓300mV,ADC2引腳上電壓500mV。
則ADCR =(300-500)×10×512 / 2560 = -400 = 0x270
ADCL=0x00,ADCH=0x9C。
若結果為右端對齊時(ADLAR=“0”),則ADCL=0x70,ADCH=0x02。
附錄2、ADC應用設計的深入討論
盡管AVR內部集成了10位的ADC,但是在實際應用中,要想真正實現10位精度,比較穩定的ADC的話,并不象上一節中的例子那么簡單。需要進一步從硬件、軟件等方面進行綜合的、細致的考慮。下面介紹一些在ADC設計應用中應該考慮的幾個要點。
1.AVcc的穩定性。
AVcc是提供給ADC工作的電源,如果AVcc不穩定,就會影響ADC的轉換精度。在圖10-5中,系統電源通過一個LC濾波后接入AVcc,這樣就能很好的抑制掉系統電源中的高頻躁聲,提高了AVcc的穩定性。另外在要求比較高的場合使用ADC時,PA口上的那些沒被用做ADC輸入的端口盡量不要作為數字I/O口使用。因為PA口的工作電源是由AVcc提供的,如果PA口上有比較大的電流波動,也會影響AVcc的穩定。
2.參考電壓VREF的選擇確定
在實際應用中,要根據輸入測量電壓的范圍選擇正確的參考電壓VREF,以求得到比較好的轉換精度。ADC的參考電壓VREF還決定了A/D轉換的范圍。如果單端通道的輸入電壓超過VREF,將導致轉換結果全部接近于0x3FF,因此ADC的參考電壓應稍大于模擬輸入電壓的最高值。
ADC的參考電壓VREF可以選擇為AVCC,或芯片內部的2.56V參考源,或者為外接在AREF引腳上的參考電壓源。外接參考電壓應該穩定,并大于2.0V(芯片的工作電壓為1.8V時,外接參考電壓應大于1.0V)。要求比較高的場合,建議在AREF引腳外接標準參考電壓源來作為ADC的參考電源。
3. ADC通道帶寬和輸入阻抗
不管使用單端輸入轉換還是差分輸入轉換方式,所有模擬輸入口的輸入電壓應在AVcc-GNG之間。
在單端ADC轉換方式時,ADC通道的輸入頻率帶寬取決于ADC轉換時鐘頻率。一次常規的ADC轉換需要13個ADC時鐘,當ADC轉換時鐘為1MHz時,一秒種內ADC采樣轉換的次數約77K。根據采樣定理,此時ADC通道的帶寬為38.5KHz。
差分方式ADC轉換的帶寬是由芯片內部的差分放大器的帶寬決定,為4KHz。
AVR的ADC輸入阻抗典型值為100MΩ,為保證測量的準確,被測信號源的輸出阻抗要盡可能的低,應在10K以下。
4. ADC采樣時鐘的選擇
通常條件下,AVR的ADC逐次比較電路要達到轉換的最大精度,需要一個50K~200KHz的采樣時鐘。一次正常的ADC轉換過程需要13個采樣時鐘,假定ADC采樣時鐘為200KHz,那么最高的采樣速率為200K/13=15.384K。因此根據采樣定理,理論上被測模擬信號的最高頻率為7.7K!
盡管可以設置ADC的采樣時鐘為1M,但并不能提高ADC轉換精度,反而會降低轉換精度(受逐次比較硬件電路的限制),因此AVR的ADC不能完成高速ADC的任務。如果所需的轉換精度低于10位,那么采樣時鐘可以高于200KHz,以達到更高的采樣頻率。
ADC采樣時鐘的選擇方式為:給出或估計被測模擬信號的最高頻率fs,取采樣頻率為fs的4-10倍,再乘上13為ADC采樣時鐘頻率,該頻率應在50K~200KHz之間。 如果該頻率大于200KHz,則ADC的10位精度不能保證。如果該頻率小于50Khz,則可選擇50K~200KHz之間的數值。
5.模擬噪聲的抑制
器件外部和內部的數字電路會產生電磁干擾,并會影響模擬測量的精度。如果ADC轉換精度要求很高,可以采用以下的技術來降低噪聲的影響:
(1)使模擬信號的通路盡可能的短。模擬信號連線應從模擬地的布線盤上通過,并使它們盡可能遠離高速開關數字信號線。
(2)AVR的AVcc引腳應該通過LC網絡與數字端電源Vcc相連。
(3)采用ADC噪聲抑制器功能來降低來自MCU內部的噪聲。
(4)如果某些ADC引腳是作為通用數字輸出口使用,那么在ADC轉換過程中,不要改變這些引腳的狀態。
6.ADC的校正
由于AVD內部ADC部分的放大器非線性等客觀原因,ADC的轉換結果會有誤差的。如果要獲得高精度的ADC轉換,還需要對ADC結果進行校正。具體的方法請參考AVR應用筆記AVR120(avr_app_120.pdf),在這篇應用設計參考中詳細介紹了誤差的種類,以及校正方案。
7.ADC精度的提高
在有了上述幾點的保證后,通過軟件的手段也能適當的提高ADC的精度。如采用多次測量取平均,軟件濾波算法等。在AVR應用筆記AVR121(avr_app_121.pdf)中介紹了一種使用過采樣算法的軟件實現,可以將ADC的精度提高到11位或更高,當然這是在花費更多的時間基礎上實現的。