问题1:DMA采用半字传输16位ADC值,用于存储ADC数据的数组一定是采集数的两倍,否则会产生ADC溢出的错误中断HAL_ADC_ErrorCallback,从而无法进入ADC采集完成中断HAL_ADC_ConvCpltCallback。具体为什么是两倍,网上有很多解释,有兴趣的可以去查一下。
问题2:在使用ADC+DMA采集的时候突然发现一个奇怪的现象,就是只要在程序的任何一个地方再申请一个全局变量,ADC就会出现错误中断HAL_ADC_ErrorCallback。最后发现程序没有什么问题,就怀疑和初始化顺序相关,然后就使用STM32CUBEMX配置了一下ADC+DMA,看一下配置出来的初始化顺序,然后改成和CUBEMX配置顺序一样的,这个问题就解决了。
void ADC_Init(void)
{
ADC_ChannelConfTypeDef sConfig = {0};
AdcHandle.Instance = ADC1;
AdcHandle.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV2;
AdcHandle.Init.Resolution = ADC_RESOLUTION_16B;
AdcHandle.Init.ScanConvMode = ADC_SCAN_ENABLE;
AdcHandle.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
AdcHandle.Init.LowPowerAutoWait = DISABLE;
AdcHandle.Init.ContinuousConvMode = ENABLE;
AdcHandle.Init.NbrOfConversion = 3;
AdcHandle.Init.DiscontinuousConvMode = DISABLE;
AdcHandle.Init.NbrOfDiscConversion = 1;
AdcHandle.Init.ExternalTrigConv = ADC_SOFTWARE_START;
AdcHandle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
AdcHandle.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR;
AdcHandle.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
AdcHandle.Init.OversamplingMode = DISABLE; /* 禁止过采样 */
/* 初始化 ADC */
if (HAL_ADC_Init(&AdcHandle) != HAL_OK)
{
}
/* 校准 ADC,采用偏移校准 */
if (HAL_ADCEx_Calibration_Start(&AdcHandle, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED) != HAL_OK)
{
}
/*黄灯对应采集通道*/
sConfig.Channel = ADC_CHANNEL_3; /* 配置使用的 ADC 通道 */
sConfig.Rank = ADC_REGULAR_RANK_1; /* 采样序列里的第 1 个 */
sConfig.SamplingTime = ADC_SAMPLETIME_387CYCLES_5; /* 采样周期 */
sConfig.SingleDiff = ADC_SINGLE_ENDED; /* 单端输入 */
sConfig.OffsetNumber = ADC_OFFSET_NONE; /* 无偏移 */
sConfig.Offset = 0; /* 无偏移的情况下,此参数忽略 */
sConfig.OffsetRightShift = DISABLE; /* 禁止右移 */
sConfig.OffsetSignedSaturation = DISABLE; /* 禁止有符号饱和 */
HAL_ADC_ConfigChannel(&AdcHandle, &sConfig);
sConfig.Channel = ADC_CHANNEL_7; /* 配置使用的 ADC 通道 */
sConfig.Rank = ADC_REGULAR_RANK_2; /* 采样序列里的第 1 个 */
HAL_ADC_ConfigChannel(&AdcHandle, &sConfig);
sConfig.Channel = ADC_CHANNEL_4; /* 配置使用的 ADC 通道 */
sConfig.Rank = ADC_REGULAR_RANK_3; /* 采样序列里的第 1 个 */
HAL_ADC_ConfigChannel(&AdcHandle, &sConfig);
sConfig.Channel = ADC_CHANNEL_9; /* 配置使用的 ADC 通道 */
sConfig.Rank = ADC_REGULAR_RANK_4; /* 采样序列里的第 1 个 */
HAL_ADC_ConfigChannel(&AdcHandle, &sConfig);
/* 启动 ADC 的 DMA 方式传输 */
if (HAL_ADC_Start_DMA(&AdcHandle, (uint32_t*)adc_buf, 3) != HAL_OK)
{
}
}
void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(adcHandle->Instance==ADC1)
{
/* ADC1 clock enable */
__HAL_RCC_ADC12_CLK_ENABLE();
__HAL_RCC_DMA1_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_4|GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
ADC1DMA_Handler.Instance = DMA1_Stream1;
ADC1DMA_Handler.Init.Request = DMA_REQUEST_ADC1;
ADC1DMA_Handler.Init.Direction = DMA_PERIPH_TO_MEMORY;
ADC1DMA_Handler.Init.PeriphInc = DMA_PINC_DISABLE;
ADC1DMA_Handler.Init.MemInc = DMA_MINC_ENABLE;
ADC1DMA_Handler.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
ADC1DMA_Handler.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
ADC1DMA_Handler.Init.Mode = DMA_CIRCULAR;
ADC1DMA_Handler.Init.Priority = DMA_PRIORITY_LOW;
ADC1DMA_Handler.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
ADC1DMA_Handler.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
ADC1DMA_Handler.Init.MemBurst = DMA_MBURST_SINGLE;
ADC1DMA_Handler.Init.PeriphBurst = DMA_PBURST_SINGLE;
if(HAL_DMA_Init(&ADC1DMA_Handler) != HAL_OK)
{
}
__HAL_LINKDMA(&AdcHandle, DMA_Handle, ADC1DMA_Handler);
/* DMA interrupt init */
/* DMA1_Stream0_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);
}
}
void HAL_ADC_MspDeInit(ADC_HandleTypeDef* adcHandle)
{
if(adcHandle->Instance==ADC1)
{
/* Peripheral clock disable */
__HAL_RCC_ADC12_CLK_DISABLE();
__HAL_RCC_DMA1_CLK_DISABLE();
HAL_GPIO_DeInit(GPIOC, GPIO_PIN_0|GPIO_PIN_4|GPIO_PIN_5);
}
}
void DMA1_Stream1_IRQHandler(void)
{
HAL_DMA_IRQHandler(&ADC1DMA_Handler);
}
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle)
{
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)