/** * @brief Poll for injected conversion complete * @param hadc: pointer to a ADC_HandleTypeDef structure that contains * the configuration information for the specified ADC. * @param Timeout: Timeout value in millisecond. * @retval HAL status */ HAL_StatusTypeDef HAL_ADCEx_InjectedPollForConversion(ADC_HandleTypeDef* hadc, uint32_t Timeout) { uint32_t tickstart = 0U; /* Get tick */ tickstart = HAL_GetTick(); /* Check End of conversion flag */ while(!(__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_JEOC))) { /* Check for the Timeout */ if(Timeout != HAL_MAX_DELAY) { if((Timeout == 0U)||((HAL_GetTick() - tickstart ) > Timeout)) { hadc->State= HAL_ADC_STATE_TIMEOUT; /* Process unlocked */ __HAL_UNLOCK(hadc); return HAL_TIMEOUT; } } } /* Clear injected group conversion flag */ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_JSTRT | ADC_FLAG_JEOC); /* Update ADC state machine */ SET_BIT(hadc->State, HAL_ADC_STATE_INJ_EOC); /* Determine whether any further conversion upcoming on group injected */ /* 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_INJECTED(hadc) && (HAL_IS_BIT_CLR(hadc->Instance->JSQR, ADC_JSQR_JL) || HAL_IS_BIT_CLR(hadc->Instance->CR2, ADC_CR2_EOCS) ) && (HAL_IS_BIT_CLR(hadc->Instance->CR1, ADC_CR1_JAUTO) && (ADC_IS_SOFTWARE_START_REGULAR(hadc) && (hadc->Init.ContinuousConvMode == DISABLE) ) ) ) { /* Set ADC state */ CLEAR_BIT(hadc->State, HAL_ADC_STATE_INJ_BUSY); if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_REG_BUSY)) { SET_BIT(hadc->State, HAL_ADC_STATE_READY); } } /* Return ADC state */ return HAL_OK; }
/** * @brief DMA transfer complete callback. * @param hdma: pointer to a DMA_HandleTypeDef structure that contains * the configuration information for the specified DMA module. * @retval None */ static void ADC_MultiModeDMAConvCplt(DMA_HandleTypeDef *hdma) { /* Retrieve ADC handle corresponding to current DMA handle */ ADC_HandleTypeDef* hadc = ( ADC_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; /* 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 */ HAL_ADC_ConvCpltCallback(hadc); } else { /* Call DMA error callback */ hadc->DMA_Handle->XferErrorCallback(hdma); } }
/** * @brief Enables ADC, starts conversion of regular group and transfers result * through DMA. * Multimode must have been previously configured using * HAL_ADCEx_MultiModeConfigChannel() function. * Interruptions enabled in this function: * - DMA transfer complete * - DMA half transfer * Each of these interruptions has its dedicated callback function. * @note: On STM32F1 devices, ADC slave regular group must be configured * with conversion trigger ADC_SOFTWARE_START. * @note: ADC slave can be enabled preliminarily using single-mode * HAL_ADC_Start() function. * @param hadc: ADC handle of ADC master (handle of ADC slave must not be used) * @param pData: The destination Buffer address. * @param Length: The length of data to be transferred from ADC peripheral to memory. * @retval None */ HAL_StatusTypeDef HAL_ADCEx_MultiModeStart_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length) { HAL_StatusTypeDef tmp_hal_status = HAL_OK; ADC_HandleTypeDef tmphadcSlave; /* Check the parameters */ assert_param(IS_ADC_MULTIMODE_MASTER_INSTANCE(hadc->Instance)); assert_param(IS_FUNCTIONAL_STATE(hadc->Init.ContinuousConvMode)); /* Process locked */ __HAL_LOCK(hadc); /* Set a temporary handle of the ADC slave associated to the ADC master */ ADC_MULTI_SLAVE(hadc, &tmphadcSlave); /* On STM32F1 devices, ADC slave regular group must be configured with */ /* conversion trigger ADC_SOFTWARE_START. */ /* Note: External trigger of ADC slave must be enabled, it is already done */ /* into function "HAL_ADC_Init()". */ if ((tmphadcSlave.Instance == NULL) || (! ADC_IS_SOFTWARE_START_REGULAR(&tmphadcSlave)) ) { /* Update ADC state machine to error */ hadc->State = HAL_ADC_STATE_ERROR; /* Process unlocked */ __HAL_UNLOCK(hadc); return HAL_ERROR; } /* Enable the ADC peripherals: master and slave (in case if not already */ /* enabled previously) */ tmp_hal_status = ADC_Enable(hadc); if (tmp_hal_status != HAL_ERROR) { tmp_hal_status = ADC_Enable(&tmphadcSlave); } /* Start conversion all ADCs of multimode are effectively enabled */ if (tmp_hal_status != HAL_ERROR) { /* State machine update (ADC master): Check if an injected conversion is */ /* ongoing. */ if(hadc->State == HAL_ADC_STATE_BUSY_INJ) { /* Change ADC state */ hadc->State = HAL_ADC_STATE_BUSY_INJ_REG; } else { /* Change ADC state */ hadc->State = HAL_ADC_STATE_BUSY_REG; } /* Process unlocked */ /* Unlock before starting ADC conversions: in case of potential */ /* interruption, to let the process to ADC IRQ Handler. */ __HAL_UNLOCK(hadc); /* Set ADC error code to none */ ADC_CLEAR_ERRORCODE(hadc); /* Set the DMA transfer complete callback */ hadc->DMA_Handle->XferCpltCallback = ADC_DMAConvCplt; /* Set the DMA half transfer complete callback */ hadc->DMA_Handle->XferHalfCpltCallback = ADC_DMAHalfConvCplt; /* Set the DMA error callback */ hadc->DMA_Handle->XferErrorCallback = ADC_DMAError; /* Manage ADC and DMA start: ADC overrun interruption, DMA start, ADC */ /* start (in case of SW start): */ /* Clear regular group conversion flag and overrun flag */ /* (To ensure of no unknown state from potential previous ADC operations) */ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_EOC); /* Enable ADC DMA mode of ADC master */ SET_BIT(hadc->Instance->CR2, ADC_CR2_DMA); /* Start the DMA channel */ HAL_DMA_Start_IT(hadc->DMA_Handle, (uint32_t)&hadc->Instance->DR, (uint32_t)pData, Length); /* Start conversion of regular group if software start has been selected. */ /* If external trigger has been selected, conversion will start at next */ /* trigger event. */ /* Note: Alternate trigger for single conversion could be to force an */ /* additional set of bit ADON "hadc->Instance->CR2 |= ADC_CR2_ADON;"*/ if (ADC_IS_SOFTWARE_START_REGULAR(hadc)) { /* Start ADC conversion on regular group with SW start */ SET_BIT(hadc->Instance->CR2, (ADC_CR2_SWSTART | ADC_CR2_EXTTRIG)); } else { /* Start ADC conversion on regular group with external trigger */ SET_BIT(hadc->Instance->CR2, ADC_CR2_EXTTRIG); } } else { /* Process unlocked */ __HAL_UNLOCK(hadc); } /* Return function status */ return tmp_hal_status; }