您的位置:首页 > 其它

MSP430G2553 模数转换器 ADC10

2015-10-01 12:37 344 查看

一、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)通道上的电压,通过串口打印显示。

// voltage meter 2015.10.1
// for MSPG2 launchpad, VCC = 3.6V; and if Vcc changes,
// ref_vcc should be modified.

#include "io430.h"

#define A6 BIT6 // ADC input pin P1.6
#define RXD BIT1 //P1.1
#define TXD BIT2 //P1.2

#define IDLE 0
#define BUSY 1

// function definitions
void initADC10(void);
void initTA0(void);

void sendByte(unsigned char);
void printf(char *, ...);
void initUART(void);

// global variables
float volts = 0.0; // unit: mV
float ref_vcc = 3600.0;
char i = 0;
char status = IDLE;

void main( void )
{
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;

// DCO setup
BCSCTL1 = CALBC1_1MHZ;
DCOCTL = CALDCO_1MHZ;

// ADC10 setup
initADC10();

// UART setup
initUART();

// Timer0 setup
initTA0();

__enable_interrupt();

LPM0;

while(1)
{
switch(status)
{
case IDLE:
break;
case BUSY:
ADC10CTL0 |= ADC10SC;   // start a new conversion
while ((ADC10CTL1 & ADC10BUSY) == 0x01);   // wait for conversion to end
volts = ADC10MEM * ref_vcc /1023.0;
printf("Voltage:  %i mV\r\n", (int)volts);
status = IDLE;
break;
}
LPM0;

}
}

void initADC10(void)
{
// Use Vcc(3.6V)/GND for Refs, 16 x ADC10CLKs, reference buffer on, turn on ADC
ADC10CTL0 = SREF_0 + ADC10SHT_2 + ADC10SR + ADC10ON;

// A6 input, use ADC10CLK div 1, single channel mode
ADC10CTL1 =  INCH_6 + SHS_0 + ADC10SSEL_0 + ADC10DIV_0 + CONSEQ_0;

// ADC input on P1.6
ADC10AE0 = A6;

// Enable conversions
ADC10CTL0 |= ENC;
}

void initTA0(void)
{
TA0CCR0 = 62550 - 1;
TA0CCTL0 = CCIE; // enable compare interrupt
TA0CTL = TASSEL_2 + ID_3 + MC_1 + TACLR;
// input clock: SMCLK/8 -> 125kHz; Up to CCR0 mode
// timer overflow freq: 125k/(TA0CCR0+1) -> 2Hz -> 500ms
// clear and start the timer, up mode
}

void initUART(void) {
//config P1.1 RXD, P1.2 TXD
P1SEL |= TXD + RXD;
P1SEL2 |= TXD + RXD;

//reset UCA0, to be configured
UCA0CTL1 = UCSWRST;
//config
UCA0CTL1 |= UCSSEL_2; //SMCLK
UCA0BR0 = 104;
UCA0BR1 = 0;//1MHz baut rate = 9600
UCA0MCTL = UCBRS0; // Modulation UCBRSx = 1
//make UCA0 out of reset
UCA0CTL1 &= ~UCSWRST;
}

void sendByte(unsigned char byte )
{
while (!(IFG2&UCA0TXIFG));            // USCI_A0 TX buffer ready?
UCA0TXBUF = byte;                // TX -> RXed character
}

//interrupt service routines
#pragma vector = TIMER0_A0_VECTOR
__interrupt void CCR0_ISR(void)
{
if(++i == 4) // interval: 1/2 * 4 = 2s, freq: 0.5Hz
{
// automatic flag clearing
i = 0;
status = BUSY;
LPM0_EXIT;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: