STM32F407和STM32F103在HAL库使用的时候有较大的差别,同时407取消掉了ADC校准,在使用DMA进行多通道采集时需要打开DMA连续请求:hadc1.Init.DMAContinuousRequests = ENABLE;否则DMA传输的数组里面就只会有第一次传输的数据,再也不会增加了。
同时在实验过程中发现407的ADC精度貌似不是很准确,采样率越高,偏差越大。受到(http://www.openedv.com/forum.php?mod=viewthread&tid=51312)的启发,自己也进行了一点小小的实验。
ADC1的通道3在 ADCCLK=10.8MHz(8分频)的情况下,对通道3进行接地处理,数字稳定在0-1之间;对通道3接入高电平3.3v,数字稳定在4092;在2分频的情况下,ADCCLK=42MHz(2分频),对通道3进行接地处理,数字稳定在2-3之间;对通道3接入高电平3.3v,数字稳定在4092;
同时在实验过程中发现407的ADC精度貌似不是很准确,采样率越高,偏差越大。受到(http://www.openedv.com/forum.php?mod=viewthread&tid=51312)的启发,自己也进行了一点小小的实验。
ADC1的通道3在 ADCCLK=10.8MHz(8分频)的情况下,对通道3进行接地处理,数字稳定在0-1之间;对通道3接入高电平3.3v,数字稳定在4092;在2分频的情况下,ADCCLK=42MHz(2分频),对通道3进行接地处理,数字稳定在2-3之间;对通道3接入高电平3.3v,数字稳定在4092;
自己分析出现以上情况,可能是参考电压有问题或者本身板子的设计有问题,干扰太大。但是也没深究,希望对精度有更高要求的同志能进行较为深入的研究,给大家指条明路。
并且,在引脚悬空的情况下会出现数值在1040-1060之间的数值跳动,因此输入管脚请不要悬空处理!!!!!!!!!
下面贴一下ADC.C的信息 双通道进行DMA处理,第一通道接PA3,接受光敏电阻的信息,第二通道是单片机内部的温度通道。
#include "adc.h"
#include "gpio.h"
#include "dma.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;
/* ADC1 init function */
void MX_ADC1_Init(void)
{
ADC_ChannelConfTypeDef sConfig;
/**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_DIV2;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.ScanConvMode = ENABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 2;
hadc1.Init.DMAContinuousRequests = ENABLE;
hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_3;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
sConfig.Rank = 2;
sConfig.SamplingTime = ADC_SAMPLETIME_112CYCLES;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(adcHandle->Instance==ADC1)
{
/* USER CODE BEGIN ADC1_MspInit 0 */
/* USER CODE END ADC1_MspInit 0 */
/* ADC1 clock enable */
__HAL_RCC_ADC1_CLK_ENABLE();
/**ADC1 GPIO Configuration
PA3 ------> ADC1_IN3
*/
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* ADC1 DMA Init */
/* ADC1 Init */
hdma_adc1.Instance = DMA2_Stream0;
hdma_adc1.Init.Channel = DMA_CHANNEL_0;
hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hdma_adc1.Init.Mode = DMA_CIRCULAR;
hdma_adc1.Init.Priority = DMA_PRIORITY_LOW;
hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_adc1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
__HAL_LINKDMA(adcHandle,DMA_Handle,hdma_adc1);
/* USER CODE BEGIN ADC1_MspInit 1 */
/* USER CODE END ADC1_MspInit 1 */
}
}
void HAL_ADC_MspDeInit(ADC_HandleTypeDef* adcHandle)
{
if(adcHandle->Instance==ADC1)
{
/* USER CODE BEGIN ADC1_MspDeInit 0 */
/* USER CODE END ADC1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_ADC1_CLK_DISABLE();
/**ADC1 GPIO Configuration
PA3 ------> ADC1_IN3
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_3);
/* ADC1 DMA DeInit */
HAL_DMA_DeInit(adcHandle->DMA_Handle);
/* USER CODE BEGIN ADC1_MspDeInit 1 */
/* USER CODE END ADC1_MspDeInit 1 */
}
}
最后奉上源代码。
点击打开链接