cancel
Showing results for 
Search instead for 
Did you mean: 

ADC & DMA

planeetmaa
Associate II
Posted on February 23, 2007 at 07:15

ADC & DMA

2 REPLIES 2
planeetmaa
Associate II
Posted on February 22, 2007 at 06:42

Hi all!

Im using STR730 in my current project. I encountered few problems while trying to use DMA to transfer ADC conversion results.

I tried to set up DMA to transfer data from few specified channels. Channels 1, 5, 7 and 9, for example. So I did the following:

---------------------------------------------------------------

CFG_PeripheralClockConfig(CFG_CLK_ADC,DISABLE);

CFG_PeripheralClockConfig(CFG_CLK_ADC,ENABLE);

/* ADC Configuration */

ADC_StructInit(&ADC_InitStructure);

ADC_InitStructure.ADC_Calibration = ADC_Calibration_ON;

ADC_InitStructure.ADC_CalibAverage = ADC_CalibAverage_Enable;

ADC_InitStructure.ADC_AutoClockOff = ADC_AutoClockOff_Disable ;

ADC_InitStructure.ADC_ConversionMode = ADC_ConversionMode_Scan ;

ADC_InitStructure.ADC_SamplingPrescaler = 0x0;

ADC_InitStructure.ADC_ConversionPrescaler = 0x2; // divided by 4

ADC_InitStructure.ADC_FirstChannel = ADC_CHANNEL0 ;

ADC_InitStructure.ADC_ChannelNumber = 16;

ADC_Init (&ADC_InitStructure);

ADC_Cmd(ENABLE);

ADC_ConversionCmd (ADC_ConversionStart);

--------------------------------------------------

Now ADC is up and running. It is sampling all the channels. And I can read current conversion value from the D0...D15 registers at any moment. Being happy with this I tried to enable DMA to trasfer data from specified channels to the memory buffer for the further analysis.

First I set up DMA:

-------------------------------------------------

CFG_PeripheralClockConfig(CFG_CLK_DMA3, DISABLE);

CFG_PeripheralClockConfig(CFG_CLK_DMA3, ENABLE);

DMA_InitStructure.DMA_Stream = DMA_Stream0;

DMA_InitStructure.DMA_SRC = DMA_SRC_NOT_INCR;

DMA_InitStructure.DMA_DST = DMA_DST_INCR;

DMA_InitStructure.DMA_SRCSize = DMA_SRCSize_HalfWord;

DMA_InitStructure.DMA_SRCBurst = DMA_SRCBurst_1Word;

DMA_InitStructure.DMA_DSTSize = DMA_DSTSize_HalfWord;

DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

DMA_InitStructure.DMA_Dir = DMA_Dir_PeriphSRC;

DMA_InitStructure.DMA_DSTBaseAddr = (u32) ADCBuffer;

DMA_DeInit(DMA3, DMA_Stream0);

DMA_AHBArbitrationConfig(DMA_Priority_High);

-------------------------------------

and prior to fetching channels I did the following:

-------------------------------------

ADC_ConversionCmd (ADC_ConversionStop);

while (ADC->CLR0 & 0x01); //still active

DMA_Cmd(DMA3, DMA_Stream0, DISABLE);

DMA_InitStructure.DMA_BufferSize= Ameas->noTotal;

DMA_Init(DMA3, &DMA_InitStructure);

ADC_DMAConfig(Ameas->DMA, ENABLE); //Ameas-DMA specifies channels 1, 5, 7 for example

DMA_Cmd(DMA3, DMA_Stream0, ENABLE);

ADC_DMACmd(ENABLE);

ADC_ConversionCmd (ADC_ConversionStart); //yield the uc, if needed, semaphore or similar

while (DMA_GetTerminalCounter(DMA3, DMA_Stream0)); //wait for end

DMA_Cmd(AnalogDMA, DMA_Stream0, DISABLE);

ADC_DMACmd(DISABLE);

ADC_DMAConfig(0xFFFF, DISABLE);

----------------------------------------------

So as I understood, DMA should get channel 1, 5, 7 results from the ADC when ready and transfer to memory. Target was to get memory buffer filled like:

ch1 result 0

ch5 result 0

ch7 result 0

ch1 result 1

ch5 result 1

ch7 result 1

etc.

But it does not work that way. After investigating examples from the st library (BSPI example) I noticed that source address for the DMA has to be specified as well (even if DMA3 stream 0 is kind of assinged to ADC). As my source address was 0 and not incrementing DMA filled the buffer with 0x0F (which is the content of memory region 0 according to the hex file).

So my question is. How is it possible to trasfer not sequential channels to memory with the help of DMA? With sequential channels I could use cirular buffer and incrementing source address. But even then there are unused memory regions between D0..D15 registers. So I have to read 32 bits in and 32 out, which is the waste of memory (as only 10 bits are of interest)? And as needed channels vary, I have to fetch all 16 channels with 32 bit all the time? But whats the reason of DMAenable bits in ADC then? Whats the point of being able to enable DMA for channel 1, 5, 7 if there is no way to use DMA like that? Could you please help me out with this issue.

Thank you in advance,

Madis

planeetmaa
Associate II
Posted on February 23, 2007 at 07:15

Hello!

I tested different things and gave up using DMA. What I do is trigger single shot chain conversion now. I.e. if I need data from channels 1 5 and 7 I trigger as many single shot chain conversions from channel 1 to 7 as needed and save data where needed. But then another problem raised.

Before I had continuos conversion going on for all the channels all the time. And the conversion results where ok. I.e. mathed to the actual values measured by multimeter. But now the result depends of how long channel I set up to convert. If I set channel 0 as first channel and number on channel to convert to 2, channel 0 result is 130, for example. If I set number of channels to 10, I get 300. And in continuous conversion mode (conversion constantly running round and round) I get 400, which is the correct result. While performing 10 single shot chain converisions from channels 0 to 1 the trendline is rising. First result is 130 and last about 270.

It seems to me that the ADC module is kind of ''warming up''. Could you please help me with this. Is it normal behaviour of the ADC?

thanks,

Madis