1. 程式人生 > >模數轉換(A/D)與數模轉換(D/A)

模數轉換(A/D)與數模轉換(D/A)

微控制器是一個典型的數字系統,數字系統只能呢個對輸入的數字訊號進行處理,其輸出訊號也是數字的。但工業或者生活中的很多量都是模擬量,這些模擬量可以通過感測器變成與之對應的電壓、電流等模擬量。為了實現數字系統對這些電模擬量的測量,運算和控制,就需要一個模擬量和數字量之間的相互轉化的過程。

A/D和D/A的基本概念

A/D是模擬量到數字量的轉換,依靠的是模數轉換器(Analog to Digital Converter),簡稱ADC。D/A是數字量到模擬量的轉換,依靠的是數模轉換器(Digital to Analog Converter),簡稱DAC。它們的道理是完全一樣的,只是轉換方向不同,因此我們講解過程主要以A/D為例來講解。 
什麼是模擬量?就是指變數在一定範圍內連續變化的量,總之,任何兩個數字之間都有無限箇中間值,所以稱之為連續變化的量,也就是模擬量。ADC就是起到把連續的訊號用離散的數字表達出來的作用

A/D的主要指標

我們在選取和使用A/D的時候,依靠什麼指標很重要。由於AD的種類很多,分為積分型,逐次逼近型,並行/序列比較型,Σ-Δ型等多種型別。同時指標也比較多,並且有的指標還有輕微差別。

1.ADC的位數

一個n位的ADC表示這個ADC共有2的n次方個刻度。8位ADC,輸出的是從0-255的256個數字,也就是2的8次方的一個數據刻度。

2.基準源

基準源也叫基準電壓,是ADC的1個重要標準,要想把輸入ADC的訊號測量準確,那麼基準源首先要準,基準源的偏差會導致轉換結果的偏差比如一根米尺,總長度本應該是1米,假定這根米尺被火烤了一下,實際變成了1.2米,再用這根米尺測物體長度的話自然就有了較大的偏差。假如我們的基準源應該是5.10V,但是實際上提供的卻是4.5V,這樣誤把4.5V當成了5.10V來處理的話,偏差也會比較大。

3.解析度

解析度是數字量變化的一個最小刻度時,模擬訊號的變化量,定義為滿刻度量程與2n-1的比值。假定5.10V的電壓系統,使用8位的ADC進行測量,那麼相當於0-255一共256個刻度把5.10V劃分成255份,那麼解析度就是5.10/255=0.02V.

INL(積分非線性度)和DNL(差分非線性度)

一般容易混淆兩個概念就是解析度和精度,認為解析度越高,則精度越高,而實際上,兩者並沒有必然的聯絡。解析度是用來描述刻度劃分的,而精度是用來描述準確程度。同樣一根米尺,刻度數相同,解析度就相當,但是精度卻可以相差很大,ADC精度關係重大的兩個指標是INL(Integral NonLiner)和DNL(Differencial NonLiner)。 
INL指的是ADC器件在所有的數值上對應的模擬值,和真實值之間的誤差最大的哪一個點的誤差值,是ADC最重要的一個精度標準,單位是LSB。LSB是最低有效位的意思,那麼實際上對應的就是ADC的解析度。一個基準為5.10V的8位ADC,它的解析度就是0.02V,用它去測量一個電壓訊號,得到的實際結果是100,就是表示它測到的電壓值是100*0.02=2V,假定它的INL是1LSB,就是表示這個電壓訊號真實的準確值是在1.98V——2.02之間的,按理想情況對應的數字因該是99-101,測量誤差是一個最低的有效位,即1LBS。 
DNL表示的是ADC相鄰兩個刻度之間最大的差異,單位也是LSB。一把解析度是1毫米的尺子,相鄰的刻度之間並不都剛好是一毫米,而總是會存在或大或小的誤差。同理,一個ADC的兩個刻度線之間也不總是準確的等於解析度,也是存在誤差,這個就是DNL。一個基準為5.10V的8位ADC,假定DNL是0.5LSB,那麼當它的轉換結果從100增加到101時,理想情況下實際電壓應該增加0.02V,但DNL為0.5LSB的情況下實際電壓為0.01——0.03V之間,值得一提的是DNL並非一定小於1LSB,很多時候它會等於或者大於1LSB,這在相當一定程度上刻度紊亂,當實際電壓保持不變時,ADC得出的結果可能會在幾個數值之間跳動,很大程度上由於這個原因(但並不完全是,因為還有很多幹擾)。

5.轉換速率

轉換速率,是指ADC每秒能進行取樣轉換的最大次數,單位是sps(或s/s、sa/s,即samples per second),它與ADC完成一次從模擬到數字的轉換所需要的時間互為倒數關係。ADC的種類比較多,其中積分型的ADC轉換時間是毫秒級的,屬於低速ADC;逐次逼近型ADC轉換時間是微妙級的,屬於中速ADC;並行/序列的ADC的轉換時間可達到納秒級,屬於高速ADC。 
ADC的這幾個主要指標大家先熟悉一下,對於其它的,作為一個入門級別的選手來說,先不著急深入理解。以後使用過程中遇到了,再查詢相關資料深入學習,當前重點是在頭腦中建立一個ADC的基本概念。

PCF8591

PCF8591是一個單電源低功耗的8位CMOS資料採集器件,具有4路模擬輸入,1路模擬輸出和一個序列I2C匯流排介面用來與微控制器通訊。引腳1、2、3、4是4路模擬輸入,引腳5、6、7是I2C匯流排的硬體地址,8腳是數字地GND,9腳和10腳是I2C匯流排的SDA和SCL。12腳是時鐘選擇引腳,如果接高電平表示用外部時鐘輸入,接低電平則用內部時鐘,我們這套電路用的是內部時鐘,因此12腳直接接GND,同時11腳懸空。13腳是模擬地AGND,在實際開發中,如果有比較複雜的類比電路,那麼AGND部分在佈局佈線上要特別處理,而且和GND的連線也有多種方式,這裡大家先了解即可。在我們板子上沒有複雜的模擬部分電路,所以我們把AGND和GND接到一起。14腳是基準源,15腳是DAC的模擬輸出,16腳是供電電源VCC。 
PCF8591的ADC是逐次逼近型的,轉換速率算是中速,但是它的速度瓶頸在I2C通訊上。由於I2C通訊速度較慢,所以最終的PCF8591的轉換速度,直接取決於I2C的通訊速率。由於I2C速度的限制,所以PCF8591得算是個低速的AD和DA的整合,主要應用在一些轉換速度要求不高,希望成本較低的場合,比如電池供電裝置,測量電池的供電電壓,電壓低於某一個值,報警提示更換電池等類似場合。 
軟體程式設計 
PCF8591的通訊介面是I2C,那麼程式設計肯定是要符合這個協議的。微控制器對PCF8591進行初始化,一共傳送三個位元組即可。第一個位元組,和EEPROM類似,是器件地址位元組,其中7位代表地址,1位代表讀寫方向。地址高4位固定是0b1001,低三位是A2,A1,A0,這三位我們電路上都接了GND,因此也就是0b000,傳送到PCF8591的第二個位元組將被儲存在控制暫存器,用於控制PCF8591的功能。其中第3位和第7位是固定的0,另外6位各自有各自的作用。 
控制位元組的第6位是DA使能位,這一位置1表示DA輸出引腳使能,會產生模擬電壓輸出功能。第4位和第5位可以實現把PCF8591的4路模擬輸入配置成單端模式和差分模式,單端模式和差分模式的區別,我們在17.5節有介紹,這裡大家只需要知道這兩位是配置AD輸入方式的控制位即可 
控制位元組的第2位是自動增量控制位,自動增量的意思就是,比如我們一共有4個通道,當我們全部使用的時候,讀完了通道0,下一次再讀,會自動進入通道1進行讀取,不需要我們指定下一個通道,由於A/D每次讀到的資料,都是上一次的轉換結果,所以同學們在使用自動增量功能的時候,要特別注意,當前讀到的是上一個通道的值。為了保持程式的通用性,我們的程式碼沒有使用這個功能,直接做了一個通用的程式。 
控制位元組的第0位和第1位就是通道選擇位了,00、01、10、11代表了從0到3的一共4個通道選擇。 
傳送給PCF8591的第三個位元組D/A資料暫存器,表示D/A模擬輸出的電壓值。D/A模擬我們一會介紹,大家知道這個位元組的作用即可。我們如果僅僅使用A/D功能的話,就可以不傳送第三個位元組。

/* 讀取當前的ADC轉換值,chn-ADC通道號0~3 */

unsigned char GetADCValue(unsigned char chn)
      {
unsigned char val;

I2CStart();
if (!I2CWrite(0x48<<1))  //定址PCF8591,如未應答,則停止操作並返回0
{
    I2CStop();
    return 0;
}
I2CWrite(0x40|chn);         //寫入控制位元組,選擇轉換通道
I2CStart();
I2CWrite((0x48<<1)|0x01);  //定址PCF8591,指定後續為讀操作    
I2CReadACK();                //先空讀一個位元組,提供取樣轉換時間
val = I2CReadNAK();         //讀取剛剛轉換完的值
I2CStop();
return val;
 }

DAC的輸出

此處輸入程式碼/* 設定DAC輸出值,val-設定值 */
 void SetDACOut(unsigned char val)
  {
I2CStart();
if (!I2CWrite(0x48<<1)) //定址PCF8591,如未應答,則停止操作並返回
{
    I2CStop();
    return;
}
I2CWrite(0x40);         //寫入控制位元組
I2CWrite(val);          //寫入DA值  
I2CStop();
}