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.

ADC12 Sampling Sequence Every Other Time

Other Parts Discussed in Thread: MSP430F5340

My goal: Sample two ADC12 channels at a sample rate of 160Hz. I am using TimerA0 for generating an interrupt at a rate of 160Hz, which then starts the ADC conversion sequence.

Symptoms: Only every second time the timer interrupt is called, does the ADC interrupt get thrown. In other words, the timer is telling the ADC to sample at a rate of 160Hz, but the ADC is sampling at a rate of 80Hz. I have verified the timing with an oscilloscope.

I have tried everything I can think of, and am completely stuck. Any help would be GREATLY appreciated.

___________________

#include <msp430.h>

void initPins(void);
void initTimers(void);
void initADC(void);
void initClocks(void);

unsigned long ADC_Result_0;
unsigned long ADC_Result_1;

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

initPins();
initTimers();

while(1)
{
initADC();
__bis_SR_register(LPM3_bits + GIE); // Enter LPM0, interrupts enabled
}
}


void initPins(void) {

P1DIR |= BIT1; // P1.1 LED PPG 1
P1OUT |= BIT1 + BIT2;

P5DIR |= BIT0;
P5OUT &= ~BIT0;

P6SEL = BIT1; // Enable A/D channel inputs
P5SEL = BIT1;
}

void initTimers(void) {
// Timer for ADC - 160Hz
TA0CCR0 = 206;
TA0CCTL0 = CCIE; // CCR0 interrupt enabled
TA0CTL = TASSEL_1 + MC_1 + TACLR; // ACLK, upmode, clear TAR
}

void initADC(void) {
ADC12CTL0 = ADC12ON;
ADC12CTL0 |= ADC12MSC + ADC12SHT0_15; // Turn on ADC12, enable multiple

ADC12CTL1 = ADC12SHP+ADC12CONSEQ_1; // Use sampling timer, single sequence
ADC12MCTL0 = ADC12INCH_9; // ref+=AVcc, channel = A0
ADC12MCTL1 = ADC12INCH_1 + ADC12EOS; // ref+=AVcc, channel = A1
ADC12CTL2 = ADC12SR;
ADC12IE = ADC12IE1; // Enable ADC12IFG.3 **note, can use differen interrupts for things
ADC12CTL0 |= ADC12ENC; // Enable conversions
}

#pragma vector=TIMER0_A0_VECTOR
__interrupt void TIMER0_A0_ISR(void)
{
P1OUT ^= BIT1;
ADC12CTL0 |= ADC12SC; // Sampling and conversion start
}

#pragma vector=ADC12_VECTOR
__interrupt void ADC12ISR (void)
{
P5OUT ^= BIT0;
switch(__even_in_range(ADC12IV,34))
{
case 0: break; // Vector 0: No interrupt
case 2: break; // Vector 2: ADC overflow
case 4: break; // Vector 4: ADC timing overflow
case 6: break; // Vector 6: ADC12IFG0
case 8: // Vector 8: ADC12IFG1

ADC_Result_0 = ADC12MEM0; // Move results, IFG is cleared
ADC_Result_1 = ADC12MEM1;

break;
case 10: break; // Vector 10: ADC12IFG2
case 12: break; // Vector 12: ADC12IFG3
case 14: break; // Vector 14: ADC12IFG4
case 16: break; // Vector 16: ADC12IFG5
case 18: break; // Vector 18: ADC12IFG6
case 20: break; // Vector 20: ADC12IFG7
case 22: break; // Vector 22: ADC12IFG8
case 24: break; // Vector 24: ADC12IFG9
case 26: break; // Vector 26: ADC12IFG10
case 28: break; // Vector 28: ADC12IFG11
case 30: break; // Vector 30: ADC12IFG12
case 32: break; // Vector 32: ADC12IFG13
case 34: break; // Vector 34: ADC12IFG14
default: break;
}
}

  • Hey!

    Just a thought: you may want to set the output mode for the timer module.  i.e.TA0CCTL0 = OUTMOD_3 (which is set/reset behavior)  

    I'm (successfully) doing the same thing at 480Hz and I noticed your post.

  • Isn't ACLK 12 kHz which would give a period of 83 usec. Multiply by your count of 206 = 17 ms which is only 58 Hz not 160 Hz

  • I still have the same effect when using OUTMOD_3 and ACLK is normally 12 kHz, but you can set ACLK to be 32 kHz using the following:

    UCSCTL4 = SELA__REFOCLK; // ACLK = REFO (32kHz)

    The timing is accurate, I am getting 160 Hz, tested and verified with an oscilloscope.

    Another bit of information, I was able to "solve" the problem by toggling SC twice.

    ADC12CTL0 |= ADC12SC; // Sampling and conversion start
    ADC12CTL0 &= ~ADC12SC; // Sampling and conversion start
    ADC12CTL0 |= ADC12SC; // Sampling and conversion start
    ADC12CTL0 &= ~ADC12SC; // Sampling and conversion start

    I would like to understand what's going on here though, even though the fix works, I am not happy with keeping it in my code.

    Thank you!

  • You don't say which micro you're using so I couldn't check the header file. Maybe something wrong with #define ADC12MSC? Perhaps should just be MSC?

  • Sorry for not mentioning that! I am using the MSP430F5340. Thank you. I checked the MSC definition, and it is 0x0008, which I believe is correct from the Family User Guide.  Thank you for the suggestion though, I never thought to check the definition.

  • We just saw the same issue, using the 5335...
    Per User Guide SLAU208M: The register description for ADC12CTL0 says that "ADC12SC is reset automatically." However, I noticed that Section 28.2.7.2 Sequence of Channels Mode says "The ADC12SC must be cleared by software after each sequence to trigger another sequence." (This was added at Rev L.)
    I added a line to the ADC interrupt to clear ADC12SC and now we get interrupts every time.
  • That's right, ADC12SC only automatically clears when in single conversion mode.

    p.s.: why not using a timer to directly control the conversion start? No need for a timer ISR, the CPU can stay in low-power-mode until conversion is done and the sample timing is jitter-free (no latency until the CPU starts the next conversion or enters the timer ISR at all)

**Attention** This is a public forum