一、ADC10組成
ADC10模塊是MSP430 MCU內部的一個高性能、10位的模數轉換器,包含了SAR(Successive-Approximation-Register) core、采樣選擇控制、基准源發生器和DTC(Data Transfer Controller)。DTC功能允許采樣結果直接內部存儲,而不需要CPU的干預。
ADC10的框圖和主要寄存器的含義,如下圖所示。雖然ADC10牽扯的寄存器配置很多,但實際使用起來並不復雜。

二、相關寄存器
主要寄存器及功能有:
ADC10AEx:模擬輸入使能,用於使能某個管腳的模擬輸入功能
ADC10MEM:保存AD轉換的結果
ADC10CTL0:
- ADC10ON:開啟/關閉ADC10
- ENC:Enable conversion。幾乎所有的ADC10設置都要在ENC=0時進行。
- ADC10SC:Start conversion。開始轉換后會自動清零。
- SREFx:選擇正負基准源
- REFOUT、REFBURST、REF2_5V、REFON:選擇內部基准源及其工作方式
- ADC10SHTx:選擇采集和保持的時鍾周期數目
- ADC10SR:選擇reference buffer drive capability,影響最大采集速率
- ADC10IE、ADC10IFG:中斷使能和中斷標志位
- MSC:多次采集轉換設置,只用於序列(sequence)或反復(repeated)模式采樣。
ADC10CTL1:
- INCHx:輸入通道選擇,可選擇外部管腳、基准源、內部溫度傳感器等。
- SHSx:選擇采樣信號由誰觸發,默認是ADC10SC位,也可以是TimerA.OUTx。
- ADC10DF:轉換數據格式,直接二進制或者二補碼。
- ADC10SSELx、ADC10DIVx:選擇ADC10的時鍾,分頻比。時鍾默認采用ADC10內部的專門時鍾ADC10OSC,頻率約在5MHz左右。
- CONSEQx:選擇模式,有單通道單次(默認)、多通道單次、單通道重復、多通道重復四種。
- ADC10BUSY:標志ADC10是否采樣、轉換完成。
如果使用到DTC的功能,還需要操作ADC10DTC0、ADC10DTC1、ADC10SA寄存器,具體可查看MSP430x2xx Family User's Guide。
三、代碼示例
利用ADC10,每2秒讀取一次A6(P1.6)通道上的電壓,通過串口打印顯示。
1 // voltage meter 2015.10.1 2 // for MSPG2 launchpad, VCC = 3.6V; and if Vcc changes, 3 // ref_vcc should be modified. 4 5 #include "io430.h" 6 7 #define A6 BIT6 // ADC input pin P1.6 8 #define RXD BIT1 //P1.1 9 #define TXD BIT2 //P1.2 10 11 #define IDLE 0 12 #define BUSY 1 13 14 // function definitions 15 void initADC10(void); 16 void initTA0(void); 17 18 void sendByte(unsigned char); 19 void printf(char *, ...); 20 void initUART(void); 21 22 // global variables 23 float volts = 0.0; // unit: mV 24 float ref_vcc = 3600.0; 25 char i = 0; 26 char status = IDLE; 27 28 void main( void ) 29 { 30 // Stop watchdog timer to prevent time out reset 31 WDTCTL = WDTPW + WDTHOLD; 32 33 // DCO setup 34 BCSCTL1 = CALBC1_1MHZ; 35 DCOCTL = CALDCO_1MHZ; 36 37 // ADC10 setup 38 initADC10(); 39 40 // UART setup 41 initUART(); 42 43 // Timer0 setup 44 initTA0(); 45 46 __enable_interrupt(); 47 48 LPM0; 49 50 while(1) 51 { 52 switch(status) 53 { 54 case IDLE: 55 break; 56 case BUSY: 57 ADC10CTL0 |= ADC10SC; // start a new conversion 58 while ((ADC10CTL1 & ADC10BUSY) == 0x01); // wait for conversion to end 59 volts = ADC10MEM * ref_vcc /1023.0; 60 printf("Voltage: %i mV\r\n", (int)volts); 61 status = IDLE; 62 break; 63 } 64 LPM0; 65 66 } 67 } 68 69 void initADC10(void) 70 { 71 // Use Vcc(3.6V)/GND for Refs, 16 x ADC10CLKs, reference buffer on, turn on ADC 72 ADC10CTL0 = SREF_0 + ADC10SHT_2 + ADC10SR + ADC10ON; 73 74 // A6 input, use ADC10CLK div 1, single channel mode 75 ADC10CTL1 = INCH_6 + SHS_0 + ADC10SSEL_0 + ADC10DIV_0 + CONSEQ_0; 76 77 // ADC input on P1.6 78 ADC10AE0 = A6; 79 80 // Enable conversions 81 ADC10CTL0 |= ENC; 82 } 83 84 void initTA0(void) 85 { 86 TA0CCR0 = 62550 - 1; 87 TA0CCTL0 = CCIE; // enable compare interrupt 88 TA0CTL = TASSEL_2 + ID_3 + MC_1 + TACLR; 89 // input clock: SMCLK/8 -> 125kHz; Up to CCR0 mode 90 // timer overflow freq: 125k/(TA0CCR0+1) -> 2Hz -> 500ms 91 // clear and start the timer, up mode 92 } 93 94 void initUART(void) { 95 //config P1.1 RXD, P1.2 TXD 96 P1SEL |= TXD + RXD; 97 P1SEL2 |= TXD + RXD; 98 99 //reset UCA0, to be configured 100 UCA0CTL1 = UCSWRST; 101 //config 102 UCA0CTL1 |= UCSSEL_2; //SMCLK 103 UCA0BR0 = 104; 104 UCA0BR1 = 0;//1MHz baut rate = 9600 105 UCA0MCTL = UCBRS0; // Modulation UCBRSx = 1 106 //make UCA0 out of reset 107 UCA0CTL1 &= ~UCSWRST; 108 } 109 110 void sendByte(unsigned char byte ) 111 { 112 while (!(IFG2&UCA0TXIFG)); // USCI_A0 TX buffer ready? 113 UCA0TXBUF = byte; // TX -> RXed character 114 } 115 116 //interrupt service routines 117 #pragma vector = TIMER0_A0_VECTOR 118 __interrupt void CCR0_ISR(void) 119 { 120 if(++i == 4) // interval: 1/2 * 4 = 2s, freq: 0.5Hz 121 { 122 // automatic flag clearing 123 i = 0; 124 status = BUSY; 125 LPM0_EXIT; 126 } 127 }
