cancel
Showing results for 
Search instead for 
Did you mean: 

DAC & ADC speed help

jean_prieur
Associate III
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 !

13 REPLIES 13
frankmeyer9
Associate II
Posted on November 14, 2013 at 13:10

void

 

Refresh_ADC_Values(

 

void

 

)

{

ADC_SoftwareStartConv(ADC1);

while

 

(ADC_GetSoftwareStartConvStatus(ADC1) != RESET){}

}

Is it normal ?

Yes, because actually, you are not interested in the status of the SWSTART flag.

Instead, try implementing an interrupt on the TC flag of the DMA.

jean_prieur
Associate III
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...
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
Up vote any posts that you find helpful, it shows what's working..
jean_prieur
Associate III
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.