2016-07-25 03:05 AM
Hello, I have a few question about ADC. I want to drive ADC through DMA. The problem is that when I choose more than 6 samples I cannot enter in HAL_ADC_ConvCpltCallback. My second question is how to set the time to fill the array
static void hw_adc_init_channel(U8 adc, U8 channel)
{
GPIO_InitTypeDef gpio_init; // Init gpio at analog mode
//Enables the AHB1 peripheral clock
__HAL_RCC_GPIOF_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
gpio_init.Pin = GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10; // Set analog input for adc 3, channel 4,5,6,7,8
gpio_init.Mode = GPIO_MODE_ANALOG;
gpio_init.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOF, &gpio_init);
gpio_init.Pin = GPIO_PIN_0; // Set analog input for adc 3, channel 0
gpio_init.Mode = GPIO_MODE_ANALOG;
gpio_init.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &gpio_init);
}
/*****************************************************************************/
/*****************************************************************************/
static void hw_adc_dma_init(ADC_HandleTypeDef* hadc3)
{
static DMA_HandleTypeDef hdma;
__HAL_RCC_DMA2_CLK_ENABLE();
hdma.Instance = DMA2_Stream0;
hdma.Init.Channel = DMA_CHANNEL_2;
hdma.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma.Init.PeriphInc = DMA_PINC_DISABLE;
hdma.Init.MemInc = DMA_MINC_ENABLE;
hdma.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hdma.Init.Mode = DMA_CIRCULAR;
hdma.Init.Priority = DMA_PRIORITY_MEDIUM;
hdma.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
hdma.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL;
hdma.Init.MemBurst = DMA_MBURST_SINGLE;
hdma.Init.PeriphBurst = DMA_PBURST_SINGLE;
HAL_DMA_Init(&hdma);
__HAL_LINKDMA(hadc3, DMA_Handle, hdma); // Associate init DMA handle to ADC DMA
// Set DMA priority
// When 2 interrupts have same preemption priority, then he one who has higher sub priority will be execute first.
// If both interrupts both have same preemption priority and sub priority, the one comes first will be execute first
HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
}
/*****************************************************************************/
/*****************************************************************************/
void hw_adc_3_init(ADC_INIT* _adc3)
{
ADC_ChannelConfTypeDef adc_channel_conf; // Config which channel will be active
// Enable the High Speed APB (APB2) peripheral clock for ADC3
__HAL_RCC_ADC3_CLK_ENABLE();
// Init ADC3 registers
hadc3.Instance = ADC3;
hadc3.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV2; // ADC prescaler, its common to all ADCs. PLCK div
hadc3.Init.ContinuousConvMode = ENABLE;
hadc3.Init.DMAContinuousRequests = ENABLE; // DMA continuous mode is enable
hadc3.Init.DataAlign = ADC_DATAALIGN_RIGHT; // Set data alignment
hadc3.Init.DiscontinuousConvMode = DISABLE; // Discontinuous mode is enabled
hadc3.Init.NbrOfDiscConversion = 0;
hadc3.Init.EOCSelection = DISABLE;
hadc3.Init.ExternalTrigConv = ADC_CR2_EXTSEL;
hadc3.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc3.Init.NbrOfConversion = adc_3->adc_channel_activation; // Select how many channels will be scanned
hadc3.Init.Resolution = ADC_RESOLUTION_8B; // Set resolution of the conversion of ADC. 12 bit -> minimum 15 ADC clock cycles
hadc3.Init.ScanConvMode = DISABLE; // ADC read only 1 channel, that with rank = 1 ..... (ADC can read with all 8 channel. Injected mode)
HAL_ADC_Init(&hadc3);
// Sequence of channel read
adc_channel_conf.Channel = ADC_CHANNEL_0;
adc_channel_conf.Rank = 1; // Specifies the rank in the regular group sequencer
adc_channel_conf.SamplingTime = adc_3->adc_sample_frequency; // Sample time individually for each channel
HAL_ADC_ConfigChannel(&hadc3, &adc_channel_conf);
adc_3 = _adc3;
hw_adc_init_channel(3, 1);
hw_adc_dma_init(&hadc3);
}
/*****************************************************************************/
/*****************************************************************************/
void hw_adc_3_start()
{
HAL_ADC_Start_DMA(&hadc3, (U32 *)&adc_convert_value[0], 20); // Length: The length of data to be transferred from ADC peripheral to memory.
}
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc3)
{
BSP_LED_Toggle(LED1);
adc_convert_value[0] = hadc3->Instance->DR;
}
/*****************************************************************************/
/*****************************************************************************/
void DMA2_Stream0_IRQHandler(void)
{
HAL_DMA_IRQHandler(hadc3.DMA_Handle);
}
#adc #stm32f746
2016-09-01 05:13 AM
Hello s.boris,
For the DMA process the values are automatically populated into the designated array. Due to this the following bit of code may be not doing what you want it to:void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc3)
{
BSP_LED_Toggle(LED1);
adc_convert_value[0] = hadc3->Instance->DR;
}
/*****************************************************************************/
/
For the ADC DMA operation, the code is more clearly explained in the following blog post.
http://tunizem.blogspot.com/2014/09/using-adc-with-dma-on-stmhtml
It helped clear up some of the configuration for me at least. Good luck!