STM32H实现ADC采集

实现参考STM32F7实现ADC采集(软件触发+轮询)

注意,在CubeMX中,void SystemClock_Config(void)多了如下代码:

  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
  PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_ADC|RCC_PERIPHCLK_CKPER;
  PeriphClkInitStruct.CkperClockSelection = RCC_CLKPSOURCE_HSE;
  PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_CLKP;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

查看HAL_RCCEx_PeriphCLKConfig函数中关于adc的部分:

 /*---------------------------- ADC configuration -------------------------------*/
  if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_ADC) == RCC_PERIPHCLK_ADC)
  {
    switch(PeriphClkInit->AdcClockSelection)
    {

    case RCC_ADCCLKSOURCE_PLL2: /* PLL2 is used as clock source for ADC*/

      ret = RCCEx_PLL2_Config(&(PeriphClkInit->PLL2),DIVIDER_P_UPDATE);

      /* ADC clock source configuration done later after clock selection check */
      break;

    case RCC_ADCCLKSOURCE_PLL3:  /* PLL3 is used as clock source for ADC*/
      ret = RCCEx_PLL3_Config(&(PeriphClkInit->PLL3),DIVIDER_R_UPDATE);

      /* ADC clock source configuration done later after clock selection check */
      break;

    case RCC_ADCCLKSOURCE_CLKP:
      /* HSI, HSE, or CSI oscillator is used as source of ADC clock */
      /* ADC clock source configuration done later after clock selection check */
      break;

    default:
      ret = HAL_ERROR;
      break;
    }

    if(ret == HAL_OK)
    {
      /* Set the source of ADC clock*/
      __HAL_RCC_ADC_CONFIG(PeriphClkInit->AdcClockSelection);
    }
    else
    {
      /* set overall return value */
      status = ret;
    }
  }

而实际上我们只需要在生成HAL_ADC_MspInit中添加一句核心的__HAL_RCC_ADC_CONFIG(RCC_ADCCLKSOURCE_CLKP);//ADC外设时钟选择就可以了。
ADC的时钟源有三个选项:

/** @defgroup RCCEx_ADC_Clock_Source  RCCEx ADC Clock Source
  * @{
  */
#define RCC_ADCCLKSOURCE_PLL2       ((uint32_t)0x00000000)
#define RCC_ADCCLKSOURCE_PLL3       RCC_D3CCIPR_ADCSEL_0
#define RCC_ADCCLKSOURCE_CLKP       RCC_D3CCIPR_ADCSEL_1

默认将采用RCC_ADCCLKSOURCE_PLL2,即400M的输入时钟,时钟太快,所以会导致ADC采集出来的数据不会有变化。
STM32H实现ADC采集_第1张图片

全部代码如下:

#include "adc.h"
#include "delay.h"	

ADC_HandleTypeDef hadc1;

static void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */

  /* USER CODE END Error_Handler_Debug */
}

//获得ADC值
//ch: 通道值 0~16,取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_16
//返回值:转换结果
u16 Get_Adc(u32 ch)   
{
	ADC_ChannelConfTypeDef ADC1_ChanConf;
	
	ADC1_ChanConf.Channel=ch;                                   //通道
	ADC1_ChanConf.Rank=ADC_REGULAR_RANK_1;                  	//1个序列
	ADC1_ChanConf.SamplingTime=ADC_SAMPLETIME_64CYCLES_5;      	//采样时间       
	ADC1_ChanConf.SingleDiff=ADC_SINGLE_ENDED;  				//单边采集          		
	ADC1_ChanConf.OffsetNumber=ADC_OFFSET_NONE;             	
	ADC1_ChanConf.Offset=0;   
	HAL_ADC_ConfigChannel(&hadc1,&ADC1_ChanConf);        //通道配置

	HAL_ADC_Start(&hadc1);                               //开启ADC

	HAL_ADC_PollForConversion(&hadc1,10);                //轮询转换
	return (u16)HAL_ADC_GetValue(&hadc1);	            //返回最近一次ADC1规则组的转换结果
}

//获取指定通道的转换值,取times次,然后平均 
//times:获取次数
//返回值:通道ch的times次转换结果平均值
u16 Get_Adc_Average(u32 ch,u8 times)
{
	u32 temp_val=0;
	u8 t;
	for(t=0;t<times;t++)
	{
		temp_val+=Get_Adc(ch);
		delay_ms(5);
	}
	return temp_val/times;
} 




/* ADC1 init function */
void MX_ADC1_Init(void)
{
  ADC_MultiModeTypeDef multimode = {0};
  ADC_ChannelConfTypeDef sConfig = {0};

  /** Common config 
  */
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV12;
  hadc1.Init.Resolution = ADC_RESOLUTION_16B;
  hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc1.Init.LowPowerAutoWait = DISABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.NbrOfConversion = 1;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR;
  hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
  hadc1.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
  hadc1.Init.OversamplingMode = DISABLE;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure the ADC multi-mode 
  */
  multimode.Mode = ADC_MODE_INDEPENDENT;
  if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel 
  */
  sConfig.Channel = ADC_CHANNEL_19;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
  sConfig.SingleDiff = ADC_SINGLE_ENDED;
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  sConfig.Offset = 0;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

}

void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(adcHandle->Instance==ADC1)
  {
  /* USER CODE BEGIN ADC1_MspInit 0 */

  /* USER CODE END ADC1_MspInit 0 */
    /* ADC1 clock enable */
    __HAL_RCC_ADC12_CLK_ENABLE();
  
    __HAL_RCC_GPIOA_CLK_ENABLE();
		
	__HAL_RCC_ADC_CONFIG(RCC_ADCCLKSOURCE_CLKP); //ADC外设时钟选择
    /**ADC1 GPIO Configuration    
    PA5     ------> ADC1_INP19 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_5;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /* 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_ADC12_CLK_DISABLE();
  
    /**ADC1 GPIO Configuration    
    PA5     ------> ADC1_INP19 
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5);

  /* USER CODE BEGIN ADC1_MspDeInit 1 */

  /* USER CODE END ADC1_MspDeInit 1 */
  }
} 

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

主程序代码:

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "adc.h"

int main(void)
{
 u16 adcx;
    //Cache_Enable();                 //打开L1-Cache
    HAL_Init();                           //初始化HAL库
    Stm32_Clock_Init(200, 2, 2, 2); //设置时钟,400Mhz
    delay_init(400);                        //延时初始化
    uart_init(115200);                  //串口初始化
    printf("hello\r\n");
		MX_ADC1_Init();
    while (1)
    {
			adcx = Get_Adc_Average(ADC_CHANNEL_19, 20); //获取通道19的转换值,20次取平均
			printf("adcx:%d\r\n",adcx);
			delay_ms(500);
    }
}

你可能感兴趣的:(stm32)