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采集出来的数据不会有变化。
在这里插入图片描述

全部代码如下:

#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);
    }
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于STM32麦克风模块的ADC采集,可以参考以下步骤进行配置和使用。 首先,在生成HAL_ADC_MspInit函数中添加一句核心的__HAL_RCC_ADC_CONFIG(RCC_ADCCLKSOURCE_CLKP)来选择ADC的时钟源。ADC的时钟源有三个选项,其中RCC_ADCCLKSOURCE_CLKP是其中之一。\[1\] 其次,通过单片机的ADC模块进行数据采集。可以使用ADC的转换值与数据表进行比较,找到对应的温度区间。比如,可以通过查表得到-30°C到70°C对应的下标为0~100,然后将采集到的数据的下标减去30,就可以得到对应的温度值。\[2\] 最后,可以在主程序中进行ADC的初始化和数据采集。可以使用HAL库提供的函数进行ADC的初始化,然后在循环中使用Get_Adc_Average函数获取通道的转换值,并进行相应的处理。\[3\] 以上是关于STM32麦克风模块ADC采集的一般步骤和代码示例。具体的实现还需要根据具体的硬件和需求进行调整和优化。 #### 引用[.reference_title] - *1* *3* [STM32H实现ADC采集](https://blog.csdn.net/qq_27508477/article/details/105761199)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [11讲 | STM32单片机实现ADC采集功能](https://blog.csdn.net/weixin_39903708/article/details/107904439)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值