cancel
Showing results for 
Search instead for 
Did you mean: 

ADC -> DMA with no libraries

dileptor
Associate II
Posted on December 06, 2011 at 00:55

Hi,

I'm trying to implement a sensor network. I know that I must use DMA to be able to work with multiple ADC channels. Since this is a school assignment, I'm not allowed to use any libraries.

For some reason I'm only able to read the first channel. The second one is constant zero. How do I even define that the ADC channel 3 is supposed to go to DMA channel 2 ?

Here's a snippet of my code:

[CODE]

int32_t temperature;  //globals

uint32_t degree;

void ADC_Configuration(void){

RCC->APB2RSTR |= ADC_RESET;        //reset

RCC->APB2RSTR &= ~ADC_RESET;    //cancel reset

ADC1->CR2       |= ADC_SWSTART;     //set start by SW

ADC1->SMPR1   |= ADC_SMP_16;    //sample 28.5 on channel 16

ADC1->SMPR2   |= ADC_SMP_3;        //sample 7.5 on channel 3

ADC1->SQR3      |= ADC_SQR;          //channel 16 first, channel 3 second

ADC1->CR2      |= ADC_CALIB_RST;    //reset calib,  ADON - start

ADC1->CR2      |= ADC_DMA_EN;    //DMA

while (ADC1->CR2 & 0x8);         //wait for ADC to reset calibration

ADC1->CR2      |= ADC_START_CALIB; //start calibration

while (ADC1->CR2 & ADC_START_CALIB); //wait for ADC to start calibration

ADC1->CR2      |= ADC_TSVREFE;  //TSVREFE, ADON start

//jeste treba udelat DMA

}

/*----------------------------------------------------------------------------

  DMA Configuration

 *----------------------------------------------------------------------------*/

void DMA_Configuration(void){

DMA1_Channel1->CPAR = (uint32_t)&(ADC1->DR);

DMA1_Channel1->CMAR = (uint32_t)&temperature;

DMA1_Channel1->CNDTR = 0x1;

DMA1_Channel1->CCR = 0x1A20;

DMA1_Channel1->CCR |= 0x1;

DMA1_Channel2->CPAR = (uint32_t)&(ADC1->DR);

DMA1_Channel2->CMAR = (uint32_t)&degree;

DMA1_Channel2->CNDTR = 0x1;

DMA1_Channel2->CCR = 0x1A20;

DMA1_Channel2->CCR |= 0x1;

}

int32_t ReadTemp(void){

     int32_t temp;

    uint32_t deg;

    int32_t v25 = 1738;

    int32_t avg_slope = 56;

    int32_t constant = 250000;

    int32_t magnify = 10000;

    //temp = (int32_t) degree;

    temp = (int32_t) temperature;  // THIS ONE WORKS, BUT IF I CHANGE IT TO DEGREE, IT BECOMES CONSTANTS ZERO

    if (temp == v25) return constant;

        temp = v25 - temp;

        temp = temp*magnify;

        temp =temp/avg_slope;

        temp = temp + constant;

        return temp;

}

int main (void) {

  int32_t    temper;

  float value;

    

  RCC_Configuration(); //note that I do send clk to ADC and DMA

  GPIO_Configuration();

  USART_Configuration();

  buffer_Init();                                  // init RX / TX buffers

  DMA_Configuration();

  ADC_Configuration();

 

  ADC1->CR2      |= ADC_SWST_EXTTRIG;                               

  temper = ReadTemp();                                 //clear the first measurement, which is always a bit off

  while (1) {                                     // Loop forever

    char string[7];    

        

    Delay(4000);

    ADC1->CR2      |= ADC_SWST_EXTTRIG;

      

    temper = ReadTemp();

    ADC1->CR2      |= 0x1;

    value = (float)temper;

    value = value/10000;

    snprintf(string, SIZE, ''%f'', value);

    SendString(string);

    SendChar(0xD);

    SendChar(0xA);

    Delay(4000);

    

  }

}

[/CODE]

Any help would be appreciated.
4 REPLIES 4
Posted on December 06, 2011 at 02:19

Any help would be appreciated.

You need to read the manual more thoroughly, especially if you're going to ignore the libraries. Your inability to use the library in your final code does not preclude you from examining all the examples and source code to understand what does and what does not work.

ADC1 is only EVER going to use DMA1.Channel1

To read multiple ADC channels, you need to set DMA to run cyclically across multiple memory locations into which it will store your variables. The size of that memory will be dictated by the number of ADC channels you plan on reading.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
dileptor
Associate II
Posted on December 06, 2011 at 10:48

>You need to read the manual more thoroughly, especially if you're going to ignore the libraries. Your inability to use the library in your final code does >not preclude you from examining all the examples and source code to understand what does and what does not work.

 

 

I've looked at some ADC + DMA samples using libraries, but it I wasn't able to find the libraries itself, so it was pretty useless. Could you provide me with a url to the libraries itself?

 

>To read multiple ADC channels, you need to set DMA to run cyclically across multiple memory locations into which it will store your variables. The size >of that memory will be dictated by the number of ADC channels you plan on reading.

 

 

So, should I only have one memory location and set memory auto increment in the DMA.CR ? And should I only use the DMA.channel1 ?

Now, considering that the sensors have different sample rates, wouldn't one of the channels store its reading more often than the other, filling more of the memory than expected?

Let's say I expect this behaviour:

Memory location = reading from ADC channel1

Memory location + 4 = reading from ADC channel2

...

...

Couldn't something like this happen ?

Memory location = reading from ADC channel1

Memory location + 4 = reading from ADC channel1 again

Memory location + 8 = reading from ADC channel2

...

...
Posted on December 06, 2011 at 16:10

Could you provide me with a url to the libraries itself?

 

 

http://www.st.com/internet/evalboard/product/250863.jsp

 

Design Support -> Firmware

 

 

So, should I only have one memory location and set memory auto increment in the DMA.CR ?

Yes, you'll need an array

And should I only use the DMA.channel1 ?

You really don't have much of a choice do you? According to the documentation I've read ADC1 is hardwired to DMA1.Channel1. If you have ADC3 that is hardwired to DMA2.Channel5

Now, considering that the sensors have different sample rates, wouldn't one of the channels store its reading more often than the other, filling more of the memory than expected?

 

Not sure how you'd handle that, but it sure sounds like fun. I'd guess you'd either have to use a larger array, if the ADC actually permits that kind of interleaving, or change the ADC and DMA configuration at each TC interrupt, or use ADC3/DMA2.

If you can do each ADC read on demand, perhaps you don't need DMA, and a simple state machine would suffice.

You'll really need to get your head around the documentation, to determine what is and what is not physically possible with the hardware you have chosen.

Documentation for STM32F100 series

http://www.st.com/internet/mcu/product/216844.jsp

Design Support -> Reference Manual

http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/REFERENCE_MANUAL/CD00246267.pdf

See table 54 on page 149
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
dileptor
Associate II
Posted on December 06, 2011 at 17:45

Thanks a lot,

I'll get to it and report back if I succeed.