STM32H实现ADC采集

发布者:Joyful444Life最新更新时间:2022-07-08 来源: csdn关键字: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 {

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("hellorn");

MX_ADC1_Init();

    while (1)

    {

adcx = Get_Adc_Average(ADC_CHANNEL_19, 20); //获取通道19的转换值,20次取平均

printf("adcx:%drn",adcx);

delay_ms(500);

    }

}

关键字:STM32H  ADC采集  软件触发  轮询 引用地址:STM32H实现ADC采集

上一篇:STM32H7模拟量引脚分布
下一篇:J-Link V6.30h Device Selection 无法识别到STM32H743VITx芯片

推荐阅读最新更新时间:2024-11-03 09:05

STM32F10x_ADC三通道DMA连续转换(3通道、软件单次触发)
Ⅰ、概述 上一篇文章讲述的内容是:三通道逐次转换(单次、单通道软件触发),也就是说3条通道要三次软件触发才能完成转换,而且是通过软件读取转换数值。 本文讲述三通道DMA连续转换(3通道、软件单次触发),也就是说3条通道只需要一次软件触发就能完成转换,使用DMA保存在数值。 上一篇文章实例是使用间断模式单次触发单条通道采集,本文是使用DMA模式单次触发三条通道采集。使用DMA传输的好处就是效率很高,我们直接读取转换的结果就是了,比如想做的示波器实例就是要求效率很高。 实例实验效果: 本文的实验效果和上一篇文章一样,只是实现的方式不一样 通道1接地、通道2接1.5V电源、通道3接VCC 上一篇文章内容:
[单片机]
STM32F10x_<font color='red'>ADC</font>三通道DMA连续转换(3通道、<font color='red'>软件</font>单次<font color='red'>触发</font>)
用DMA实现多路ADC通道数据采集
找了不少例子参考,ADC和DMA的设置了解了个大概,并直接利用开发板来做一些实验来验证相关的操作,保证自己对各部分设置的理解。 我这里用了3路的ADC通道,1路外部变阻器输入,另外两路是内部的温度采样和Vrefint,这样就能组成连续的采样,来测试多通道ADC自动扫描了,ADC分规则转换和注入转换,其实规则转换就是按照既定的设定来顺序转换,而注入转换就是可以在这顺序队列中插队一样,能够提前转换了。 初始化设置: 1 //PC0 FOR ANAGLE SAMPLE 2 static void Protect_ClkInit(void) 3 { 4 RCC_APB2PeriphClockCmd(RCC_APB2P
[单片机]
TI全新精密宽带宽ADC可提升数据采集性能
TI全新精密宽带宽ADC可提升数据采集性能,同时使尺寸和功耗减小一半 工程师可实现业界领先的交流和直流性能,同时提高通道密度并延长电池寿命 北京(2021年12月7日)– 德州仪器 (TI)现推出超小型24位宽带宽模数转换器(ADC),可比同类ADC在更宽的带宽内实现业界领先的信号测量精度。ADS127L11为TI精密宽带宽ADC系列的全新产品,其封装尺寸减小了50%,可实现超精密数据采集,大幅优化了多种工业系统应用下的功耗、分辨率和测量带宽。 “在测试和测量设备以及便携式医疗设备等应用中,缩小解决方案尺寸和降低功耗是一大流行趋势,与此同时延长电池寿命也势在必行,”Omdia高级研究分析师Noman Akhtar表示,
[模拟电子]
STM32F10x_ADC三通道逐次转换(单次、单通道软件触发)
Ⅰ、概述 本文讲述关于STM32功能比较强大的ADC模块。ADC(Analog to Digital Converter)也就是模拟量转化为数字量,而STM32的ADC模块功能比较多,本文主要讲述“三条通道逐次转换(单次、单通道软件触发)”。 根据笔者的经验,STM32所有系列芯片的ADC模块功能及配置都差不多。因此,本文虽是以F1为例,其实其他系列(F0、F2、F4等)都适用。 本文提供实例代码:三条通道,配置为逐次转换(间隔模式),适用软件触发转换(每触发一次转换一条通道),一个循环也就是需要软件触发三次。 实例实验效果: 通道1接地、通道2接1.5V电源、通道3接VCC 本文讲述的知识点相对较多,若初次学习
[单片机]
STM32F10x_<font color='red'>ADC</font>三通道逐次转换(单次、单通道<font color='red'>软件</font><font color='red'>触发</font>)
STM32基于时间片轮询机制
1. 基于时间片的轮询调度算法(仅局限单核CPU芯片): 利用定时器为每个任务函数设定执行时间间隔,保证使用频率高的函数多次被调用,提高单核芯片的资源利用率。如果只是简单地将A、B两个函数放在while中,那么在一定时间内这两个函数调用的次数是一致的,,这样就浪费了单核芯片的资源。 2. 例子: 函数A(100μs执行一次----使用频率高), 函数B(1000μs执行一次----使用频率低)。 那么在1ms 内 函数A 执行了10次,而函数B只执行1次 当然你要保证函数A在100μs内执行完毕、函数B在1000μs内执行完毕 如果超出时间的话系统会变得卡顿。有部分的函数可能没有别执行到。毕竟单核芯片只在很短时间内只做
[单片机]
STM32的ADC多通道采集的实现
在经过半个月的不懈努力下,终于将32的ADC多通道的信号采集完成,在网上能找到一些对于多通道信号采集的范例,要么就是用多个ADC,要么就是指贴出部分关键代码,也不对其中的配置及实现做一些细致的说明,这让人会走很多弯路,但也正是这样才能不断提升,才能认识自己的不足。好了,下面就先对STM的ADC做个简单的介绍; ADC又称'模拟/数字转换器',在 STM32 单片机 中模拟/数字转换器(ADC)是一种提供可选择多通道输入,逐次逼近型的模数转换器。分辨率为12位,在一般的信号采集应用中已经算是很高的分辨率了。 它有18个通道,可测量16个外部和2个内部信号源。各通道的A/D转换可以单次、连续、扫描或间
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved