How to enable ADC continuous mode with DMA?
Hello community,
I try to configure the ADC in continuous mode so it writes the converted values via DMA continuously into a memory address in background without triggering via software.
It should be possible with : ContinuousConvMode = ENABLE and ExternalTrigConv =ADC_SOFTWARE_START.
But the function HAL_ADC_Start_DMA reads only once, writes via DMA and then stops and isn't getting triggered continuously. According to HAL manual, the function HAL_ADC_Start_DMA seems to work only in single mode. How do I get the ADC and DMA run continuously in the background? Do I need a timer? I thought it shall be possible without special timers.
main.c:
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC1_Init();
uint16_t ADC_buf=0;
uint16_t ADC_poll=0;
//Start DMA stream
HAL_ADC_Start_DMA(&hadc1,(uint32_t*) &ADC_buf,2);
while(1){
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1,10);
ADC_poll=HAL_ADC_GetValue(&hadc1);
printf("DMA: %d \t Poll: %d\n",(int) ADC_buf, (int)ADC_poll);
HAL_ADC_Stop(&hadc1);
HAL_Delay(100);
.
.
.
static void MX_ADC1_Init(void)
{
ADC_ChannelConfTypeDef sConfig;
/**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.ExternalTrigConv =ADC_SOFTWARE_START ;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 2;
hadc1.Init.DMAContinuousRequests = ENABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_0;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
static void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA2_CLK_ENABLE();
/* DMA interrupt init */
hdma_adc1.Instance=DMA2_Stream0;
hdma_adc1.Init.Channel = DMA_CHANNEL_0;// Channel 0, Stream 0
hdma_adc1.Init.Direction=DMA_PERIPH_TO_MEMORY;
hdma_adc1.Init.PeriphInc=DMA_PINC_DISABLE;
hdma_adc1.Init.MemInc=DMA_MINC_DISABLE;
hdma_adc1.Init.PeriphDataAlignment=DMA_PDATAALIGN_HALFWORD;
hdma_adc1.Init.MemDataAlignment=DMA_MDATAALIGN_HALFWORD;
hdma_adc1.Init.Mode=DMA_CIRCULAR;
hdma_adc1.Init.Priority=DMA_PRIORITY_HIGH;
hdma_adc1.Init.FIFOMode=DMA_FIFOMODE_DISABLE;
hdma_adc1.Init.FIFOThreshold=DMA_FIFO_THRESHOLD_HALFFULL;
hdma_adc1.Init.MemBurst=DMA_MBURST_SINGLE;
hdma_adc1.Init.PeriphBurst=DMA_PBURST_SINGLE;
//Initialize DMA
if (HAL_DMA_Init(&hdma_adc1) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } ;
/* DMA2_Stream0_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
}stm32f7xx_it.c
void DMA2_Stream0_IRQHandler(void)
{
printf("Interrupted\n");
HAL_DMA_IRQHandler(&hdma_adc1);
}Prints out:
Initializing
Interrupted
DMA: 4095 Poll: 4034
DMA: 4095 Poll: 4032
DMA: 4095 Poll: 4095
DMA: 4095 Poll: 4041
DMA: 4095 Poll: 4095
...So DMA transfer runs only once. What am I doing / thinking wrong???
