这里使用ADC1联动DMA1, 开启半传输中断、传输中断。debug时,dma也一直在工作,所以半传输中断、传输中断会同时生效。
1. adc1使用了DMA1_Stream0,Instance表示如下
一个DMA数据流中断标志占6个bit(在DMA_LISR)。Stream0 :hdma->StreamIndex=0,Stream1:hdma->StreamIndex=6
DMA_Base_Registers *regs_dma = (DMA_Base_Registers *)hdma->StreamBaseAddress;
tmpisr_dma = regs_dma->ISR;
tmpisr_dma表示
(hdma->StreamIndex & 0x1FU) 保证在0~31之间。
DMA_FLAG_TEIF0_4 ((uint32_t)0x00000008U)
2. 代码
/**
* @brief Handles DMA interrupt request.
* @param hdma: pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA Stream.
* @retval None
*/
void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma)
{
uint32_t tmpisr_dma, tmpisr_bdma;
uint32_t ccr_reg;
__IO uint32_t count = 0U;
uint32_t timeout = SystemCoreClock / 9600U;
/* calculate DMA base and stream number */
DMA_Base_Registers *regs_dma = (DMA_Base_Registers *)hdma->StreamBaseAddress;
BDMA_Base_Registers *regs_bdma = (BDMA_Base_Registers *)hdma->StreamBaseAddress;
tmpisr_dma = regs_dma->ISR;
tmpisr_bdma = regs_bdma->ISR;
if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
{
//hdma->Instance = DMA1_Stream0 = 0x40020010
/* Transfer Error Interrupt management ***************************************/
if ((tmpisr_dma & (DMA_FLAG_TEIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U) //发生了Transfer error中断
{
//tmpisr_dma = DMA_LISR寄存器
//hdma->StreamIndex = 0
//DMA_FLAG_TEIF0_4 = ((uint32_t)0x00000008U)
//(hdma->StreamIndex & 0x1FU) 0~31之间
if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_TE) != 0U) //数据流x的传输错误中断使能,在DMA_SxCR
{
//DMA_IT_TE ((uint32_t)DMA_SxCR_TEIE)
/* Disable the transfer error interrupt */
((DMA_Stream_TypeDef *)hdma->Instance)->CR &= ~(DMA_IT_TE);
//停止数据流x的error中断
/* Clear the transfer error flag */
regs_dma->IFCR = DMA_FLAG_TEIF0_4 << (hdma->StreamIndex & 0x1FU);
//清数据流x的error标志
/* Update error code */
hdma->ErrorCode |= HAL_DMA_ERROR_TE;
}
}
/* FIFO Error Interrupt management ******************************************/
if ((tmpisr_dma & (DMA_FLAG_FEIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U) //发生了FIFI error中断
{
//DMA_FLAG_FEIF0_4 = ((uint32_t)0x00000001U)
if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_FE) != 0U) //数据流x的FIFO错误中断使能,在DMA_DxFCR
{
/* Clear the FIFO error flag */
regs_dma->IFCR = DMA_FLAG_FEIF0_4 << (hdma->StreamIndex & 0x1FU);
//清数据流x的FIFO error标志
/* Update error code */
hdma->ErrorCode |= HAL_DMA_ERROR_FE;
}
}
/* Direct Mode Error Interrupt management ***********************************/
if ((tmpisr_dma & (DMA_FLAG_DMEIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U) //发生了Direct Mode Error中断
{
//DMA_FLAG_DMEIF0_4 = ((uint32_t)0x00000004U) DMEIE
if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_DME) != 0U) //直接模式错误中断使能,在DMA_SxCR
{
/* Clear the direct mode error flag */
regs_dma->IFCR = DMA_FLAG_DMEIF0_4 << (hdma->StreamIndex & 0x1FU);
//清数据流x的Direct error标志
/* Update error code */
hdma->ErrorCode |= HAL_DMA_ERROR_DME;
}
}
/* Half Transfer Complete Interrupt management ******************************/
if ((tmpisr_dma & (DMA_FLAG_HTIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U) //发生了半传输中断
{
if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_HT) != 0U) //半传输中断使能,在DMA_SxCR
{
//DMA_IT_HT ((uint32_t)DMA_SxCR_HTIE)
/* Clear the half transfer complete flag */
regs_dma->IFCR = DMA_FLAG_HTIF0_4 << (hdma->StreamIndex & 0x1FU); //清半传输中断标志
/* Multi_Buffering mode enabled */
if(((((DMA_Stream_TypeDef *)hdma->Instance)->CR) & (uint32_t)(DMA_SxCR_DBM)) != 0U)//双缓存开启,代码没开启
{
/* Current memory buffer used is Memory 0 */
if((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_CT) == 0U)
{
if(hdma->XferHalfCpltCallback != NULL)
{
/* Half transfer callback */
hdma->XferHalfCpltCallback(hdma);
}
}
/* Current memory buffer used is Memory 1 */
else
{
if(hdma->XferM1HalfCpltCallback != NULL)
{
/* Half transfer callback */
hdma->XferM1HalfCpltCallback(hdma);
}
}
}
else
{
/* Disable the half transfer interrupt if the DMA mode is not CIRCULAR */
if((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_CIRC) == 0U) //循环模式,则清半传输中断
{
/* Disable the half transfer interrupt */
((DMA_Stream_TypeDef *)hdma->Instance)->CR &= ~(DMA_IT_HT);
}
if(hdma->XferHalfCpltCallback != NULL) //回调函数不为空,则调用回调函数
{
/* Half transfer callback */
hdma->XferHalfCpltCallback(hdma); //半传输中断,循环模式下,就只调用了这行
//HAL_ADC_Start_DMA() hadc->DMA_Handle->XferHalfCpltCallback = ADC_DMAHalfConvCplt;
}
}
}
}
/* Transfer Complete Interrupt management ***********************************/
if ((tmpisr_dma & (DMA_FLAG_TCIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U) //发生了传输中断
{
if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_TC) != 0U) //传输中断使能,在DMA_SxCR
{
/* Clear the transfer complete flag */
regs_dma->IFCR = DMA_FLAG_TCIF0_4 << (hdma->StreamIndex & 0x1FU); //清传输中断标志
if(HAL_DMA_STATE_ABORT == hdma->State) //HAL_DMA_Abort_IT() hdma->State=HAL_DMA_STATE_ABORT,手动关闭DMA中断,我的代码没用到
{
/* Disable all the transfer interrupts */
((DMA_Stream_TypeDef *)hdma->Instance)->CR &= ~(DMA_IT_TC | DMA_IT_TE | DMA_IT_DME);
//清传输完成、传输错误、直接模式错误中断使能标志
((DMA_Stream_TypeDef *)hdma->Instance)->FCR &= ~(DMA_IT_FE);
//清FIFO错误中断使能标志
if((hdma->XferHalfCpltCallback != NULL) || (hdma->XferM1HalfCpltCallback != NULL))
{
((DMA_Stream_TypeDef *)hdma->Instance)->CR &= ~(DMA_IT_HT);
}
/* Clear all interrupt flags at correct offset within the register */
regs_dma->IFCR = 0x3FUL << (hdma->StreamIndex & 0x1FU);
/* Process Unlocked */
__HAL_UNLOCK(hdma);
/* Change the DMA state */
hdma->State = HAL_DMA_STATE_READY;
if(hdma->XferAbortCallback != NULL)
{
hdma->XferAbortCallback(hdma);
}
return;
}
if(((((DMA_Stream_TypeDef *)hdma->Instance)->CR) & (uint32_t)(DMA_SxCR_DBM)) != 0U) //双缓存开启,我的代码没用到
{
/* Current memory buffer used is Memory 0 */
if((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_CT) == 0U)
{
if(hdma->XferM1CpltCallback != NULL)
{
/* Transfer complete Callback for memory1 */
hdma->XferM1CpltCallback(hdma);
}
}
/* Current memory buffer used is Memory 1 */
else
{
if(hdma->XferCpltCallback != NULL)
{
/* Transfer complete Callback for memory0 */
hdma->XferCpltCallback(hdma);
}
}
}
/* Disable the transfer complete interrupt if the DMA mode is not CIRCULAR */
else
{
if((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_CIRC) == 0U) //循环模式没开
{
/* Disable the transfer complete interrupt */
((DMA_Stream_TypeDef *)hdma->Instance)->CR &= ~(DMA_IT_TC); //清传输完成中断
/* Process Unlocked */
__HAL_UNLOCK(hdma);
/* Change the DMA state */
hdma->State = HAL_DMA_STATE_READY;
}
if(hdma->XferCpltCallback != NULL)
{
/* Transfer complete callback */
hdma->XferCpltCallback(hdma); //传输中断,循环模式下,就只调用了这行
// HAL_ADC_Start_DMA() hadc->DMA_Handle->XferCpltCallback = ADC_DMAConvCplt;
}
}
}
}
/* manage error case */
if(hdma->ErrorCode != HAL_DMA_ERROR_NONE) //有DMA错误
{
if((hdma->ErrorCode & HAL_DMA_ERROR_TE) != 0U) //有DMA传输错误
{
hdma->State = HAL_DMA_STATE_ABORT;
/* Disable the stream */
__HAL_DMA_DISABLE(hdma); //关闭DMA,关闭一个DMA数据流
do
{
if (++count > timeout)
{
break;
}
}
while((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_EN) != 0U);//等待关闭
/* Process Unlocked */
__HAL_UNLOCK(hdma); //hdma开锁
if((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_EN) != 0U) //DMA数据流没关闭,出错
{
/* Change the DMA state to error if DMA disable fails */
hdma->State = HAL_DMA_STATE_ERROR;
}
else
{
/* Change the DMA state to Ready if DMA disable success */
hdma->State = HAL_DMA_STATE_READY;
}
}
if(hdma->XferErrorCallback != NULL)
{
/* Transfer error callback */
hdma->XferErrorCallback(hdma);
}
}
}
else if(IS_BDMA_CHANNEL_INSTANCE(hdma->Instance) != 0U) /* BDMA instance(s) */
{
ccr_reg = (((BDMA_Channel_TypeDef *)hdma->Instance)->CCR);
/* Half Transfer Complete Interrupt management ******************************/
if (((tmpisr_bdma & (BDMA_FLAG_HT0 << (hdma->StreamIndex & 0x1FU))) != 0U) && ((ccr_reg & BDMA_CCR_HTIE) != 0U))
{
/* Clear the half transfer complete flag */
regs_bdma->IFCR = (BDMA_ISR_HTIF0 << (hdma->StreamIndex & 0x1FU));
/* Disable the transfer complete interrupt if the DMA mode is Double Buffering */
if((ccr_reg & BDMA_CCR_DBM) != 0U)
{
/* Current memory buffer used is Memory 0 */
if((ccr_reg & BDMA_CCR_CT) == 0U)
{
if(hdma->XferM1HalfCpltCallback != NULL)
{
/* Half transfer Callback for Memory 1 */
hdma->XferM1HalfCpltCallback(hdma);
}
}
/* Current memory buffer used is Memory 1 */
else
{
if(hdma->XferHalfCpltCallback != NULL)
{
/* Half transfer Callback for Memory 0 */
hdma->XferHalfCpltCallback(hdma);
}
}
}
else
{
if((ccr_reg & BDMA_CCR_CIRC) == 0U)
{
/* Disable the half transfer interrupt */
__HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT);
}
/* DMA peripheral state is not updated in Half Transfer */
/* but in Transfer Complete case */
if(hdma->XferHalfCpltCallback != NULL)
{
/* Half transfer callback */
hdma->XferHalfCpltCallback(hdma);
}
}
}
/* Transfer Complete Interrupt management ***********************************/
else if (((tmpisr_bdma & (BDMA_FLAG_TC0 << (hdma->StreamIndex & 0x1FU))) != 0U) && ((ccr_reg & BDMA_CCR_TCIE) != 0U))
{
/* Clear the transfer complete flag */
regs_bdma->IFCR = (BDMA_ISR_TCIF0) << (hdma->StreamIndex & 0x1FU);
/* Disable the transfer complete interrupt if the DMA mode is Double Buffering */
if((ccr_reg & BDMA_CCR_DBM) != 0U)
{
/* Current memory buffer used is Memory 0 */
if((ccr_reg & BDMA_CCR_CT) == 0U)
{
if(hdma->XferM1CpltCallback != NULL)
{
/* Transfer complete Callback for Memory 1 */
hdma->XferM1CpltCallback(hdma);
}
}
/* Current memory buffer used is Memory 1 */
else
{
if(hdma->XferCpltCallback != NULL)
{
/* Transfer complete Callback for Memory 0 */
hdma->XferCpltCallback(hdma);
}
}
}
else
{
if((ccr_reg & BDMA_CCR_CIRC) == 0U)
{
/* Disable the transfer complete and error interrupt, if the DMA mode is not CIRCULAR */
__HAL_DMA_DISABLE_IT(hdma, DMA_IT_TE | DMA_IT_TC);
/* Process Unlocked */
__HAL_UNLOCK(hdma);
/* Change the DMA state */
hdma->State = HAL_DMA_STATE_READY;
}
if(hdma->XferCpltCallback != NULL)
{
/* Transfer complete callback */
hdma->XferCpltCallback(hdma);
}
}
}
/* Transfer Error Interrupt management **************************************/
else if (((tmpisr_bdma & (BDMA_FLAG_TE0 << (hdma->StreamIndex & 0x1FU))) != 0U) && ((ccr_reg & BDMA_CCR_TEIE) != 0U))
{
/* When a DMA transfer error occurs */
/* A hardware clear of its EN bits is performed */
/* Disable ALL DMA IT */
__HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
/* Clear all flags */
regs_bdma->IFCR = (BDMA_ISR_GIF0) << (hdma->StreamIndex & 0x1FU);
/* Update error code */
hdma->ErrorCode = HAL_DMA_ERROR_TE;
/* Process Unlocked */
__HAL_UNLOCK(hdma);
/* Change the DMA state */
hdma->State = HAL_DMA_STATE_READY;
if (hdma->XferErrorCallback != NULL)
{
/* Transfer error callback */
hdma->XferErrorCallback(hdma);
}
}
else
{
/* Nothing To Do */
}
}
else
{
/* Nothing To Do */
}
}
/**
* @brief DMA transfer complete callback.
* @param hdma pointer to DMA handle.
* @retval None
*/
void ADC_DMAConvCplt(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 ((hadc->State & (HAL_ADC_STATE_ERROR_INTERNAL | HAL_ADC_STATE_ERROR_DMA)) == 0UL)
{
/* Set ADC state */
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 */
/* to disable interruption. */
/* Is it the end of the regular sequence ? */
if ((hadc->Instance->ISR & ADC_FLAG_EOS) != 0UL) //系列转换完成
{
/* Are conversions software-triggered ? */
if (LL_ADC_REG_IsTriggerSourceSWStart(hadc->Instance) != 0UL) //软件触发?
{
/* Is CONT bit set ? */
if (READ_BIT(hadc->Instance->CFGR, ADC_CFGR_CONT) == 0UL)
{
/* CONT bit is not set, no more conversions expected */
CLEAR_BIT(hadc->State, HAL_ADC_STATE_REG_BUSY);
if ((hadc->State & HAL_ADC_STATE_INJ_BUSY) == 0UL)
{
SET_BIT(hadc->State, HAL_ADC_STATE_READY);
}
}
}
}
else
{
/* DMA End of Transfer interrupt was triggered but conversions sequence
is not over. If DMACFG is set to 0, conversions are stopped. */
if (READ_BIT(hadc->Instance->CFGR, ADC_CFGR_DMNGT) == 0UL) //常规数据仅存储再DR中
{
//DMNGT 数据管理配置
/* DMACFG bit is not set, conversions are stopped. */
CLEAR_BIT(hadc->State, HAL_ADC_STATE_REG_BUSY);
if ((hadc->State & HAL_ADC_STATE_INJ_BUSY) == 0UL)
{
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 ADC DMA error callback */
hadc->DMA_Handle->XferErrorCallback(hdma);
}
}
/**
* @brief Returns the DMA Stream base address depending on stream number
* @param hdma: pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA Stream.
* @retval Stream base address
*/
static uint32_t DMA_CalcBaseAndBitshift(DMA_HandleTypeDef *hdma)
{
if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
{
uint32_t stream_number = (((uint32_t)((uint32_t*)hdma->Instance) & 0xFFU) - 16U) / 24U;
/* lookup table for necessary bitshift of flags within status registers */
static const uint8_t flagBitshiftOffset[8U] = {0U, 6U, 16U, 22U, 0U, 6U, 16U, 22U};
hdma->StreamIndex = flagBitshiftOffset[stream_number & 0x7U];
if (stream_number > 3U)
{
/* return pointer to HISR and HIFCR */
hdma->StreamBaseAddress = (((uint32_t)((uint32_t*)hdma->Instance) & (uint32_t)(~0x3FFU)) + 4U);
}
else
{
/* return pointer to LISR and LIFCR */
hdma->StreamBaseAddress = ((uint32_t)((uint32_t*)hdma->Instance) & (uint32_t)(~0x3FFU));
}
}
else /* BDMA instance(s) */
{
/* return pointer to ISR and IFCR */
hdma->StreamBaseAddress = ((uint32_t)((uint32_t*)hdma->Instance) & (uint32_t)(~0xFFU));
}
return hdma->StreamBaseAddress;
}
}
3. HAL_ADC_Start_DMA 中 DMA模式下ADC溢出中断强制使能
/* With DMA, overrun event is always considered as an error even if
hadc->Init.Overrun is set to ADC_OVR_DATA_OVERWRITTEN. Therefore,
ADC_IT_OVR is enabled. */
__HAL_ADC_ENABLE_IT(hadc, ADC_IT_OVR); //原来是0,现在打开,DMA模式下ADC溢出中断强制使能
LL_ADC_REG_SetDataTransferMode(hadc->Instance, (uint32_t)hadc->Init.ConversionDataManagement);
4. 代码
/**
* @brief DMA error callback.
* @param hdma pointer to DMA handle.
* @retval None
*/
void ADC_DMAError(DMA_HandleTypeDef *hdma)
{
/* Retrieve ADC handle corresponding to current DMA handle */
ADC_HandleTypeDef *hadc = (ADC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
/* Set ADC state */
SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_DMA);
/* Set ADC error code to DMA error */
SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_DMA);
/* Error callback */
#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
hadc->ErrorCallback(hadc);
#else
HAL_ADC_ErrorCallback(hadc);
#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
}
/**
* @brief DMA transfer complete callback.
* @param hdma pointer to DMA handle.
* @retval None
*/
void ADC_DMAConvCplt(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 ((hadc->State & (HAL_ADC_STATE_ERROR_INTERNAL | HAL_ADC_STATE_ERROR_DMA)) == 0UL)
//ADC_DMAError() 执行完之后HAL_ADC_STATE_ERROR_DMA
{
/* Set ADC state */
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 */
/* to disable interruption. */
/* Is it the end of the regular sequence ? */
if ((hadc->Instance->ISR & ADC_FLAG_EOS) != 0UL)
{
/* Are conversions software-triggered ? */
if (LL_ADC_REG_IsTriggerSourceSWStart(hadc->Instance) != 0UL)
{
/* Is CONT bit set ? */
if (READ_BIT(hadc->Instance->CFGR, ADC_CFGR_CONT) == 0UL)
{
/* CONT bit is not set, no more conversions expected */
CLEAR_BIT(hadc->State, HAL_ADC_STATE_REG_BUSY);
if ((hadc->State & HAL_ADC_STATE_INJ_BUSY) == 0UL)
{
SET_BIT(hadc->State, HAL_ADC_STATE_READY);
}
}
}
}
else
{
/* DMA End of Transfer interrupt was triggered but conversions sequence
is not over. If DMACFG is set to 0, conversions are stopped. */
if (READ_BIT(hadc->Instance->CFGR, ADC_CFGR_DMNGT) == 0UL)
{
/* DMACFG bit is not set, conversions are stopped. */
CLEAR_BIT(hadc->State, HAL_ADC_STATE_REG_BUSY);
if ((hadc->State & HAL_ADC_STATE_INJ_BUSY) == 0UL)
{
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)
//HAL_ADC_STATE_ERROR_INTERNAL位,HAL_ADC_Init()、ADC_Enable()、ADC_Disable()之后可能
{
/* 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 ADC DMA error callback */
hadc->DMA_Handle->XferErrorCallback(hdma);
//有DMA错误,执行ADC_DMAError()之后,每次传输完成中断也不会调用用户回调,继续调用ADC_DMAError()
}
}
}
}
/**
* @brief DMA half transfer complete callback.
* @param hdma pointer to DMA handle.
* @retval None
*/
void ADC_DMAHalfConvCplt(DMA_HandleTypeDef *hdma)
{
/* Retrieve ADC handle corresponding to current DMA handle */
ADC_HandleTypeDef *hadc = (ADC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
/* Half conversion callback */
#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
hadc->ConvHalfCpltCallback(hadc);
#else
HAL_ADC_ConvHalfCpltCallback(hadc);
#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
}
/**
* @brief ADC error callback in non-blocking mode
* (ADC conversion with interruption or transfer by DMA).
* @note In case of error due to overrun when using ADC with DMA transfer
* (HAL ADC handle parameter "ErrorCode" to state "HAL_ADC_ERROR_OVR"):
* - Reinitialize the DMA using function "HAL_ADC_Stop_DMA()".
* - If needed, restart a new ADC conversion using function
* "HAL_ADC_Start_DMA()"
* (this function is also clearing overrun flag)
* @param hadc ADC handle
* @retval None
*/
__weak void HAL_ADC_ErrorCallback(ADC_HandleTypeDef *hadc)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(hadc);
/* NOTE : This function should not be modified. When the callback is needed,
function HAL_ADC_ErrorCallback must be implemented in the user file.
*/
}