2022-01-31 03:31 AM
Hi!!
I am using a STM32F4 Discovery board. I am using the ADC1 and ADC2, both with DMA. I need the conditional to know which ADC was the one that finished reading data. I tried if(hadc->Instance == ADC1) but it only works when DMA is not used.
Could you help me to get the identifier of the ADC when using DMA?
2022-01-31 04:30 AM
hello
first i think you should be aware of some thing like configuration
these are the Steps to configure the ADC in the DMA mode.
1. Enable ADC and GPIO clock
2. Set the prescalar in the Common Control Register (CCR)
3. Set the Scan Mode and Resolution in the Control Register 1 (CR1)
4. Set the Continuous Conversion, EOC, and Data Alignment in Control Reg 2 (CR2)
5. Set the Sampling Time for the channels in ADC_SMPRx
6. Set the Regular channel sequence length in ADC_SQR1
7. Set the Respective GPIO PINs in the Analog Mode
2022-01-31 06:06 AM
Hi @LSoll.1 ,
Can you describe more the context of your issue ?
Do you mean the ADC instance in IRQ handler callback function ?
If yes, this is a solution (same as you mentionned):
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
if(hadc->Instance == ADC1)
{
...
}
else /* if(hadc->Instance == ADC2) */
{
...
}
}
Best regards
Philippe
2022-01-31 06:26 AM
Hello, I am using the falling edge of TIM8 to launch the conversion of ADC1, once the conversion is finished the DMA transfers the data. That works fine, the problem is that I need to get the interrupt from ADC1 to accumulate the data that the DMA transferred and then average it.
This is the ADC configuration:
static void MX_ADC1_Init(void)
{
/* USER CODE BEGIN ADC1_Init 0 */
/* USER CODE END ADC1_Init 0 */
ADC_ChannelConfTypeDef sConfig = {0};
/* USER CODE BEGIN ADC1_Init 1 */
/* USER CODE END ADC1_Init 1 */
/** 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 = ENABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_FALLING;
hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T8_TRGO;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 3;
hadc1.Init.DMAContinuousRequests = ENABLE;
hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
/** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_4;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
This is the DMA configuration:
static void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA2_CLK_ENABLE();
/* DMA interrupt init */
/* DMA2_Stream0_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
}
To get the interrupt I was trying the following code:
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc) {
if (hadc->Instance == ADC1) {
}
}
That code works as long as DMA is not used. When enabling the DMA, I notice that the identifier changes when you enter this function
static void ADC_DMAConvCplt(DMA_HandleTypeDef *hdma)
{
/* Retrieve ADC handle corresponding to current DMA handle */
ADC_HandleTypeDef* hadc = ( ADC_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; //here change the identifier
/* Update state machine on conversion status if not in error state */
if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL | HAL_ADC_STATE_ERROR_DMA))
{
/* Update ADC state machine */
SET_BIT(hadc->State, HAL_ADC_STATE_REG_EOC);
/* Determine whether any further conversion upcoming on group regular */
/* by external trigger, continuous mode or scan sequence on going. */
/* Note: On STM32F4, there is no independent flag of end of sequence. */
/* The test of scan sequence on going is done either with scan */
/* sequence disabled or with end of conversion flag set to */
/* of end of sequence. */
if(ADC_IS_SOFTWARE_START_REGULAR(hadc) &&
(hadc->Init.ContinuousConvMode == DISABLE) &&
(HAL_IS_BIT_CLR(hadc->Instance->SQR1, ADC_SQR1_L) ||
HAL_IS_BIT_CLR(hadc->Instance->CR2, ADC_CR2_EOCS) ) )
{
/* Disable ADC end of single conversion interrupt on group regular */
/* Note: Overrun interrupt was enabled with EOC interrupt in */
/* HAL_ADC_Start_IT(), but is not disabled here because can be used */
/* by overrun IRQ process below. */
__HAL_ADC_DISABLE_IT(hadc, ADC_IT_EOC);
/* Set ADC state */
CLEAR_BIT(hadc->State, HAL_ADC_STATE_REG_BUSY);
if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_INJ_BUSY))
{
SET_BIT(hadc->State, HAL_ADC_STATE_READY);
}
}
/* Conversion complete callback */
#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
hadc->ConvCpltCallback(hadc);
#else
HAL_ADC_ConvCpltCallback(hadc);
#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
}
else /* DMA and-or internal error occurred */
{
if ((hadc->State & HAL_ADC_STATE_ERROR_INTERNAL) != 0UL)
{
/* Call HAL ADC Error Callback function */
#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
hadc->ErrorCallback(hadc);
#else
HAL_ADC_ErrorCallback(hadc);
#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
}
else
{
/* Call DMA error callback */
hadc->DMA_Handle->XferErrorCallback(hdma);
}
}
}
2022-01-31 06:56 AM
> I tried if(hadc->Instance == ADC1) but it only works when DMA is not used.
> ADC_HandleTypeDef* hadc = ( ADC_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; //here change the identifier
How would this work if DMA isn't used? The hdma structure wouldn't exist.
What does the value equal when DMA is used?
2022-01-31 07:10 AM
I understand that you only enter the ADC_DMAConvCplt() function when DMA is used, right? That's why it works if you don't use it.
After "ADC_HandleTypeDef* hadc = ( ADC_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent" the value of hadc->Instance is equal to 0xfff
2022-01-31 07:18 AM
Can you attach the full main.c file? Doesn't look like the DMA is being linked to the ADC.
Ensure DMA is initialized before ADC.
2022-01-31 07:24 AM
Agree with @TDK , You probably have a problem in the HAL handles usage of your application.
You have to take care about DMA handle: it is a static variable and must be different for each ADC.
For example:
static DMA_HandleTypeDef hdma_adc1;
static DMA_HandleTypeDef hdma_adc2;
...
hdma_adc1.Instance = DMA2_Stream0;
hdma_adc1.Init. ...
__HAL_LINKDMA(&hadc1, DMA_Handle, hdma_adc1);
...
...
hdma_adc2.Instance = DMA2_Stream2;
hdma_adc2.Init. ...
__HAL_LINKDMA(&hadc2, DMA_Handle, hdma_adc2);
...
2022-01-31 07:36 AM
2022-01-31 08:49 AM
Can you also attach file "..._hal_msp.c" ? This is where DMA configuration and handles link is done.