cancel
Showing results for 
Search instead for 
Did you mean: 

ADC/DMA array setup and read

aeolia_amha
Associate II
Posted on May 17, 2010 at 08:28

ADC/DMA array setup and read

16 REPLIES 16
mrost9
Associate II
Posted on May 17, 2011 at 13:51

Looks like you're almost there.

just declare an array, like

u16 ADC_RegularConvertedValueTab[5];

I'm doing it exactly the same, as you can see in the thread ''ADCDMA one off problem''

[DEAD LINK /public/STe2ecommunities/mcu/Lists/ARM%20CortexM3%20STM32/Flat.aspx?RootFolder=/public/STe2ecommunities/mcu/Lists/ARM CortexM3 STM32/ADCDMA one off problem&FolderCTID=0x01200200770978C69A1141439FE559EB459D758000626BE2B829C32145B9EB5739142DC17E]Link

aeolia_amha
Associate II
Posted on May 17, 2011 at 13:51

Thanks for the quick reply, we almost have the same problem.

Does this array, u16 ADC_RegularConvertedValueTab[5];, when put into function main,already work or does this need to be programmed. From what I assume from your code, does your array store the values into memory or just overwrites it afterward, I think it doesn't store value.

I need to collect samples or data from 5 ADC channels individually for a period of 1 minute and store it . The sampling size needed not be very accurate. How do I access this array to read if it reads the correct output from my ADC.

Any suggestions?

mrost9
Associate II
Posted on May 17, 2011 at 13:51

In theory, you can use the value array as it is. But it would be good style to initialize it to a known value.

Actually, I have the ADC and DMA running continuously. So whenever I a value from the array, it is always the latest value.

If you want to keep the old values for later reference, why don't you just make the array bigger? You would need the memory anyway to store your measurement values.

Or are you going to put then into flash memory?

Then I'd prefer, as your code does, to only measure each channel once, the store the values away and trigger the next ADC cycle.

aeolia_amha
Associate II
Posted on May 17, 2011 at 13:51

By making the array bigger, do you suggest making it 2 dimensional array[x][y] or by making it 1-d array[x] and making it longer. Which is easier to store and read data for this case? From your suggestion, how do you measure each channel once, store the value and trigger the next ADC cycle.

From the given example programs where I pattern mine, it doesn't show how to store an array and how to access it in the future.

For your case, how do you read the data from a specific channel when storing it in an array, does the mcu automatically distinguish it? From what I can infer from your application, you measure 5 adc channels and overwrite immediately the previous ones, how do you separately read data from multiple channels using array.

Any tips?

Thanks

mrost9
Associate II
Posted on May 17, 2011 at 13:51

The ADC triggers the DMA after each measurement.

The DMA transfers the result to the destination (your array) and increments the pointer.

As you have selected Discontinuous mode, the ADC stops after all channels are converted.

So you end up with 5 measurements in your array, in the order of the ADC channels you selected.

So for your code, you end up with

ADC_RegularConvertedValueTab[0] contains ADC_Channel_4

ADC_RegularConvertedValueTab[1] contains ADC_Channel_14

ADC_RegularConvertedValueTab[2] contains ADC_Channel_5

ADC_RegularConvertedValueTab[3] contains ADC_Channel_6

ADC_RegularConvertedValueTab[4] contains ADC_Channel_7

Whether you use 1- or 2-dimensional array, is up to your liking.

Personally, I'd put up a 2-dimensional array, so I could easily get my 10 measurements of each channel without having to calculate index offsets.

As the array is represented as as many bytes in a row, you could just tell the DMA to fill the whole array in one go (set the DMA buffersize to the overall length). The DMA waits for the ADC to trigger it, so a row will be filled each time you trigger the ADC.

aeolia_amha
Associate II
Posted on May 17, 2011 at 13:51

Thanks for the explanation, this made it more clear to me.

I am confused with the last paragraph. What do you mean by array representing as many bytes in a row. In my case it is 5, do you suggest that the row be equal to 5, so after filling the whole array row, it goes to the next. Is this what you mean by row being filled each time you trigger the ADC. This will trigger because it is in scan mode and continuous mode. Is my assumption correct?

 

t1
Associate II
Posted on May 17, 2011 at 13:51

If I was you I would keep it as simple as possible until you have something working.  Forget DMA, forget scan mode, forget continuous mode.  Use those features later if you need to.

I have a potentiometer on my board on PC4.  This program will take 5 readings on a row and save the results in an array.  It will then take a further 5 readings a little later and so on.

// Initial C Source File

#include ''xstdsys.h''

unsigned short Results[1000];

int nResultsIndex;    // = 0

main()

{

    // PC4 to analog mode

    g_pGPIOC->CRL &= ~0X000F0000;

    // enable ADC1 clock

    g_pRCC->APB2ENR |= ADC1EN;

    // enable ADC1, external trigger software start

    g_pADC1->CR2 = ADC_EXTTRIG | ADC_EXTSEL2 | ADC_EXTSEL1 | ADC_EXTSEL0 | ADC_ADON;

    // channel 14 is first and only conversion channel

    g_pADC1->SQR3 = SQ1_3 | SQ1_2 | SQ1_1;

    while (1)

    {

        for (int i = 0; i < 5; i++)

        {

            g_pADC1->CR2 |= ADC_SWSTART;

            while ((g_pADC1->SR & ADC_EOC) == 0);

            Results[nResultsIndex++] = g_pADC1->DR;

        }

        if (nResultsIndex == 1000)

            nResultsIndex = 0;

        // wait a while before doing next 5 readings

        for (int i = 0; i < 1000000; i++);

    }

}

You will need to change the mnemonics for the registers and bits to suit you tool suite.

mrost9
Associate II
Posted on May 17, 2011 at 13:51

If you define a 

BYTE array[10][10]

you get 100 bytes of consecutive memory.

Writing these bytes sequentionally (as DMA does) is like writing row after row.

aeolia_amha
Associate II
Posted on May 17, 2011 at 13:51

As a practice, I did almost exactly the same as your code (M. Rost) except that I used 2 analog inputs and used GPIO_SetBits when a certain condition is met. Your method of using array worked. I'm still studying on how to do the 2-d array and how to store the data. Do you suggest that I average the data then store it or sample every of them and store every of them? Thanks.