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 input channel-to-channel interference?

Other Parts Discussed in Thread: MSP430F5419

I'm using ADC12 in single-channel-single-conversion mode on an MSP430F5419 (non-A).  I have two analog inputs:

ch1 has no signal input for 0 counts
ch2 has a small input for 1290 counts

If I continuously read ch1 ch2, all conversions are correct.  If I alternate between channels, ch1 ch2 eventually shows a 0 conversion result (or near 0), then returns to normal.  I'm at a loss.  I've scoped ch1 ch2 adc input looking for low-value fluctuations...none found.  Any help is much appreciated!

Code

//------ Internal ADC Setup --------------------------------------------------------------

ADC12CTL0 = ADC12ON + ADC12REFON;                    // Turn on ADC and reference
ADC12CTL1 = ADC12SSEL_1;                                          // Select ACLK (1 MHz) as ADC clk source
ADC12CTL2 = ADC12PDIV + ADC12RES_2;                  // PreDivide-by-4 ADC clk, 12 bit conversions
ADC12MCTL0 = ADC12SREF_1 + ADC12INCH_0;       // Select ADC reference 1.5V internal, ch0

//------ ADC state machine -------------------------------------------------------------
switch (adc_sm)
{
    //------ Start sample channel -------------------------------------------------------
    case 0:
    ADC12CTL0 |= ADC12SC + ADC12ENC;       // Sample channel
    ticks = SYS_TICKS;                                               // Get system tick count

     adc_sm = 1;                                                          // Select next state
     break;

     //------ Check sampling complete ----------------------------------------------------
     case 1:
     if (CheckTicks(ticks, TPS * 0.1) == true)     // If 100ms sample period expired
     {
          ADC12CTL0 &= ~ADC12SC;                    // Start conversion
          adc_sm = 2;                                                 // Select next state
     }
     break;

      //------ Check conversion complete --------------------------------------------------
      case 2:
       if ((ADC12CTL1 & ADC12BUSY) == false)
       {
            ai_ch[ch].value = ADC12MEM0;               // Save conversion

            ch = ch ^ 1;                                                   // Get next channel

            ADC12CTL0 &= ~ADC12ENC;                // Disable ADC
            ADC12MCTL0 &= 0xF0;                            // Clear ADC channel select
            ADC12MCTL0 |= ch;                                  // Select new ADC channel

            adc_sm = 0;                                                // Select sample channel state
        }
        break;

        default:
        adc_sm = 0;
        break;
}




  • On AD12, each conversion is independent of conversion history (this is different for the SD16/SD24). For each individual conversion, one of the multiplex connections is opened, the conversion capacitor is scharged, and the conversion is done.  It makes no difference whether you convert a single channel or switch channels or even sequence or a pattern.
    Any anomaly is either caused by a bug in the software algorithm or external (spikes, crosstalk).

    After turning on the reference, you'll have to wait until it has settled. Else readings are not reliable (usually larger than expected)

    Contrary to your text, the ADC is set for CH0 in the posted code.

    Using floating point numbers and calculations in your call to CheckTicks is slow and inefficient. (and likely not necessary at all - use integer arithmetics where possible)

    250kHz conversion speed may be quite slow - it should be still okay, but on slow conversion clock, the sampled charge may leak away during conversion.
    Since you are controlling the sampling time by your own timing, there is no need to use a slow conversion clock. You can use MODOSC (default) and if you don't want to stabilize your reference externally, use a /4 divider on it. Else keep the default, giving you the conversion results after ~3µs  (fast enough so a busy waiting loop for the result doesn't take longer than looping the state machine once)

    You don't show how you alternate the channels. Perhaps that's the problem.

  • Dood +1 for you getting contributor of the year 2012.  Seriously, I don't think I have a single post that you haven't supported.  Thanks for your contribution to this site and many EE's!

    You're right, it was a software bug...stupid array index out of range.  I should have seen that sooner.

    ADC channels are switched every conversion with this line: 

    ch = ch ^ 1; // Get next channel

    I'll modify CheckTicks for integer arithmetic where possible.  Speed hasn't ever been a concern on the projects I've worked on so I'm not familiar with "best practice" in this area.  Thanks for the tip!

    Last q. For the ADC clock divide-by-4, is there a preference between ADC12PDIV and ADC12DIV?

  • jdr said:
    Last q. For the ADC clock divide-by-4, is there a preference between ADC12PDIV and ADC12DIV?

    Well, not much. The ADC12 (you are using the ADC12_A) didn't have the PDIV. Well, the MSPs with the old ADC12 were 8MHz only.
    I guess instead of completely restructuring the existing ADC12DIVx bitfield (where to get the additional 2 bits?), another pre-divider was added to the new ADC12CTL2 register.
    So ADC12CTL1 was kept unchanged.

**Attention** This is a public forum