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.

Stellaris LaunchPad, ADC behaviour



Hi guys,

I've choosen for my last university project the amazing Stellaris Launchpad.

Everything goes fine until I've used the integrated ADC:

A simple two steps sequence is used to measure I-V of a device:

Configuration:

GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_4);
GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_5);
ADCSequenceDisable(ADC0_BASE, 2);
ADCSequenceConfigure(ADC0_BASE, 2, ADC_TRIGGER_PROCESSOR, 0);
ADCSequenceStepConfigure(ADC0_BASE, 2, 0, ADC_CTL_CH8);
ADCSequenceStepConfigure(ADC0_BASE, 2, 1, ADC_CTL_CH9 | ADC_CTL_IE | ADC_CTL_END );
ADCSequenceEnable(ADC0_BASE, 2);
Call:

while(i < 300)
{
ADCIntClear(ADC0_BASE, 2);
ADCProcessorTrigger(ADC0_BASE, 2);
GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_7, 0);
while(!ADCIntStatus(ADC0_BASE, 2, false))
{
}
ADCSequenceDataGet(ADC0_BASE, 2, ADCvalue);
UARTCharPut(UART0_BASE, (0x3F & (ADCvalue[0] >> 6)));
UARTCharPut(UART0_BASE, (0x40 | (0x3F & ADCvalue[0])));
SysCtlDelay(1000000);
UARTCharPut(UART0_BASE, (0x80 | (0x3F & (ADCvalue[1] >> 6))));
UARTCharPut(UART0_BASE, (0xC0 | (0x3F & ADCvalue[1])));

if (ADCvalue[1] < 20) break;
i ;
}

As you can see, I put ADC datas into UART buffer with a simple two packets communication protocol that marks with a mask the packet (0x3F, 0x40 an so on).

Sometimes, two three times every call, samples of the first channel are changed with the samples of the second channel. It seems that ADC samples first the second channel and then the first one.

Can you help me?

Thank you so much!

  • Code extract does not show this required set-up/config...  (and there may be more - this jumps out!)

         // Enable the ADC peripherals and the associated GPIO port
        //
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE );

    This is missed time & again - if you have done this it should be shown...

    Another thought - suspect that it is better to "unpack" your ADC FIFO - it may be that you have an over or underflow - or your FIFO is NOT empty after reading the data.

    Here's one method:  Note: we used this for a different sequence than yours - you must adapt.

            //
            // Disable the sequence.
            //
            HWREG(ADC0_BASE + ADC_O_ACTSS) &= ~ADC_ACTSS_ASEN0;
            //
            // Drain the Sequence FIFO.
            //
            while(!(HWREG(ADC0_BASE + ADC_O_SSFSTAT0) & ADC_SSFSTAT0_EMPTY))
            {
                //
                // Read the next sample.
                //
                ulTemp = HWREG(ADC0_BASE + ADC_O_SSFIFO0);
            }

            //
            // Clear any overflow/underflow conditions that might exist.
            //
            HWREG(ADC0_BASE + ADC_O_OSTAT) = ADC_OSTAT_OV0;
            HWREG(ADC0_BASE + ADC_O_USTAT) = ADC_USTAT_UV0;

        // Read the samples from the ADC FIFO.
        //
        g_pusADC0DataRaw[0] = HWREG(ADC0_BASE + ADC_O_SSFIFO0);   //   Note: your data is much safer copied to var - as shown here!
        g_pusADC0DataRaw[1] = HWREG(ADC0_BASE + ADC_O_SSFIFO0);


       

     

  • This might be of interest as well:

    http://e2e.ti.com/support/microcontrollers/stellaris_arm_cortex-m3_microcontroller/f/473/t/212263.aspx

    have fun...

  • sorry for my late answer!

    Why should I have an underflow or an overflow? I wait until ADC generates an interrupt!

    Thank you so much!

  • Suggest that you try this:

    while(!ADCIntStatus(ADC0_BASE, 2, false))
    {
    }

    ADCIntClear(ADC0_BASE, 2);   // add this - also leave it - where it exists now - top instruct w/in while...

    ADCSequenceDataGet(ADC0_BASE, 2, ADCvalue);

    var0 = ADCvalue[0];

    var1 = ADCvalue[1];

    and then use your:

    UARTCharPut(UART0_BASE, (0x3F & (var0 >> 6)));   // this to insure that you don't over-flow the ADC FIFO 

    and similarly for var1...

    The fact that you confirm that your ADC data is "intermixed" - strongly points to over or under-flow.  You may succeed just with the 2nd ADCIntClear() - but try with the code as suggested first - then you may experiment by "backing out" the copy of the FIFO data.