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.

CCS/MSP-EXP430FR2433: Driverlib ADC channel 'specified memory buffer'

Part Number: MSP-EXP430FR2433


Tool/software: Code Composer Studio

Hi,

I'm trying to use the Launchpad kit to read out multiple channels with driverlib (MSP430 DriverLib for MSP430FR2xx_4xx Devices)

I've already successfully read multiple channels on a different launchpad by using the ADC12.

With ADC 12 I was able to store my ADC values in specified memory buffers according to the configureMemory and getResult functions with the code

    ADC12_B_configureMemoryParam memParam1 = {0};
    memParam1.memoryBufferControlIndex = ADC12_B_MEMORY_0;                   // first memory slot
    memParam1.inputSourceSelect = ADC12_B_INPUT_A9;                          // input pin sensor 1
    memParam1.refVoltageSourceSelect = ADC12_B_VREFPOS_AVCC_VREFNEG_VSS;     // default
    memParam1.endOfSequence = ADC12_B_NOTENDOFSEQUENCE;                      // keep on sampling
    memParam1.windowComparatorSelect = ADC12_B_WINDOW_COMPARATOR_DISABLE;    // default
    memParam1.differentialModeSelect = ADC12_B_DIFFERENTIAL_MODE_DISABLE;    // default
    ADC12_B_configureMemory(ADC12_B_BASE, &memParam1);                       // load settings

Where ADC12_B_MEMORY_0 held my ADC values and could be read out by

L1 = ADC12_B_getResults(ADC12_B_BASE, ADC12_B_MEMORY_0);

I can apply different inputs to different memory locations quite easely for reading out multiple channels.

Now here's where the difference/problem is: ADC10 apparently doesn't support this memory feature, because ADC10's function getResults and configureMemory don't accept a memory location (for getResults only a baseAddress is asked and for configure memory there's no memoryBufferControlIndex setting).

The code now looks like this where I want to send my data over the UART conneciton:

ADC_startConversion(ADC_BASE,                           //start ADC conversion
                            ADC_REPEATED_SEQOFCHANNELS);        // multiple sequential reads until disable command

    while(1){
        L1 = ADC_getResults(ADC_BASE);    // Lsensor 1
        L2 = ADC_getResults(ADC_BASE);    // Lsensor 2
        P1 = ADC_getResults(ADC_BASE);    // Psensor 1

        if (L1 >= 0x001){                                           // Threshold for sensor
            transmitEUSCI_UART16(L1|0x1000);                       // add designation 1 for sensor 1, send value
         }

Previously on ADC12 I could specify which value I wanted to put in my L1, L2 and P1 variables and it worked great.
Now on ADC10 I get some results over UART, but I can't tell which ADC results I'm actually sending, and I can't guarantee if it is the expected ADC result.

The only example codes I found were based on interrupts or for a single read-out. I want to manually read my ADC sensor value in a loop and spit out the sensor values over UART.

Driverlib also says under the getResult function "

Parameters
baseAddress is the base address of the ADC module.
Returns
A Signed Integer of the contents of the specified memory buffer.

"

So my question: Where are my ADC values stored? Where is this 'specified memory buffer'? I read some things about the DTC to move memory from INCH registers, but the driverlib apparently doesn't know anything about DTC or the INCH registers.

  • The FR2/4 series ADC has only one result buffer+control (ADCMEM0/MCTL0). For multiple channels it samples from An (down) to A0, similar to the ADC10. There's no DMA nor DTC, so you have to grab the samples as they appear. With MSC=1 this can be a challenge. Per-channel VREF settings are also tricky.

    The strategy I use for multiple channels is to set MSC=0, and space the triggers so as to give the program time between them to fetch the results.

  • Thanks for your reply!

    So everytime I read the ADC by the command "ADC_getResults(ADC_BASE);" I get the results of ADC channel A3, and when I use the command again, it is the result of A2, down to A1 (the lowest set ADC channel)  and it starts with A3 (highest set channel) again after every repeated command?

    VREF shouldn't be a problem since I want to use the same voltage reference for every channel. I assume this is default.

     And maybe a simple question; what does MSC stand for? I see no such abbreviation in the datasheet.

  • You're currently using repeated-sequence mode (CONSEQ=3), and in context you're probably using MSC=1, so the ADC is doing sweeps as fast as it can. With a single MEM register, you have no idea at any given time which result is in it. (There are clues, but too many races to use them reliably.)

    You'll need a lock-step mechanism (schematically trigger/wait/fetch for each channel). There are different strategies, but you can't just let it run and pick the results at leisure the way you can with the ADC12.

    ADCMSC is described in FR2/4 User Guide (SLAU445I) Sec 21.2.7.5. It generally causes the ADC to continue on (per context) after a conversion is done, rather than waiting for another trigger. Driverlib knows it as ADC_MULTIPLESAMPLESENABLE.

  • With the goal of my system in mind, I wanted the system to stream ADC data to a pc without a trigger, just a continuous stream of recent data. The pc program doesn't care about the exact value of the ADC, but it does care if the value surpasses a certain threshold. Therefore accuracy and exact timings aren't too important.

    I thought by running the ADC continuously on the fastest speed, I'll get the most recent value from a sensor to stream over UART to my pc without too many problems, as long as I know which channel is being read. Now I see it doesn't really work like that on this ADC.

    Would you suggest to use "ADC_configureMemory();"to start sampling on A3, use single samples, and everytime it has finished a single conversion and gave an interrupt, I should trigger the next conversion and wait for the next adc-completed-interrupt and that value will be A2 and repeat it until A0 is reached? Will this work with my intended use-case?

  • To keep your high-level structure, you might want to maintain a "shadow" MEM-register array. Run the ADC continuously (CONSEQ=3) but with a discrete trigger (MSC=0), and have an ADC ISR which fetches the MEM0 value into the array in the background. main() can fetch values out of the array when it chooses, 

    Example adc10_10 illustrates the principle. The ADC_Results[] array serves as the shadow-MEM array. (I don't see an equivalent Driverlib example.):

    http://dev.ti.com/tirex/explore/node?node=ADbtMIec3YLSRwlYtORsMw__IOGqZri__LATEST

    This version of adc10_10 uses a timer trigger (SHS=2). You could use a software trigger (SHS=0) and set ADCSC in the ISR to trigger the next conversion; this would run fast, but you might find it eating into your CPU budget. 

  • Thanks for helping me understand the ADC :)

    "This version of adc10_10 uses a timer trigger (SHS=2). You could use a software trigger (SHS=0) and set ADCSC in the ISR to trigger the next conversion; this would run fast, but you might find it eating into your CPU budget. "

    This is what I'll try to implement in my system. Luckily the MCU doesn't have to do a lot, only passing ADC data through to UART, so I hope it'll work. I'll get back to you if I managed to make it work.

    Update:


    The shadow memory trick worked! It needed some finetuning and 'delays' in clock dividers and cyclehold. Having everything on the fastest settings gave me too many interrupts.The somewhat recursive command in the ISR as trigger works very well.

    Apparently I already had the settings MSC=0, CONSEQ=3 and SHS=0 since the beginning, the only thing i really missed was the ISR and cycle/hold code for my program (and a small bug where SMCLK for eUSCI was not 1MHz but 1.048MHz, giving me weird packetloss.)

    Thanks again!

  • Hi M Spit,

    I am going to close this post now.

    Please reply directly to reopen the post when you have any further questions.

    Thanks,

    Ling

**Attention** This is a public forum