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.

MSP430 stuck after ADC repeat single channel conversion

Other Parts Discussed in Thread: MSP430G2432

Hi folks.

I am having an issue where my MSP430G2432 gets stuck on the line of code where I am trying to disable ADC conversion ("ADC10CTL0 &= ~ENC;") - at least according to the debugger.  This happens right after the ADC finishes a repeat single channel conversion and exits low power mode via an ISR.  If I hit "Resume" after entering debug mode, and then pause later on, it always is on this line.  Also, it will not let me single step past this point.  My code is below.  The code is essentially taking a large number of samples and summing them so I can get the average.

If anyone has any thoughts, I would appreciate the input. I'm afraid the solution is obvious, but I haven't had any luck finding it.

Thanks!

#include <msp430.h>
#include <stdint.h>

// Multiply to get the total num of samples (e.g., 32*64=2048)
#define NUM_SAMPLES 32
#define SAMPLES_MULTIPLIER 64

uint8_t count = 0;
uint16_t samples[NUM_SAMPLES];
uint32_t sum = 0;


void config() {

DCOCTL = CALDCO_8MHZ;  // Make the uP run at 8MHz
BCSCTL1 = CALBC1_8MHZ; // Make the uP run at 8MHz
BCSCTL2 = 0;           // DCO is MCLK source, MCLK/1, DCO is SMCLK source, SMCLK/1, DCOR not available
BCSCTL3 = LFXT1S_2;    // XT2 00, VLO is ACLK source, XCAP 00, XT2OF 0, LFXT1 0

// ADC
ADC10CTL0 = SREF_7 + ADC10SHT_1 + MSC + ADC10ON + ADC10IE;
ADC10CTL1 = CONSEQ_2 + INCH_0 + ADC10DIV_3 + ADC10SSEL_3;
ADC10DTC1 = NUM_SAMPLES;                                   // 32 (0x20) conversions
P1DIR &= ~BIT0;                                            // Set P1.0 to input direction
ADC10AE0 |= BIT0;                                          // Select P1.0 for ADC to sample

}

int main(void) {

   WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer

   config();

   _EINT();

   while(1) {

      ADC10CTL0 |= ENC + ADC10SC;       // Enable Conversion and conversion start
      __bis_SR_register(CPUOFF + GIE);  // LPM0, ADC10_ISR
      ADC10CTL0 &= ~ENC;                // Disable Conversion - GETS STUCK HERE
      while (ADC10CTL1 & BUSY);         // Wait if ADC10 busy
      ADC10SA = (uint16_t)samples;      // Transfers data to next array (DTC auto increments address)

      uint8_t i;
      for (i = 0; i < NUM_SAMPLES; i++) {
         sum += samples[i];
      }

      if (count == SAMPLES_MULTIPLIER-1) {

         save_sum(sum);  // Not really what happens here, but this part is irrelevant to the question.

         sum = 0;
         count = 0;

      } else {
         count++;
      }

   }

}

// ADC10 interrupt service routine
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR(void) {
   __bic_SR_register_on_exit(CPUOFF);
}

  • Tyler Horton said:
    ... at least according to the debugger ...

    That is exactly what happens. When the CPU is off, the debugger will show you it is stuck at the next instruction.

  • old_cow_yellow said:

    That is exactly what happens. When the CPU is off, the debugger will show you it is stuck at the next instruction.

    I don't think this is the problem, however (at least not entirely).  I put an instruction in the code to set a pin high so I could see what was going on without the dubugger.  The pin was set high whenever I placed the instruction anywhere before the "__bis_SR_register(CPUOFF + GIE);" line.  Anywhere after that, including inside the ISR, the pin was never set high.  So for some reason, I think, the interrupt signalling the sampling is done is never getting triggered, or the ISR isn't being called.

  • It probably isn't finishing the sequence because the DTC is not configured for the first run, your code for resetting it for the next loop is also wrong.

    ADC10SA = (uint16_t)samples;

    The ADC10SA register needs the address of the first result, the remaining results will be sequentially written the memory locations following the one specified. Therefor you need:

    ADC10SA = (unsigned int)&(samples)

    Make sure you set it the first time before you start the ADC, you could do it just before the ADC is started, then it will happen every loop.

     

**Attention** This is a public forum