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.

Full Scale Value

Other Parts Discussed in Thread: MSP430F5438A

Hi,

I tried lots of many settings but the MSP430F5438A's ADC does not give me the correct full scale value. I checked the Reference settings so many times but I was unable to find anything wrong. It is giving me half of the full scale value.

 

So instead of giving  me ( 2^12 )  x   ( 3.2 / 2.5) = 5242 decimal , its giving me 2621 decimal. Any thoughts!  jessica

 

#include <msp430.h>
#include <math.h>
#include <intrinsics.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>

void Port_Init();
void adc_init(void);
void adc_start_Read(void);
void acc_read_with_offset();
void UART_init(void);
void UART(int,int,int);

volatile int SavedADC12MEM0, SavedADC12MEM1, SavedADC12MEM2;
unsigned int adc_index = 0;

int main(void)
{
WDTCTL = WDTPW+WDTHOLD;
Port_Init();
adc_init();
UART_init();
while (1)
{
adc_start_Read();
}
}

void Port_Init(void)
{
P3SEL = 0x30; // P3.4,5 = USCI_A0 TXD/RXD
P6SEL |= 0xFF;
// P6DIR |= 0x10;
P1DIR |= 0x01;
P11DIR |= 0x07; // ACLK, MCLK, SMCLK set out to pins
P11SEL |= 0x07; // P11.0,1,2 for debugging purposes.
P1DIR |= 0x01;
P7DIR |= 0x00;
P7SEL |= 0xF0;

}

void adc_init(void)
{

REFCTL0 &= ~REFVSEL_3; //Page 693 of data sheet
REFCTL0 |= REFVSEL_3 + REFON; // Configure internal 2.5V reference
__delay_cycles(2100); // delay for reference to settle
ADC12CTL0 &= ~ADC12ENC; // Ensure ENC is clear
ADC12CTL0 |= ADC12ON | ADC12SHT0_6 | ADC12MSC ; //| ADC12REFON | ADC12REF2_5V;
ADC12CTL0 |= ADC12REF2_5V;
ADC12MCTL0 = ADC12SREF_7;// | ADC12EOS;
ADC12CTL1 |= ADC12SHP |ADC12SSEL_3 | ADC12CONSEQ_1 | ADC12DIV_1;
ADC12MCTL0 = ADC12INCH_4;
ADC12MCTL1 = ADC12INCH_13;// | ADC12EOS;
ADC12MCTL2 = ADC12INCH_14 | ADC12EOS;
ADC12CTL2 = ADC12RES_2;
// ADC12MCTL1 = ADC12SREF_1 | ADC12EOS;
__delay_cycles(1900);

}

void adc_start_Read(void)
{
for(;;)
{
ADC12CTL0 |= ADC12ENC | ADC12SC;
while ((ADC12BUSY & ADC12CTL1)!=0)
{
P1OUT |= 0x01;
ADC12CTL0 &= ~ADC12ENC;
SavedADC12MEM0 = ADC12MEM0;
SavedADC12MEM1 = ADC12MEM1;
SavedADC12MEM2 = ADC12MEM2;
}
P1OUT &= ~0x01;
UART_SEND (SavedADC12MEM0, SavedADC12MEM1, SavedADC12MEM2);
}
}

 

 

 

  • the input voltage much not be greater than reference voltage i guess.
  • and if you want to convert 3.2 volts using ADC.the use AVCC as reference voltage.which will be around 3 to 3.6v
  • The input voltage can be as high as the supply voltage, regardless of the reference voltage. But you will get the full-scale value for everything higher than the reference voltage. At least you should...in this specific case I couldn't see the reason at first sight. First thought about wrong ADC12DF or ADC12RES setting, but this seems to be right.


    I think the goal is not to measure 3.2 volts - it's just the wrong full-scale value. And Avcc isn't good as reference voltage as it is not precise enough in most cases. Better scale your input-signal down to the range of the reference voltage.

    Dennis

  • Jessica, why do you open two threads with the same content:

    http://e2e.ti.com/support/microcontrollers/msp430/f/166/t/393901

    The only difference between them are some settings concerning the reference voltage for example. Of course you cannot see 5242 as a result from a 12 bit ADC, you can virtually expect it...

    Anyway - with the different settings - where does your input signal come from? Is it capable of driving the ADCs input?

  • The source is the power supply that is also powering up the MSP430F5438A. I have a potentiometer attached to the port 6.4. I applied 2.5v too but I do not get the full scale value. 

    jess

  • I suspect your input is not settled prior to the conversion. Try converting just one channel without any switching and see what you get.
  • Maybe I'm wrong, but your init-code could be the reason.

    You are sampling A4 on P6.4? That is ADC12INCH_4.

    And you want to use the internal reference of 2.5V? That would be ADC12SREF_1.

    Your code:

    void adc_init(void)
    {
      REFCTL0 &= ~REFVSEL_3; //Page 693 of data sheet
      REFCTL0 |= REFVSEL_3 + REFON; // Configure internal 2.5V reference
      __delay_cycles(2100); // delay for reference to settle
      ADC12CTL0 &= ~ADC12ENC; // Ensure ENC is clear
      ADC12CTL0 |= ADC12ON | ADC12SHT0_6 | ADC12MSC ; //| ADC12REFON | ADC12REF2_5V;
      ADC12CTL0 |= ADC12REF2_5V;
      ADC12MCTL0 = ADC12SREF_7;// | ADC12EOS;
      ADC12CTL1 |= ADC12SHP |ADC12SSEL_3 | ADC12CONSEQ_1 | ADC12DIV_1;
      ADC12MCTL0 = ADC12INCH_4;
      ADC12MCTL1 = ADC12INCH_13;// | ADC12EOS;
      ADC12MCTL2 = ADC12INCH_14 | ADC12EOS;
      ADC12CTL2 = ADC12RES_2;
      // ADC12MCTL1 = ADC12SREF_1 | ADC12EOS;
      __delay_cycles(1900);
    }

    I'm only talking about A4 on P6.4 now - you are setting

    ADC12MCTL0 = ADC12SREF_7;

    which is VeREF+ and VREF-/VeREF-, but I think you want to use the internal reference.

    Then you are doing the following:

    ADC12MCTL0 = ADC12INCH_4;

    You want to set A4 to MCTL0, but with this line you are deleting all other settings in ADC12MCTL0 - your reference for example is now ADC12SREF_0. You have to

    ADC12MCTL0 |= ADC12INCH_4;

    your input channel or write both of them in one instruction

    ADC12MCTL0 = (ADC12SREF_1 | ADC12INCH_4);

    Give it a try.

    Dennis

  • Hi,

    I made the changes that you recommended but no luck so far. I am still not getting the full scale value. jess :(

    #include <msp430.h>
    #include <math.h>
    #include <intrinsics.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <stdint.h>

    void Port_Init();
    void adc_init(void);
    void adc_start_Read(void);
    void acc_read_with_offset();
    void UART_init(void);
    void UART(int,int,int);

    volatile int SavedADC12MEM0, SavedADC12MEM1, SavedADC12MEM2;
    unsigned int adc_index = 0;

    int main(void)
    {
    WDTCTL = WDTPW+WDTHOLD;
    Port_Init();
    adc_init();
    UART_init();
    while (1)
    {
    adc_start_Read();
    }
    }

    void Port_Init(void)
    {
    P3SEL = 0x30; // P3.4,5 = USCI_A0 TXD/RXD
    P6SEL |= 0xFF;
    // P6DIR |= 0x10;
    P1DIR |= 0x01;
    P11DIR |= 0x07; // ACLK, MCLK, SMCLK set out to pins
    P11SEL |= 0x07; // P11.0,1,2 for debugging purposes.
    P1DIR |= 0x01;
    P7DIR |= 0x00;

    P7SEL |= 0xF0;

    }

    void adc_init(void)
    {

    REFCTL0 &= ~REFVSEL_3; //Page 693 of data sheet
    REFCTL0 |= REFVSEL_3 | REFON; // Configure internal 2.5V reference
    __delay_cycles(2100); // delay for reference to settle

    ADC12CTL0 |= ADC12ON | ADC12SHT0_6 | ADC12MSC ; //| ADC12REFON | ADC12REF2_5V;
    ADC12CTL0 |= ADC12REF2_5V;
    ADC12MCTL0 = ADC12SREF_7;// | ADC12EOS;
    ADC12CTL2 |= ADC12RES_2;
    ADC12CTL1 |= ADC12SHP |ADC12SSEL_3 | ADC12CONSEQ_1 | ADC12DIV_1;
    // ADC12MCTL0 |= ADC12SREF_1 ;
    ADC12CTL0 &= ~ADC12ENC; // Ensure ENC is clear
    ADC12MCTL0 |= ADC12INCH_4;
    ADC12MCTL1 |= ADC12INCH_13;// | ADC12EOS;
    ADC12MCTL2 |= ADC12INCH_14 | ADC12EOS;

    // ADC12MCTL1 = ADC12SREF_1 | ADC12EOS;
    __delay_cycles(1900);

    }

    void adc_start_Read(void)
    {
    for(;;)
    {
    ADC12CTL0 |= ADC12ENC | ADC12SC;
    while ((ADC12BUSY & ADC12CTL1)!=0)
    {
    P1OUT |= 0x01;
    ADC12CTL0 &= ~ADC12ENC;
    SavedADC12MEM0 = ADC12MEM0;
    SavedADC12MEM1 = ADC12MEM1;
    SavedADC12MEM2 = ADC12MEM2;
    }
    P1OUT &= ~0x01;
    UART_SEND (SavedADC12MEM0, SavedADC12MEM1, SavedADC12MEM2);
    }
    }
  • For ADC12MCTL0, you're still selecting ADC12SREF_7, which takes the external reference from VeREF pin. Use ADC12SREF_1 to use the configured internal reference.
    Setting ASC12SREF2_5V in adc12XTL0 is void, as you're using the REF module to configure the reference. All reference-related controls in the ADC12 are inactive.
    You're using SMCLK as ADC12CLK and divide it by 2. So you're at the lower limit of the allowed ADC clock range, but this shouldn't be a problem, unless you change your clock settings from the default. It will, however, take some time until the DCO (and therefore SMCLK) reaches the 1MHz. Until then, the ADC might be operating on a too low frequency for reliable results.

    Hint: volatile variables are only needed if you are using them in main as well as inside an ISR. You don't have any ISR, so making them volatile decreases the compiler optimizing efficiency without need.

    hint: using the 'insert code' feature of the rich text editor makes code much more readable, with syntax highlighting and line numbering. (See Dennis' post above)

**Attention** This is a public forum