Skip to main content
jean_prieur
Associate III
November 12, 2013
Question

DAC & ADC speed help

  • November 12, 2013
  • 13 replies
  • 1856 views
Posted on November 12, 2013 at 15:54

Hello,

I'm coding a real time system based on STM32F427 requiring a lot of ressources and using almost all peripherials (ADC, DAC, SPI, I2aC, USART, USB, SDIO).

This is why I want to reduce the ressource needs of my peripherials and especially the ADC and DAC.Theses analog I/Os don't have to be very fast (500 Hz max). I'm a newbie with microcontrolers, soI have two questions:

1) When I set the DAC output to a voltage with

DAC_SetChannel1Data(DAC_Align_12b_R, voltage);

the microcontroler set a voltage on his pin. But after it will not take ressources if I do nothing ? I mean, until I do not set another value, the DAC will nottake ressources of the uC ?

2) I config my ADC (ADC 1 & ADC2) to work with DMA and scanning 4 channels. But this operation is continuous and I don't know the sampling rate. I want to have the control and to ask for a sample when this is necessary. Is it possible ? For example ''GetOneAdcSample();'' My code is below:

void

ADC_Config(

void

)

{

// ADC init

ADC_CommonInitTypeDef ADC_CommonInitStructure;

// Set of the CLOCK for DMA2 + GPIOC + ADC1 + ADC2

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOC, ENABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2, ENABLE);

// Config of DMA2 (direct access memory) Stream0 channel0

DMA_InitTypeDef DMA_InitStructure;

DMA_InitStructure.DMA_Channel = DMA_Channel_0;

// USE CHANNEL 0

DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&TabADC;

// Save values in TabADC(4)

DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC_CCR_ADDRESS;

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;

DMA_InitStructure.DMA_BufferSize = 4;

// BUFFER SIZE (same size as TabADC)

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;

DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;

DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

DMA_InitStructure.DMA_Priority = DMA_Priority_High;

DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;

DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;

DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;

DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;

DMA_Init(DMA2_Stream0, &DMA_InitStructure);

DMA_Cmd(DMA2_Stream0, ENABLE);

// DMA2_Stream0 enable

// GPIO config pins C4 C4 A2 A3

GPIO_InitTypeDef GPIO_InitStructure;

// GPIOC

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN ;

GPIO_Init(GPIOC, &GPIO_InitStructure);

//GPIOA

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;

GPIO_Init(GPIOA, &GPIO_InitStructure);

// Init ADC ''Common''

ADC_CommonInitStructure.ADC_Mode = ADC_DualMode_RegSimult;

ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div8;

ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1;

ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles ;

ADC_CommonInit(&ADC_CommonInitStructure);

// Init ADC ''1'' channels 15, 3

ADC_InitTypeDef ADC_InitStructure;

ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;

ADC_InitStructure.ADC_ScanConvMode = ENABLE;

ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;

ADC_InitStructure.ADC_ExternalTrigConv = 0;

ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;

ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;

ADC_InitStructure.ADC_NbrOfConversion = 2;

// 2 conv because 2 channels

ADC_Init(ADC1, &ADC_InitStructure);

// ADC1 regular channels 15, 14 configuration

ADC_RegularChannelConfig(ADC1, ADC_Channel_15, 1, ADC_SampleTime_56Cycles);

ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 2, ADC_SampleTime_56Cycles);

// Init ADC ''2'' channels 14, 2

ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;

ADC_InitStructure.ADC_ScanConvMode = ENABLE;

ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;

ADC_InitStructure.ADC_ExternalTrigConv = 0;

ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;

ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;

ADC_InitStructure.ADC_NbrOfConversion = 2;

ADC_Init(ADC2, &ADC_InitStructure);

// ADC2 regular channels 1, 2 configuration

ADC_RegularChannelConfig(ADC2, ADC_Channel_3, 1, ADC_SampleTime_56Cycles);

ADC_RegularChannelConfig(ADC2, ADC_Channel_2, 2, ADC_SampleTime_56Cycles);

// Enable DMA request after last transfer (Multi-ADC mode)

ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE);

// Enable ADC1 and ADC2

ADC_Cmd(ADC1, ENABLE);

ADC_Cmd(ADC2, ENABLE);

// Start ADC1 Software Conversion

ADC_SoftwareStartConv(ADC1);

}

I hope I made it clear.

Thanks !

    This topic has been closed for replies.

    13 replies

    jean_prieur
    Associate III
    November 14, 2013
    Posted on November 14, 2013 at 18:23

    I implement an interrupt onDMA_IT_TC by adding:

    void
    ADC_Config(
    void
    )
    {
    .......
    /* Enable DMA Stream Half / Transfer Complete interrupt */
    DMA_ITConfig(DMA2_Stream0, DMA_IT_TC | DMA_IT_HT, ENABLE);
    .........
    NVIC_Configuration();
    }

    void
    NVIC_Configuration(
    void
    )
    {
    NVIC_InitTypeDef NVIC_InitStructure;
    // Enable the DMA Stream IRQ Channel
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
    NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream0_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    }
    void
    DMA2_Stream0_IRQHandler(
    void
    )
    {
    // Test on DMA Stream Half Transfer interrupt
    if
    (DMA_GetITStatus(DMA2_Stream0, DMA_IT_HTIF0))
    {
    // Clear DMA Stream Half Transfer interrupt pending bit
    DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_HTIF0);
    }
    }

    But with this method there is a problem: the soft freeze, it seems that the interrupDMA2_Stream0_IRQHandler is called in an infinite loop...
    Tesla DeLorean
    Guru
    November 14, 2013
    Posted on November 14, 2013 at 18:34

    You've implemented an HT handler, you never clear the TC. You are only doing 4 samples, use TC throughout.

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    jean_prieur
    Associate III
    November 15, 2013
    Posted on November 15, 2013 at 11:51

    Exact !

    I replaced

    DMA_ITConfig(DMA2_Stream0, DMA_IT_TC | DMA_IT_HT, ENABLE);

    by

    DMA_ITConfig(DMA2_Stream0, DMA_IT_HT, ENABLE);

    And now it works perfectly ! Thanks everybody.