2013-11-12 06:54 AM
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 withDAC_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 0DMA_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 channelsADC_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 !2013-11-14 04:10 AM
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.2013-11-14 09:23 AM
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...
2013-11-14 09:34 AM
You've implemented an HT handler, you never clear the TC. You are only doing 4 samples, use TC throughout.
2013-11-15 02:51 AM
Exact !
I replacedDMA_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.