Analogue to digital conversion

The first example, taken verbatim from here,  shows you how to set up a basic single ADC. In this example if the converted value is greater than 511 then the Green LED is on and if below 511 then the red LED is on.


#include <msp430.h>

#define LED0 BIT0
#define LED1 BIT6

unsigned int value=0;

void ConfigureAdc(void);

/*
 * main.c
 */
void main(void) {
 WDTCTL = WDTPW + WDTHOLD; // Stop WDT
 BCSCTL1 = CALBC1_1MHZ; // Set range
 DCOCTL = CALDCO_1MHZ;
 BCSCTL2 &= ~(DIVS_3); // SMCLK = DCO = 1MHz
 P1DIR |= LED0 + LED1;
 P1SEL |= BIT5; //ADC Input pin P1.5
 P1OUT &= ~(LED0 + LED1);

ConfigureAdc();
 __enable_interrupt(); // Enable interrupts.

while(1)
 {
 __delay_cycles(1000); // Wait for ADC Ref to settle
 ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start
 __bis_SR_register(CPUOFF + GIE); // LPM0 with interrupts enabled
 value = ADC10MEM;
 if (value>511)
 {
 P1OUT &= ~(LED0 + LED1);
 P1OUT |= LED0;
 }
 else
 {
 P1OUT &= ~(LED0 + LED1);
 P1OUT |= LED1;
 }
 }
}
// ADC10 interrupt service routine
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR (void)
{
 __bic_SR_register_on_exit(CPUOFF); // Return to active mode
}

void ConfigureAdc(void)
{
 /* Configure ADC Channel */
 ADC10CTL1 = INCH_5 + ADC10DIV_3 ; // Channel 5, ADC10CLK/4
 ADC10CTL0 = SREF_0 + ADC10SHT_3 + ADC10ON + ADC10IE; //Vcc & Vss as reference
 ADC10AE0 |= BIT5; //P1.5 ADC option
}

The second example shows how to transmit the measured value back to a terminal on the computer using the hardware UART that is on the MSP430G2553


/*
 * This code shows how to measure a voltage that is attached to P1.5 using the ADC and then
 * return this value to a terminal program on the pc using the hardware UART. Each data
 * acquisition is started by pressing switch S2 (Remember to configure
 * the jumpers on J3 for hardware UART operation)
 *
 * Benn Thomsen, 2013
 */

#include <msp430.h>

unsigned int value=0;

void main(void) {
 WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer

/* Use Factory stored presets to calibrate the internal oscillator */
 BCSCTL1 = CALBC1_1MHZ; // Set DCO
 DCOCTL = CALDCO_1MHZ;

P1DIR |= BIT0; // Set the LEDs on P1.0 as an output
 P1OUT &= ~BIT0; // Turn it off

/* Configure Hardware UART */
 P1SEL = BIT1 + BIT2 ; // P1.1 = RXD, P1.2=TXD
 P1SEL2 = BIT1 + BIT2 ; // P1.1 = RXD, P1.2=TXD
 UCA0CTL1 |= UCSSEL_2; // SMCLK
 UCA0BR0 = 104; // Set Baud rate (1MHz CPU clock)/(9600 baud) (lower byte)
 UCA0BR1 = 0; // Set Baud rate to (1MHz CPU clock)/(9600 baud) (upper byte)
 UCA0MCTL = UCBRS0; // Modulation UCBRSx = 1
 UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**

/* Configure ADC Channel */
 ADC10CTL1 = INCH_5 + ADC10DIV_3 ; // Channel 5, ADC10CLK/4
 ADC10CTL0 = SREF_0 + ADC10SHT_3 + ADC10ON + ADC10IE; //Vcc & Vss as reference
 ADC10AE0 |= BIT5; //P1.5 ADC option

/* Configure the switch S2 on P1.3 */
 P1DIR &= ~BIT3; // Set button pin as an input pin
 P1OUT |= BIT3; // Set pull up resistor on for button
 P1REN |= BIT3; // Enable pull up resistor for button to keep pin high until pressed
 P1IES |= BIT3; // Enable Interrupt to trigger on the falling edge (high (unpressed) to low (pressed) transition)
 P1IFG &= ~BIT3; // Clear the interrupt flag for the button
 P1IE |= BIT3; // Enable interrupts on port 1 for the button

__enable_interrupt(); // Enable interrupts.

__bis_SR_register(LPM0_bits | GIE);

}

/* Port 1 interrupt to service the button press */
#pragma vector=PORT1_VECTOR
__interrupt void PORT1_ISR(void)
{
 P1IFG &= ~BIT3; // Clear the interrupt flag for the button
 P1IE &= ~BIT3; // Disable Button interrupt
 WDTCTL = WDT_MDLY_32; // Start and set watchdog timer (WDT) to trigger every 250ms
 IFG1 &= ~WDTIFG; // Clear the interrupt flag for the WDT
 IE1 |= WDTIE; // enable WDT interrupt

P1OUT |= BIT0; // Turn on LED1 to indicate start of conversion
 ADC10CTL0 |= ENC + ADC10SC; // ADC Sampling and conversion start
}

// WDT Interrupt Service Routine used to de-bounce button press
#pragma vector=WDT_VECTOR
__interrupt void WDT_ISR(void)
{
 IE1 &= ~WDTIE; // disable Watchdog timer (WDT) interrupt
 IFG1 &= ~WDTIFG; // clear WDT interrupt flag
 WDTCTL = WDTPW + WDTHOLD; // put WDT back in hold state
 P1IE |= BIT3; // Reenable interrupts for the button
}

// ADC10 interrupt service routine
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR (void)
{
 value = ADC10MEM; // read ADC value (note this is a 10bit value stored in a 16 bit register)

/* Transmit value read by ADC using the UART */
 while (!(IFG2&UCA0TXIFG)); // Wait until TX buffer ready?
 UCA0TXBUF = value >> 8; // Send MSB first
 while (!(IFG2&UCA0TXIFG)); // Wait until TX buffer ready?
 UCA0TXBUF = (value & 0x00FF); // Send LSB

P1OUT &= ~BIT0; // Turn off LED1 to indicate transmission complete
}

Advertisements

2 thoughts on “Analogue to digital conversion

  1. great job,finally i found something that is going to be easy to understand
    I have also a question how i am going to see pot values in my terminal
    just by using the last // ADC10 interrupt service routine of the second program to the first

    thank you…

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s