This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

ADC code in MASP430G2553

Other Parts Discussed in Thread: MSP430G2553

Dear all

I am posting an ADC coding here. 

#include <msp430g2553.h>

volatile int value=0;
unsigned int sampling;

int main(void)
{

WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
InitializeClocks(); // Configure system clocks
ConfigureADC();
__enable_interrupt(); // Enable interrupts.

while(1)
{
ADC10CTL0 &= ~ENC;
while((ADC10CTL1 & ADC10BUSY) == ADC10BUSY);
sampling = 1;

ADC10CTL0 |= ENC + ADC10SC;// Sampling and conversion start

value=ADC10MEM;

ADC10CTL0 &= ~(ADC10IFG | ADC10ON | REFON);

while(sampling>0); // wait until the sampling sequence is complete


__delay_cycles(100);
}

}
void ConfigureADC(void)
{
ADC10CTL0 = SREF_1 + ADC10SHT_0 + REFON + ADC10ON + ADC10IE;
ADC10CTL1 = INCH_4 + ADC10DIV_0 + ADC10SSEL_0 + CONSEQ_0;// channel 5, clock divider 2, ADC10CLK, Conversion sequence mode select single channel single conversion
ADC10AE0 |= BIT4;
ADC10CTL0 &= ~ENC+ADC10SC; // Disable conversion
__delay_cycles(40);

}
void InitializeClocks(void)

{

BCSCTL1 = CALBC1_16MHZ; // Set range


DCOCTL = CALDCO_16MHZ;

}
// ADC10 interrupt service routine
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR (void)
{
sampling=0;
__bic_SR_register_on_exit(CPUOFF); // Return to active mode }
__delay_cycles(40);

}

In this if I give  1.3 as Vin. It does not give the expected exact output. integer 887(886.6 is the exact value). Instead of this it gave 868 integer value at ADC10MEM register.  Please help in this context to expain the problem with this code. How could I get the exact value?

  • Without having a look at your complete code, this portion already has an issue:

    while( 1 )
    {
      ADC10CTL0 &= ~ENC;
      while( (ADC10CTL1 & ADC10BUSY) == ADC10BUSY );
      sampling = 1;
    
      ADC10CTL0 |= ENC + ADC10SC;// Sampling and conversion start
    
      value = ADC10MEM; // NOTE: YOU CANNOT READ THE RESULT IMMEDIATELY AFTER STARTING THE CONVERSION, SO WAIT FOR COMPLETION FIRST
    
      ADC10CTL0 &= ~(ADC10IFG | ADC10ON | REFON);
    
      while( sampling > 0 ); // wait until the sampling sequence is complete
    
      __delay_cycles( 100 );
    }

    Dennis

  • i modified the code as shown below. but still I am not getting data in value. pls help me here.

    while(1)
    {
    ADC10CTL0 &= ~ENC;

    while((ADC10CTL1 & ADC10BUSY) == ADC10BUSY);

    sampling = 1;

    ADC10CTL0 |= ENC + ADC10SC;// Sampling and conversion start

    while(!(ADC10CTL0 & ADC10IFG)); // wait till the block conversion is complete

    ADC10CTL0 &= ~(ADC10IFG | ADC10ON | REFON);

    ADC10CTL0 &= ~ENC;


    while(sampling>0); // wait until the sampling sequence is complete


    __delay_cycles(100);
    }
    value=ADC10MEM;


    }

  • Ammassk,

    have a look at the code examples for that processor - they can be found here and you can modify them according to your requirements. Your code has some questionable lines...

    while( 1 )
    {
      ADC10CTL0 &= ~ENC;
    
      while( (ADC10CTL1 & ADC10BUSY) == ADC10BUSY );
    
      sampling = 1;
    
      ADC10CTL0 |= ENC + ADC10SC;// Sampling and conversion start
    
      while( !(ADC10CTL0 & ADC10IFG) ); // wait till the block conversion is complete
    
      ADC10CTL0 &= ~(ADC10IFG | ADC10ON | REFON);
    
      ADC10CTL0 &= ~ENC;
    
      while( sampling > 0 ); // wait until the sampling sequence is complete
    
      __delay_cycles(100);
    }

    For example this line:

    ADC10CTL0 &= ~(ADC10IFG | ADC10ON | REFON);

    Why do you turn everything off here - you do not turn it on again in the next loop cycle. Look at the following example code from the link I provided you:

    • msp430g2x33_adc10_01.c                     ADC10, Sample A0, Set P1.0 if A0 > 0.5*AVcc
    #include <msp430.h>
    
    int main(void)
    {
      WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
      ADC10CTL0 = ADC10SHT_2 + ADC10ON + ADC10IE; // ADC10ON, interrupt enabled
      ADC10CTL1 = INCH_1;                       // input A1
      ADC10AE0 |= 0x02;                         // PA.1 ADC option select
      P1DIR |= 0x01;                            // Set P1.0 to output direction
    
      for (;;)
      {
        ADC10CTL0 |= ENC + ADC10SC;             // Sampling and conversion start
        __bis_SR_register(CPUOFF + GIE);        // LPM0, ADC10_ISR will force exit
        if (ADC10MEM < 0x1FF)
          P1OUT &= ~0x01;                       // Clear P1.0 LED off
        else
          P1OUT |= 0x01;                        // Set P1.0 LED on
      }
    }
    
    // ADC10 interrupt service routine
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=ADC10_VECTOR
    __interrupt void ADC10_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(ADC10_VECTOR))) ADC10_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
      __bic_SR_register_on_exit(CPUOFF);        // Clear CPUOFF bit from 0(SR)
    }
    

    You can easily change it to read your pin and then do something else with the result instead of this comparative function. But look at the other ADC10 examples as well.

    Dennis

  • When connecting a high impedance source to the ADC, by means of a resistor divider (attenuator) or a series resistor, you might need to increase the sampling time of the ADC.

    For a precise ADC result you need to calibrate the ADC result with the calibration values for Vref and ADC, see User’s Guide for instructions.
  • Dear all

    I modified the code as shown below. As I am new to msp430 I couldnt find out the problem with this code. Here also I am not getting output. In my code, I tried to give my real time pulse to channel 4 and tried to digital conversion continously. Please help on this

    #include <msp430g2553.h>
    //#define DIV_SMCLK_32768 (WDT_MDLY_32) // SMCLK/32768
    volatile int value=0;
    unsigned int sampling;
    int timecnt;
    int main(void)
    {

    WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
    if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF)
    while(1);
    DCOCTL = CALDCO_1MHZ; // Set uC to run at approximately 1 Mhz
    BCSCTL1 = CALBC1_1MHZ;
    ADC10CTL1 = ADC10DIV_3 + ADC10SSEL_3+ INCH_4 + SHS_1 + CONSEQ_2;
    ADC10CTL0 = SREF_1 + ADC10SHT_3 + ADC10IE + REFON + ADC10ON;
    ADC10AE0 |= BIT4;
    __enable_interrupt(); // Enable interrupts.
    TACCR0 = 30; // Delay to allow Ref to settle
    TACCTL0 |= CCIE;
    TACTL = TASSEL_2 | MC_1; // TACLK = SMCLK, Up mode
    LPM0; // Wait for delay.
    // TACCTL0 &= ~CCIE; // Disable timer Interrupt
    //__disable_interrupt();
    while(1)
    {
    ADC10CTL0 |= ENC+ADC10SC;
    TACTL = TASSEL_2 + MC_2; // SMCLK, cont-mode
    while (!(ADC10IFG & ADC10CTL0)); // First conversion?
    value=ADC10MEM;
    __bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupt
    }
    }

    // Timer A0 interrupt service routine
    #pragma vector=TIMER0_A0_VECTOR
    __interrupt void Timer_A (void)
    {
    timecnt++; // Keep track of time for main while loop.

    if ((timecnt%500) == 0)
    {
    ADC10CTL0 |= ENC + ADC10SC; // Enable Sampling and start conversion.
    }
    }



    //ADC10 interrupt Service Routine
    #pragma vector=ADC10_VECTOR
    __interrupt void ADC10_ISR (void)
    {
    ADC10CTL0 &= ~ADC10IFG; // clear interrupt flag
    __bic_SR_register_on_exit(CPUOFF); // Return to active mode




    }
  • Ammask,

    I think you're mixing things up a little bit. First you wanted to measure a single channel once (CONSEQ_0), now you want to (I guess) read an input channel in fixed timer intervals (timer triggers conversion), but you also have CONSEQ_2 enabled for repeated single channel measurement. Please take the time and read the ADC chapter (22) in the users's guide. Furthermore start with the code examples I have pointed you to before.

    And maybe you describe what you plan to do.

    Dennis

  • I am trying to convert analog pulse from forefinger to digital value.How should I proceed to get digital data?
  • As I said, first read the chapter in the user's guide - it isn't that long and it gives you a basic understanding of the ADC10 module and it's registers. Then start working with the code examples for the ADC10. They cover different applications that can easily be changed to your own requirements.

**Attention** This is a public forum