cancel
Showing results for 
Search instead for 
Did you mean: 

stm32f3 DISCOVERY ADC DMA INT PROBLEM

Damiano
Associate II
Posted on October 31, 2014 at 12:51

Hi,

i have a problem with the dma adc conversion, the values ​​of the conversion are correct but the interrupt is called only once. I would like to get an ongoing conversion. main.c


/* Includes ------------------------------------------------------------------*/

#include ''main.h''


#define ADC1_DR_Address ((uint32_t)0x50000040)

#define SIZE 4

#define CHANNEL 4


__IO uint16_t calibration_value = 0;

__IO uint32_t TimingDelay = 0;

bool
flag_ADCDMA_TransferComplete = 
false
;


void
Delay(__IO uint32_t nTime);

void
TimingDelay_Decrement(
void
);

void
ADC_Configure(
void
);



__IO uint16_t ADC_Val[4];

uint16_t temp[4];


/**

* @brief Main program.

* @param None

* @retval None

*/

int
main(
void
)

{ 

RCC_ClocksTypeDef RCC_Clocks;


/* SysTick end of count event each 10ms */

RCC_GetClocksFreq(&RCC_Clocks);

SysTick_Config(RCC_Clocks.HCLK_Frequency / 100); 

ADC_Configure();



while
(1)

{

//memcpy(&temp[0],ADC_Val,5); 


while
(flag_ADCDMA_TransferComplete == 
false
);

for
(uint8_t i=0; i<4; i++)

{

temp[i]=ADC_Val[i]/4;

} 

printf
(
''%d,%d,%d,%d\n\r''
,temp[0],temp[1],temp[2],temp[3]);

flag_ADCDMA_TransferComplete = 
false
;

}


}








void
ADC_Configure(
void
)

{

GPIO_InitTypeDef GPIO_InitStructure;

ADC_InitTypeDef ADC_InitStructure;

ADC_CommonInitTypeDef ADC_CommonInitStructure;

DMA_InitTypeDef DMA_InitStructure;

NVIC_InitTypeDef NVIC_InitStructure;



/* GPIOA GIPOF Periph clock enable */

/* Enable ADC1 clock */

/* DMA configuration */

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOF, ENABLE);

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ADC12, ENABLE);

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);


//------------------------------------------------------------------------


/* Configure ADC Channel7 as analog input */

/* ADC1 per:

* PA1 -> ADC1_IN2

* PA2 -> ADC1_IN3

* PA3 -> ADC1_IN4

* PF4 -> ADC1_IN5

*/

/* PA1 PA2 PA3 */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 ;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;

GPIO_Init(GPIOA, &GPIO_InitStructure);


/* PF4 */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 ;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;

GPIO_Init(GPIOF, &GPIO_InitStructure); 


//------------------------------------------------------------------------


/* Configure the ADC clock */

RCC_ADCCLKConfig(RCC_ADC12PLLCLK_Div2); 


ADC_StructInit(&ADC_InitStructure);


/* Calibration procedure */

ADC_VoltageRegulatorCmd(ADC1, ENABLE);


ADC_SelectCalibrationMode(ADC1, ADC_CalibrationMode_Single);

ADC_StartCalibration(ADC1);


ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; 

ADC_CommonInitStructure.ADC_Clock = ADC_Clock_AsynClkMode; 

ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; 

 //

ADC_CommonInitStructure.ADC_DMAMode = ADC_DMAMode_OneShot;

ADC_CommonInitStructure.ADC_DMAMode = ADC_DMAMode_Circular;

ADC_CommonInitStructure.ADC_TwoSamplingDelay = 0; 

ADC_CommonInit(ADC1, &ADC_CommonInitStructure);


while
(ADC_GetCalibrationStatus(ADC1) != RESET );

calibration_value = ADC_GetCalibrationValue(ADC1); 



ADC_InitStructure.ADC_ContinuousConvMode = ADC_ContinuousConvMode_Enable;

ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; 

ADC_InitStructure.ADC_ExternalTrigConvEvent = ADC_ExternalTrigConvEvent_0; 

ADC_InitStructure.ADC_ExternalTrigEventEdge = ADC_ExternalTrigEventEdge_None;

ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;

ADC_InitStructure.ADC_OverrunMode = ADC_OverrunMode_Disable; 

ADC_InitStructure.ADC_AutoInjMode = ADC_AutoInjec_Disable; 

ADC_InitStructure.ADC_NbrOfRegChannel = CHANNEL;

ADC_Init(ADC1, &ADC_InitStructure);


ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 1,ADC_SampleTime_19Cycles5);

ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 2,ADC_SampleTime_19Cycles5);

ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 3,ADC_SampleTime_19Cycles5);

ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 4,ADC_SampleTime_19Cycles5);


//------------------------------------------------------------------------


DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;

DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC_Val; 

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; 

DMA_InitStructure.DMA_BufferSize = SIZE;

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; 
// 16 bit

DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; 
// 16 bit 

//DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;

DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

DMA_InitStructure.DMA_Priority = DMA_Priority_High; 

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

DMA_Init(DMA1_Channel1, &DMA_InitStructure);


//------------------------------------------------------------------------


/* Enable DMA1 channel1 IRQ Channel */

NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);


/* Enable DMA1 Channel1 Transfer Complete interrupt */

DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE); 


//------------------------------------------------------------------------


// abilita il canale dma per ADC1

DMA_Cmd(DMA1_Channel1, ENABLE);

// abilita adc1 con dma

ADC_DMACmd(ADC1, ENABLE);


/* Enable ADC1 */

ADC_Cmd(ADC1, ENABLE);


/* wait for ADRDY */

while
(!ADC_GetFlagStatus(ADC1, ADC_FLAG_RDY));


/* Start ADC1 Software Conversion */

ADC_StartConversion(ADC1); 


}




/**

* @brief Inserts a delay time.

* @param nTime: specifies the delay time length, in 10 ms.

* @retval None

*/

void
Delay(__IO uint32_t nTime)

{

TimingDelay = nTime;


while
(TimingDelay != 0);

}


/**

* @brief Decrements the TimingDelay variable.

* @param None

* @retval None

*/

void
TimingDelay_Decrement(
void
)

{

if
(TimingDelay != 0x00)

{

TimingDelay--;

}

}

andstm32f30x_it.c


void
SysTick_Handler(
void
)

{

TimingDelay--;

}



/**

* @brief This function handles DMA Transfer Complete interrupt request.

* @param None

* @retval None

*/

void
DMA1_Channel1_IRQHandler(
void
)

{

DMA_ClearFlag(DMA1_IT_TC1);

flag_ADCDMA_TransferComplete = 
true
;

}

#adc #dma #discovery #board #int
3 REPLIES 3
Posted on October 31, 2014 at 16:13

DMA_ClearFlag(DMA1_IT_TC1);

// wrong function/syntax

void DMA1_Channel1_IRQHandler(void) // 5 Hz
{
/* Test on DMA1 Channel1 Transfer Complete interrupt */
if (DMA_GetITStatus(DMA1_IT_TC1))
{
/* Clear DMA1 Channel1 Transfer Complete pending bit */
DMA_ClearITPendingBit(DMA1_IT_TC1);
STM_EVAL_LEDToggle(LED3); // 2.5 Hz
}
}

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Damiano
Associate II
Posted on November 03, 2014 at 12:07

Hi Clive, thanks for the answer, my mistake ...

I corrected the routine, but the interrupt is only called once again. 

I was wrong in some settings?

declareupdate
Associate III
Posted on March 02, 2016 at 05:38

I had the same problem of the ADC conversion only happening once. Much digging yielded: 

ADC_DMAConfig(ADC1, ADC_DMAMode_Circular); //need this line 

I put it right after the ADC_RegularChannelConfig lines