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.

CCS/LP-MSP430FR2476: ADC stuck on a fixed value and just randomly reads the A1 pin.

Part Number: LP-MSP430FR2476
Other Parts Discussed in Thread: TMP235

Tool/software: Code Composer Studio

Hi,

I'm trying to do a single channel conversion with my MSP430 and send the values to my PC and plot it with MatLab. I use a potmeter connected to 3v+, P1.1(A1), GND to test my code.

My problem is that the ADC result is stuck at a fixed value (216) and but sometimes it starts to actually read something that resembles the change of the potmeter. I guess I set the A1 incorrectly and I'm reading wrong the wrong pin but I couldn't find anything in the datasheet or in the code that could be wrong.

#include <msp430.h>

unsigned int ADC_Result;

void Init_GPIO();
void Software_Trim();                       // Software Trim to get the best DCOFTRIM value
#define MCLK_FREQ_MHZ 8                     // MCLK = 8MHz

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

  // Configure GPIO
  Init_GPIO();
  // Configure GPIO

  TA0CCTL0 |= CCIE;                             // TACCR0 interrupt enabled
  TA0CCR0 = 50000;
  TA0CTL |= TASSEL__SMCLK | MC__CONTINUOUS;     // SMCLK, continuous mode

  PM5CTL0 &= ~LOCKLPM5;                    // Disable the GPIO power-on default high-impedance mode
                                           // to activate 1previously configured port settings

  __bis_SR_register(SCG0);                 // disable FLL
  CSCTL3 |= SELREF__REFOCLK;               // Set REFO as FLL reference source
  CSCTL1 = DCOFTRIMEN_1 | DCOFTRIM0 | DCOFTRIM1 | DCORSEL_3;// DCOFTRIM=3, DCO Range = 8MHz
  CSCTL2 = FLLD_0 + 243;                  // DCODIV = 8MHz
  __delay_cycles(3);
  __bic_SR_register(SCG0);                // enable FLL
  Software_Trim();                        // Software Trim to get the best DCOFTRIM value

  CSCTL4 = SELMS__DCOCLKDIV | SELA__REFOCLK; // set default REFO(~32768Hz) as ACLK source, ACLK = 32768Hz
                                           // default DCODIV as MCLK and SMCLK source

  // Configure UART pins
  P1SEL0 |= BIT4 | BIT5;                    // set 2-UART pin as second function
  // Configure ADC A1 pin
  P1SEL0 |= BIT1;
  P1SEL1 |= BIT1;
  // Configure UART
  UCA0CTLW0 |= UCSWRST;
  UCA0CTLW0 |= UCSSEL__SMCLK;

  // Baud Rate calculation
  // 8000000/(16*9600) = 52.083
  // Fractional portion = 0.083
  // User's Guide Table 17-4: UCBRSx = 0x49
  // UCBRFx = int ( (52.083-52)*16) = 1
  UCA0BR0 = 52;                             // 8000000/16/9600
  UCA0BR1 = 0x00;
  UCA0MCTLW = 0x4900 | UCOS16 | UCBRF_1;

  UCA0CTLW0 &= ~UCSWRST;                    // Initialize eUSCI
  UCA0IE |= UCRXIE;                         // Enable USCI_A0 RX interrupt

  // Configure ADC12
  ADCCTL0 |= ADCSHT_2 | ADCON;                             // ADCON, S&H=16 ADC clks
  ADCCTL1 |= ADCSHP;                                       // ADCCLK = MODOSC; sampling timer
  ADCCTL2 &= ~ADCRES;                                      // clear ADCRES in ADCCTL
  ADCCTL2 |= ADCRES_2;                                     // 12-bit conversion results
  ADCMCTL0 |= ADCINCH_1;                                   // A1 ADC input select; Vref=DVCC
  ADCIE |= ADCIE0;                                         // Enable ADC conv complete interrupt

  while(1)
  {
      ADCCTL0 |= ADCENC | ADCSC;                           // Sampling and conversion start
      __bis_SR_register(LPM0_bits | GIE);                  // LPM0, ADC_ISR will force exit
      __no_operation();                                    // For debug only
      if (ADC_Result < 0x7FF)
          P1OUT &= ~BIT0;                                  // Clear P1.0 LED off
      else
          P1OUT |= BIT0;                                   // Set P1.0 LED on
      __delay_cycles(5000);
  }
}

// Timer A0 interrupt service routine
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = TIMER0_A0_VECTOR
__interrupt void Timer_A (void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(TIMER0_A0_VECTOR))) Timer_A (void)
#else
#error Compiler not supported!
#endif
{

    UCA0TXBUF=ADC_Result;
    __delay_cycles(5000);
    UCA0TXBUF=ADC_Result<<8;
    TA0CCR0 = 50000;                             // Add Offset to TACCR0
}
void Software_Trim()
{
    unsigned int oldDcoTap = 0xffff;
    unsigned int newDcoTap = 0xffff;
    unsigned int newDcoDelta = 0xffff;
    unsigned int bestDcoDelta = 0xffff;
    unsigned int csCtl0Copy = 0;
    unsigned int csCtl1Copy = 0;
    unsigned int csCtl0Read = 0;
    unsigned int csCtl1Read = 0;
    unsigned int dcoFreqTrim = 3;
    unsigned char endLoop = 0;

    do
    {
        CSCTL0 = 0x100;                         // DCO Tap = 256
        do
        {
            CSCTL7 &= ~DCOFFG;                  // Clear DCO fault flag
        }while (CSCTL7 & DCOFFG);               // Test DCO fault flag

        __delay_cycles((unsigned int)3000 * MCLK_FREQ_MHZ);// Wait FLL lock status (FLLUNLOCK) to be stable
                                                           // Suggest to wait 24 cycles of divided FLL reference clock
        while((CSCTL7 & (FLLUNLOCK0 | FLLUNLOCK1)) && ((CSCTL7 & DCOFFG) == 0));

        csCtl0Read = CSCTL0;                   // Read CSCTL0
        csCtl1Read = CSCTL1;                   // Read CSCTL1

        oldDcoTap = newDcoTap;                 // Record DCOTAP value of last time
        newDcoTap = csCtl0Read & 0x01ff;       // Get DCOTAP value of this time
        dcoFreqTrim = (csCtl1Read & 0x0070)>>4;// Get DCOFTRIM value

        if(newDcoTap < 256)                    // DCOTAP < 256
        {
            newDcoDelta = 256 - newDcoTap;     // Delta value between DCPTAP and 256
            if((oldDcoTap != 0xffff) && (oldDcoTap >= 256)) // DCOTAP cross 256
                endLoop = 1;                   // Stop while loop
            else
            {
                dcoFreqTrim--;
                CSCTL1 = (csCtl1Read & (~DCOFTRIM)) | (dcoFreqTrim<<4);
            }
        }
        else                                   // DCOTAP >= 256
        {
            newDcoDelta = newDcoTap - 256;     // Delta value between DCPTAP and 256
            if(oldDcoTap < 256)                // DCOTAP cross 256
                endLoop = 1;                   // Stop while loop
            else
            {
                dcoFreqTrim++;
                CSCTL1 = (csCtl1Read & (~DCOFTRIM)) | (dcoFreqTrim<<4);
            }
        }

        if(newDcoDelta < bestDcoDelta)         // Record DCOTAP closest to 256
        {
            csCtl0Copy = csCtl0Read;
            csCtl1Copy = csCtl1Read;
            bestDcoDelta = newDcoDelta;
        }

    }while(endLoop == 0);                      // Poll until endLoop == 1

    CSCTL0 = csCtl0Copy;                       // Reload locked DCOTAP
    CSCTL1 = csCtl1Copy;                       // Reload locked DCOFTRIM
    while(CSCTL7 & (FLLUNLOCK0 | FLLUNLOCK1)); // Poll until FLL is locked
}



void Init_GPIO()
{
    P1DIR = 0xFF; P2DIR = 0xFF;
    P1REN = 0xFF; P2REN = 0xFF;
    P1OUT = 0x00; P2OUT = 0x00;
}

// ADC interrupt service routine
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=ADC_VECTOR
__interrupt void ADC_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(ADC_VECTOR))) ADC_ISR (void)
#else
#error Compiler not supported!
#endif
{
    switch(__even_in_range(ADCIV,ADCIV_ADCIFG))
    {
        case ADCIV_NONE:
            break;
        case ADCIV_ADCOVIFG:
            break;
        case ADCIV_ADCTOVIFG:
            break;
        case ADCIV_ADCHIIFG:
            break;
        case ADCIV_ADCLOIFG:
            break;
        case ADCIV_ADCINIFG:
            break;
        case ADCIV_ADCIFG:
            ADC_Result = ADCMEM0;
            __bic_SR_register_on_exit(LPM0_bits);            // Clear CPUOFF bit from LPM0
            break;
        default:
            break;
    }
}

MatLab code:

clear all
clc;
 if ~isempty(instrfind)
 fclose(instrfind);
 delete(instrfind);
 end
s = serial('COM5','BaudRate',9600,'TimeOut',10,'Terminator','LF');
fopen(s);
n=1:1000;
y=1:1000;
shg
 for i=1:1000
 received=fread(s,2)
 y(i)=received(1)+received(2)*256;
  ylim([0 1200])
 plot(y(:),'g'); drawnow
 ylim([0 1000])
 end
fclose(s);
shg

  • Is the "TS_EN" (J9) jumper installed? That powers the TMP235 Temperature Sensor, which feeds P1.1 [Ref LP UG (SLAU802) Fig 19].

    I expect if you remove that jumper the TMP235 won't interfere. Alternatively, try using (e.g.) P1.7 (A7), which doesn't appear to be connected to anything else.

**Attention** This is a public forum