ADC在涉及到控制和采樣的系統(tǒng)中,是個十分重要的組件,因為這里作為430的一個特性描述,所以通過430片上自帶的ADC8來簡單介紹ADC相關知識。關于ADC的詳細原理,各種類型,計劃以后專門總結一下。
為什么要有ADC?
單純的CPU是一個數(shù)字系統(tǒng),內(nèi)部只有0101,如果這個系統(tǒng)壓根不跟我們現(xiàn)實世界打交道,完全“自娛自樂”,那就是我們常見的軟件玩法。例如PC上應用軟件、網(wǎng)頁、服務器后端程序等等,。
但是比如智能手機需要通過前置光線感應器知道環(huán)境光線如何來決定是否需要提高屏幕亮度;空調(diào)需要知道室溫從而精準的為你制冷或制熱。這些場景則需要數(shù)字系統(tǒng)和模擬世界打交道了。
那ADC全稱為(Analog Digital Convertor),我的理解就是模擬世界到數(shù)字世界的轉(zhuǎn)換器。反過來,DAC(Digital Analog Convertor)則是數(shù)字到模擬的轉(zhuǎn)換器。
430 2553上的ADC模塊
查看G2553的dataheet,可以看到它內(nèi)置的是AD10模塊,也就是一個10位精度的ADC,datasheet中只是對配置進行了簡單的介紹,要看到ADC10的詳細信息,我們還是要到family user guide中,找到第534頁的ADC10的介紹。這里我們可以看到,ADC10具有如下特性:
上面只挑選了文檔中幾個重要的特性,200k采樣速率指該ADC可以每秒鐘轉(zhuǎn)換20W次,這個速率已經(jīng)很快了,可以滿足我們大部分的需求。10位精度指ADC在將模擬量轉(zhuǎn)換為數(shù)字量的時候可以達到的精度;比如ADC10的采樣范圍是0~3.3V,那10位精度則指可以將0~3.3V等分為2的10次方即1024等分,精度可以達到3mv左右,這也是為什么這個內(nèi)置模塊叫做ADC10的原因,位數(shù)越大,精度越高。內(nèi)置參考源存在的意義是可以幫我們省去搭建外部參考源的麻煩,上手就用。最大8個外部采樣腳可以允許我們同時采樣8個外部的采樣點(當然內(nèi)部是公用一個ADC的,需要一個一個排隊依次采樣,同時采是不可能的)。最后內(nèi)部自帶的溫度采樣可以實現(xiàn)溫度計的功能,可以做一個氣溫計或者跟電腦CPU溫度顯示一樣的功能,不過這個溫度采樣的精度比較低,想作為精確溫度采樣是不行的(不過也不會有人這么做)。
ADC10的內(nèi)部結構

看過前面430時鐘那一章的理解這張圖應該不難,橙色框中的是ADC10的核心,是一個SAR類型的ADC(什么是SAR后面在ADC通用介紹中細說),ADC的輸入接的是一個選擇開關(MUX),這個就是我們?yōu)槭裁纯梢杂?個輸入采樣引腳以及為什么要排隊采樣的原因。綠色框是控制采樣的,位長是4位意味著最大可以支持16個輸入引腳選擇,2553最大只有8個,其他型號會有更多。
信號進入ADC轉(zhuǎn)換前需要經(jīng)過一個叫采樣保持的電路,就是橙色框sample and hoid部分,因為外部輸入的信號是模擬量,所以電壓是不斷波動的,這樣的信號不行直接進行轉(zhuǎn)換,需要使用一個電路對電路瞬間采樣,然后把當時的電壓大小記住保持不變,再輸入ADC進行轉(zhuǎn)換。簡單的采樣保持電路內(nèi)部示意圖如下:

電路前面有一個開關和電容,采樣的時候,開關接通,外部電壓進入給電容充電,完成后斷開,進入保持階段,電容上面的電壓不變,經(jīng)過后面的射集跟隨器,進入ADC轉(zhuǎn)換。
信號進入ADC核心進行轉(zhuǎn)化時,需要標準的參考源才能正常轉(zhuǎn)換,圖片的左上角就是內(nèi)置的1.5V或2.5V參考源,通過各種選擇最終可以進入ADC的VR+引腳使用。ADC內(nèi)部數(shù)字電路工作需要提供時鐘,所以右邊藍色框的就是時鐘選擇電路,在SMCLK等各種時鐘中選擇一個使用。
最后,我們終于將模擬量轉(zhuǎn)成了數(shù)字量,數(shù)字信號可以進入灰色的框部分,供單片機軟件調(diào)用就行了。
ADC10的軟件例程
老規(guī)矩,一切基于code example,打開G2553的code example(看到這里不知道啥是code example的看下我前面的文章),找到msp430g2x33_adc10_03.c這個例程。
//******************************************************************************// MSP430G2x33/G2x53 Demo - ADC10, Sample A10 Temp, Set P1.0 if Temp ++ ~2C//// Description: se ADC10 and the integrated temperature sensor to detect// temperature gradients. The temperature sensor output voltage is sampled// ~ every 120ms and compared with the defined delta values using an ISR.// (ADC10OSC/4)/64 determines sample time which needs to be greater than// 30us for temperature sensor.// ADC10 is operated in repeat-single channel mode with the sample and// convert trigger sourced from Timer_A CCR1. The ADC10IFG at the end// of each converstion will trigger an ISR.// ACLK = n/a, MCLK = SMCLK = default DCO ~ 1.2MHz, ADC10CLK = ADC10OSC//// MSP430G2x33/G2x53// -----------------// /|\| XIN|-// | | |// --|RST XOUT|-// | |// |A10 P1.0|-->LED//// D. Dang// Texas Instruments Inc.// December 2010// Built with CCS Version 4.2.0 and IAR Embedded Workbench Version: 5.10//******************************************************************************看例程中的注釋,ADC10將會每120ms采樣測量一次溫度,如果溫度比程序啟動時高了超過2度,紅色LED燈將會亮起,否則熄滅。我們將這段程序下到launchpad中,效果如下:
下面是對程序的解釋:
#include <msp430.h>static unsigned int FirstADCVal; // 緩存程序啟動時的溫度初始值#define ADCDeltaOn 3 // 溫度上升超過大約2度時翻轉(zhuǎn)LED燈int main(void){ // 關閉看門狗 WDTCTL = WDTPW + WDTHOLD; // ADC10DIV_3:輸入時鐘三分頻 INCH_10:結構圖可知,通道10連接著溫度電阻 SHS_1:TA3 OUT1觸發(fā)采樣保持 CONSEQ_2:單通道重復采樣 ADC10CTL1 = ADC10DIV_3 + INCH_10 + SHS_1 + CONSEQ_2; // 內(nèi)部參考源,64個ADC時鐘一次采樣,2.5V參考源,使能ADC中斷,開啟參考源,開啟ADC10 ADC10CTL0 = SREF_1 + ADC10SHT_3 + REF2_5V + ADC10IE + REFON + ADC10ON; // 使能全局中斷 __enable_interrupt(); TACCR0 = 30; // Delay to allow Ref to settle TACCTL0 |= CCIE; // Compare-mode interrupt. TACTL = TASSEL_2 | MC_1; // TACLK = SMCLK, Up mode. LPM0; // Wait for delay. TACCTL0 &= ~CCIE; // Disable timer Interrupt __disable_interrupt(); ADC10CTL0 |= ENC; TACCTL1 = OUTMOD_4; // Toggle on EQU1 (TAR = 0) TACTL = TASSEL_2 + MC_2; // SMCLK, cont-mode while (!(ADC10IFG & ADC10CTL0)); // First conversion? FirstADCVal = ADC10MEM; // Read out 1st ADC value P1OUT = 0x00; // Clear P1 P1DIR = 0x01; // P1.0 as output __bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupt}#pragma vector=ADC10_VECTOR__interrupt void ADC10_ISR (void){ if (ADC10MEM >= FirstADCVal + ADCDeltaOn) P1OUT |= 0x01; // LED on else P1OUT &= ~0x01; // LED off}#pragma vector=TIMER0_A0_VECTOR__interrupt void ta0_isr(void){ TACTL = 0; LPM0_EXIT; // Exit LPM0 on return}上面只挑選了重點的寄存器進行了注釋,具體寄存器的含義,有兩種方法可以看到是什么意思,其他的可以舉一反三。一種如果使用的是CCS,按住CTRL+左鍵單擊寄存器,可以跳到宏定義的頭文件,官方對每個取值進行了注釋。第二種就是參看《MSP430x2xx Family User’s Guide》文檔,搜索寄存器,查看字段解釋。