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.

  • Resolved

MSP430F5529: Timer A not triggering ADC12

Expert 4235 points

Replies: 2

Views: 676

Part Number: MSP430F5529

Team, I am currently attempting to use an MSP430F5529 to read in an analog value and populate it to an array. I have configured the MSP430 to start a sample conversion off of TimerA0, as shown in the datasheet, but am currently getting no response from the ADC. Please see my code below. Any advice on what I'm configuring incorrectly would be much appreciated

#include <msp430.h> 


static void setup_ADC();
void setup_TimerA0(void);
void setClocks();
void SetVcoreUp (unsigned int level);


#define   Num_of_Results   2000
volatile unsigned int results[Num_of_Results];          //stores 500 words, or at an optimal sampling of 100ksps of 1kHz sine,
                                                        //5 periods worth of data
unsigned char index = 0;



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


    setClocks();                                        //set ACLK to REF0 = 32.768KHz, MCLK and SMCLK to DCO = 20MHz
    setup_TimerA0();
    setup_ADC();



infinite_loop:
    {
               __bis_SR_register(GIE);      // LPM0, global interrupts enabled
               __no_operation();                        // For debugger
    }


    goto infinite_loop;
}


// Functions //


// Timer1 interrupt service routine
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=TIMER1_A0_VECTOR
__interrupt void TIMER1_A0_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(TIMER1_A0_VECTOR))) TIMER1_A0_ISR (void)
#else
#error Compiler not supported!
#endif
{
  P1OUT ^= 0x01;                            // Toggle P1.0
  TA1CCR0 += 50000;                         // Add Offset to CCR0
}



//ADC Interrupt
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=ADC12_VECTOR
__interrupt void ADC12ISR (void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(ADC12_VECTOR))) ADC12ISR (void)
#else
#error Compiler not supported!
#endif
{
    results[index] = ADC12MEM0;             // Move results
    index++;                                // Increment results index, modulo; Set Breakpoint1 here


    if (index == 2000)
      index = 0;


    ADC12IFG = 0x0000;
}






static void setup_ADC(void){


/*  Output impedance of the DAC buffer (OPA735) is 125 ohms, so from section 28.2.5.3 of the user's guide
 *  t_samp > (125+1800)*2^13*25p + 800n, or t_samp > 1.234us. MCLK/4 period is 200ns,
 *  so needed sample period is 7 clocks (?)
*/


    ADC12CTL0 = ADC12SHT0_1 | ADC12ENC | ADC12ON;                                         // Sampling timer is 8 clocks, enable conversions, turn ADC12 on
        ADC12CTL1 = ADC12SSEL_2 | ADC12DIV_3 | ADC12SHS_1 | ADC12SHP;      // MCLK (20MHz) chosen as reference clock
                                                                                                                                            // Divide the clock by 4. New Clock becomes MCLK/4 = 5MHz
                                                                           //SHI source is Timer A CCR1
                                                                           //SAMPCON is sourced from sampling timer (8 clocks)


        P6SEL |= 0x01;                                                       // P6.0 ADC channel A0 select
        ADC12IE = 0x01;                                                    //Enable ADC Interrupts
}



void setClocks(void)
{
    void SetVcoreUp (unsigned int level);


      // Increase Vcore setting to level3 to support fsystem=20MHz
      // NOTE: Change core voltage one level at a time..
      SetVcoreUp (0x01);
      SetVcoreUp (0x02);
      SetVcoreUp (0x03);


      UCSCTL3 = SELREF_2;                       // Set DCO FLL reference = REFO
      UCSCTL4 |= SELA_2;                        // Set ACLK = REFO


        __bis_SR_register(SCG0);                  // Disable the FLL control loop
        UCSCTL0 = 0x0000;                         // Set lowest possible DCOx, MODx
        UCSCTL1 = DCORSEL_5;                      // Select DCO range 20MHz operation
        UCSCTL2 = 610;                   // Set DCO Multiplier for 20MHz
                                                  // (N + 1) * FLLRef = Fdco
                                                  // (610 + 1) * 32768 = 20MHz
        __bic_SR_register(SCG0);                  // Enable the FLL control loop


        // Worst-case settling time for the DCO when the DCO range bits have been
        // changed is n x 32 x 32 x f_MCLK / f_FLL_reference. See UCS chapter in 5xx
        // UG for optimization.
        // 32 x 32 x 25 MHz / 32,768 Hz ~ 780k MCLK cycles for DCO to settle
        __delay_cycles(625000);


      // Loop until XT1,XT2 & DCO stabilizes - In this case only DCO has to stabilize
      do
      {
        UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);
                                                // Clear XT2,XT1,DCO fault flags
        SFRIFG1 &= ~OFIFG;                      // Clear fault flags
      }while (SFRIFG1&OFIFG);                   // Test oscillator fault flag
}


void SetVcoreUp (unsigned int level)
{
  // Open PMM registers for write
  PMMCTL0_H = PMMPW_H;
  // Set SVS/SVM high side new level
  SVSMHCTL = SVSHE + SVSHRVL0 * level + SVMHE + SVSMHRRL0 * level;
  // Set SVM low side to new level
  SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 * level;
  // Wait till SVM is settled
  while ((PMMIFG & SVSMLDLYIFG) == 0);
  // Clear already set flags
  PMMIFG &= ~(SVMLVLRIFG + SVMLIFG);
  // Set VCore to new level
  PMMCTL0_L = PMMCOREV0 * level;
  // Wait till new level reached
  if ((PMMIFG & SVMLIFG))
    while ((PMMIFG & SVMLVLRIFG) == 0);
  // Set SVS/SVM low side to new level
  SVSMLCTL = SVSLE + SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level;
  // Lock PMM registers for write access
  PMMCTL0_H = 0x00;
}


void setup_TimerA0(void){
      TA0CTL = TASSEL_2 + MC_1;         // SMCLK, up mode, clear TAR
      TA0CCR0 = 200-1;                            //200 clocks@5MHz = 100ksps
      TA0CCTL1 = OUTMOD_3;              //Set, Reset on TA1
      TA0CCR1 = 99;                                //trigger for ADC


      //Code to examine sample PW cycle at GPIO
      P1SEL |= BIT2;                                 // P1.2 option select
      P1DIR |= BIT2;                                  // P1.2 output
}

Best Regards,

Carolus Andrews, Analog Applications, Current and Hall Effect Sensors

Getting Started with Current Sensing Video Training Series

TI makes no warranties and assumes no liability for applications assistance or customer product design. You are fully responsible for all design decisions and engineering with regard to your products, including decisions relating to application of TI products. By providing technical information, TI does not intend to offer or provide engineering services or advice concerning your designs.

  • Hi Carolus,

    The main reason that your code is not working is because of the order you are initializing the ADC. If you check the device user's guide www.ti.com/.../slau208 section 28.2.1 12-Bit ADC Core, you'll see that it says "With few exceptions, the ADC12_A control bits can be modified only when ADCENC = 0." In the registers section ADC12CTL1 register Figure 28-14, you'll see that most of the bits are shaded and marked "can be modified only when ADC12ENC = 0". So right now, your ADC12CTL1 settings aren't occurring because on the line before it, when you initialize ADC12CTL0, you set ADC12ENC. So you can simply remove the setting of ADC12ENC from your initialization and only set it at the very end of your ADC setup routine. Note that with your current setup, only 1 sample will occur - if you want to repeatedly sample the same channel, triggered by the timer, you need to set ADC12CONSEQ_2 in the ADC12CTL1 register as well.

    There are some good MSP430F5529 ADC code examples here: dev.ti.com/.../
    Additionally, you may prefer the APIs provided with driverlib instead: dev.ti.com/.../

    Regards,
    Katie
  • In reply to Katie Pier:

    Katie,

    It's always some tiny detail, isn't it? This fixed the problem. Thanks!

    Best Regards,

    Carolus Andrews, Analog Applications, Current and Hall Effect Sensors

    Getting Started with Current Sensing Video Training Series

    TI makes no warranties and assumes no liability for applications assistance or customer product design. You are fully responsible for all design decisions and engineering with regard to your products, including decisions relating to application of TI products. By providing technical information, TI does not intend to offer or provide engineering services or advice concerning your designs.

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.