STM32 hal库使用笔记(五)ADC—单通道/双通道DMA传输

这篇具有很好参考价值的文章主要介绍了STM32 hal库使用笔记(五)ADC—单通道/双通道DMA传输。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

实现目的:利用ADC采集光敏传感器/烟雾传感器的值,并利用串口打印

实验平台:正点原子精英版

一、简介

1.DMA的介绍

参考:STM32 hal库使用笔记(四)DMA—内存到内存/内存到外设_乱码小伙的博客-CSDN博客

2.ADC简介

     ADC(Analog-Digital Converter)模拟-数字转换器 ADC可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量,建立模拟电路到数字电路的桥梁;

    12位逐次逼近型ADC,1us转换时间;

    输入电压范围:0~3.3V,转换结果范围:0~4095;

    18个输入通道,可测量16个外部和2个内部信号源;

    规则组和注入组两个转换单元,可利用模拟看门狗自动监测输入电压范围。

3.一些概念

    ADC数据寄存器是32位,但是只用到16位,所以一般采用右对齐方式,方便计算。

    如果多通道转换ADC,次数频繁,间隔时间短(循环模式),会导致数据寄存器的数值被覆盖,所以要利用DMA转运。

hal stm32g0系列adc使用,STM32的hal库使用,stm32,笔记,嵌入式硬件

    注入组限制较多,一般采用规则组进行转换。

    TCONV = 采样时间 + 12.5个ADC周期,采样时间=n个ADC周期,ADC采用频率最大是14MHZ,由于ADC挂载总线的频率是72MHZ所以进行6分频,采用周期是12MHZ。

    ADC有一个内置自校准模式。校准可大幅减小因内部电容器组的变化而造成的准精度误差。校准期间,在每个电容器上都会计算出一个误差修正码(数字值),这个码用于消除在随后的转换中每个电容器上产生的误差。HAL_ADCEx_Calibration_Start(),进行校准。

二、HAL库配置

1.时钟树的设置

按照下图配置即可:

hal stm32g0系列adc使用,STM32的hal库使用,stm32,笔记,嵌入式硬件

 2.ADC的配置

关于串口的配置参考:STM32 hal库使用笔记(二)中断—串口中断_乱码小伙的博客-CSDN博客

    本实验不使用串口中断,中断部分的配置不用操作

2.1 单通道(代码对应3.1)

hal stm32g0系列adc使用,STM32的hal库使用,stm32,笔记,嵌入式硬件

1)关闭扫描模式,由于只有一个通道;

2)关闭连续转换模式,每次需要ADC转换时打开ADC转换即可;

3)采用规则组;

4)软件触发模式;

5)28.5个ADC周期,所以整个采采样周期是30个ADC周期。

配置完成后生成代码即可。

2.2 DMA双通道(代码对应3.2)

hal stm32g0系列adc使用,STM32的hal库使用,stm32,笔记,嵌入式硬件

1)开启双通道

2)扫描模式打开

3)转换组设置为2

4)打开通道1

5)周期28.5个

6)打开通道2

7)周期28.5个

注意每个ADC的每个通道只能对应一个GPIO。

hal stm32g0系列adc使用,STM32的hal库使用,stm32,笔记,嵌入式硬件

ADC数据是16位的,所以采用半字字宽。

配置完成后,生成代码即可。

三、代码编写

3.1 

以下代码在adc.c中编写

void MX_ADC1_Init(void)
{
  ADC_ChannelConfTypeDef sConfig = {0};

  /** Common config 
  */
  hadc1.Instance = ADC1;
  hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 1;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel 
  */
  sConfig.Channel = ADC_CHANNEL_1;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_28CYCLES_5;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)//配置ADC时钟,通道、序列 
  {
    Error_Handler();
  }
  HAL_ADCEx_Calibration_Start(&hadc1);//用户添加,ADC校准,据了解最新版HAL库已经删除 
}

用户编码区:

uint32_t adc_get_result(void)
{
    HAL_ADC_Start(&hadc1);//单次转换模式,每次转换完成后ADC转换会自动停止
    HAL_ADC_PollForConversion(&hadc1, 10);//ADC转换,转换参数ms
    return (uint16_t)HAL_ADC_GetValue(&hadc1);
}

以下在main.c

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */
  

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_ADC1_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
     
    /* USER CODE BEGIN 3 */
    HAL_Delay(2000);
      unsigned char arrary[4];
        arrary[0] = ((adc_get_result()/1000))+0x30;      
		arrary[1] = (((adc_get_result()%100)/10))+0x30;
		arrary[2] = ((adc_get_result()%10)/10)+0x30;
        arrary[3] = ((adc_get_result()%1)/10)+0x30;
    //unsigned char MyArray[1]={adc_get_result()};
      //HAL_UART_Transmit(&huart1, MyArray,1, 10000);
    HAL_UART_Transmit(&huart1, arrary,4,1000);
  }
  /* USER CODE END 3 */
}

实验现象:用手盖住和放开有明显变化

hal stm32g0系列adc使用,STM32的hal库使用,stm32,笔记,嵌入式硬件

3.2

添加接收数据数组:uint16_t g_adc_dma_buf[2];

以下代码均在adc.c中编写:

void MX_ADC1_Init(void)
{
  ADC_ChannelConfTypeDef sConfig = {0};

  /** Common config 
  */
  hadc1.Instance = ADC1;
  hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 2;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel 
  */
  sConfig.Channel = ADC_CHANNEL_1;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_28CYCLES_5;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel 
  */
  sConfig.Channel = ADC_CHANNEL_2;
  sConfig.Rank = ADC_REGULAR_RANK_2;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
   HAL_ADC_Start_DMA(&hadc1,(uint32_t *)(g_adc_dma_buf) ,0);//触发ADC转换,DMA传输数据
}

 HAL_ADC_Start_DMA(&hadc1,(uint32_t *)(g_adc_dma_buf) ,0);这个可以省略,因为DMA不是循环模式,ADC也不是连续模式,所以每次采集ADC都需要重新开启。

用户编码区:

void adc_dma_enable(uint32_t cndtr)
{
    
    __HAL_ADC_DISABLE(&hadc1);
    
    __HAL_DMA_DISABLE(&hdma_adc1);
    
    while (__HAL_DMA_GET_FLAG(&hdma_adc1, DMA_FLAG_TC1))
    {
    __HAL_DMA_CLEAR_FLAG(&hdma_adc1, DMA_FLAG_TC1);  //清除标志位
    }//实测,删去也能正常使用,因为测量间隔时间长,DMA肯定关闭了
    
    DMA1_Channel1->CNDTR = cndtr;

    __HAL_DMA_ENABLE(&hdma_adc1);
    
    __HAL_ADC_ENABLE(&hadc1);
    HAL_ADC_Start(&hadc1); //开启ADC转换,必须定时开启,因为ADC不是连续扫描模式 
}

以下均在main.c

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */
  

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_ADC1_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
         HAL_Delay(2000);
       adc_dma_enable(2);//必须添加
      unsigned char arrary[4];
      unsigned char arrary2[4];
        arrary[0] = ((g_adc_dma_buf[0]/1000))+0x30;      
		arrary[1] = (((g_adc_dma_buf[0]%100)/10))+0x30;
		arrary[2] = ((g_adc_dma_buf[0]%10)/10)+0x30;
        arrary[3] = ((g_adc_dma_buf[0]%1)/10)+0x30;
      printf("ADC1:");
      HAL_UART_Transmit(&huart1, arrary,4,1000);
      printf("\r\n");
        arrary2[0] = ((g_adc_dma_buf[1]/1000))+0x30;      
		arrary2[1] = (((g_adc_dma_buf[1]%100)/10))+0x30;
		arrary2[2] = ((g_adc_dma_buf[1]%10)/10)+0x30;
        arrary2[3] = ((g_adc_dma_buf[1]%1)/10)+0x30;
      printf("ADC2:");
      HAL_UART_Transmit(&huart1, arrary2,4,1000);
      printf("\r\n");
  }
  /* USER CODE END 3 */
}

实验现象:没有打火机,烟雾传感器值一直为0,ADC通道1连接光敏,有明显变化(连接到通道2上也有明显变化)。实测成功。

hal stm32g0系列adc使用,STM32的hal库使用,stm32,笔记,嵌入式硬件

 欢迎大家交流和指正!!!文章来源地址https://www.toymoban.com/news/detail-773197.html

到了这里,关于STM32 hal库使用笔记(五)ADC—单通道/双通道DMA传输的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM-32:ADC模数转换器—ADC单通道转换/ADC多通道转换

    ADC(Analog-Digital Converter),意即模拟-数字转换器,简称模数转换器。ADC可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量,建立模拟电路到数字电路的桥梁。与ADC相对应,从数字电路到模拟电路的桥梁即DAC(Digital-Analog Convertor),数模转换器。 DAC不是唯一可以

    2024年02月09日
    浏览(28)
  • STM32CubeMX教程13 ADC - 单通道转换

    开发板(正点原子stm32f407探索者开发板V2.4) STM32CubeMX软件(Version 6.10.0) keil µVision5 IDE(MDK-Arm) ST-LINK/V2驱动 野火DAP仿真器 XCOM V2.6串口助手 1个滑动变阻器 使用STM32CubeMX软件配置STM32F407开发板的 ADC实现单通道ADC采集 ,具体为使用ADC1_IN5通道通过软件/定时器触发采集滑动变阻

    2024年02月02日
    浏览(18)
  • 【正点原子STM32连载】第三十三章 单通道ADC采集实验 摘自【正点原子】APM32E103最小系统板使用指南

    1)实验平台:正点原子APM32E103最小系统板 2)平台购买地址:https://detail.tmall.com/item.htm?id=609294757420 3)全套实验源码+手册+视频下载地址: http://www.openedv.com/docs/boards/xiaoxitongban 本章介绍使用APM32E103模数转换器(ADC)进行带通道的电压采集。通过本章的学习,读者将学习到单通

    2024年02月19日
    浏览(22)
  • HAL库配置ADC_1_单通道配置

    💦在使用ADC外设前,先查看下芯片手册,看下ADC的特点。 💦ADC的使用,一定是有参考电压的,在使用时要注意,芯片手册上关于ADC参考电压的范围。 通常正参考电压VREF+连接到VCC,负参考电压VREF-连接到GND 💦通过框图可以了解ADC的工作流程。   下面是ADC比较常用的参数说

    2024年02月04日
    浏览(13)
  • STM32自学☞AD单通道

      程序的最终运行成果: 当转动电位器时,数值和电压值发生变化 #include \\\"stm32f10x.h\\\" #include \\\"stm32f10x_adc.h\\\" #include \\\"ad.h\\\" #include \\\"stdint.h\\\" void ad_Init(void) {  /*  初始化步骤:  1.开启GPIO时钟和ADC时钟,配置ADCCLK  2.配置GPIO,模拟输入模式  3.配置多路开关  4.配置ADC转换器  5.开启

    2024年03月21日
    浏览(23)
  • STM32CubeMx实现ADC多通道+DMA读取(HAL库)

    目录 一、实验结果  二、STM32CubeMx配置 三、main.c测试代码 1、RCC配置 (外部晶振选择8MHz。设置相应的分频器M=8,倍频器倍频系数N=336,分频器分频系数P=2,那么主PLL生成的第一个输出高速时钟PLLP为:168MHz)  2、SYS配置  3、ADC(规则)通道配置(独立模式,预分频4分频,1

    2024年02月15日
    浏览(16)
  • STM32CubeMx配置ADC(多通道采集+DMA读取数据)(HAL库开发)

    目录 1、函数配置过程(这是标准库配置过程): 2、STM32CubeMx配置过程  3、main函数源文件 采集5路ADC数据,并用串口printf()函数打印出来。 实验现象:  ADC转换的初始条件: 1、使能 2、触发源条件完成(这个需要自己配置)利用:HAL_ADC_Start_DMA()函数; ADC中HAL开发优势就是,

    2023年04月08日
    浏览(33)
  • STM32CubeMX配置STM32G031多通道ADC + DMA采集(HAL库开发)

     时钟配置HSI主频配置64M  勾选打开8个通道的ADC  使能连续转换模式  添加DMA  DMA模式选择循环模式  使能DMA连续请求 采样时间配置160.5 转换次数为8  配置好8次转换的顺序  配置好串口,选择异步模式 配置好需要的开发环境并获取代码  修改main.c 串口重定向  串口重定向

    2024年02月08日
    浏览(20)
  • 实验(六):ADC应用:独立模式单通道采集实验

    实验目的: 1. 学习对ADC基础功能的使用; 2. 掌握KEIL5的仿真与调试。 任务: 1.   根据要求编写程序,并写出原理性注释; 2. 将检查程序运行的结果,分析一下是否正确; 3. 完成所建工程的验证调试。 贴片滑动变阻器的动触点通过连接至STM32 芯片的ADC 通道引脚。当我们使

    2024年02月15日
    浏览(26)
  • STM32基于hal库的adc以DMA的多通道采样以及所遇问题解决

    目录 准备 配置 步骤  总结   正点原子的STM32F103ZET6开发板(精英版) CUBEMX配置软件 KEIL5  右对齐就是正常的数据格式。左对齐除以16后得正常数据。(当输出非常大时考虑是否改了对齐方式,默认都是右对齐)  扫描模式,连续转换模式使能。(多通道下扫描模式自动使能

    2024年02月04日
    浏览(21)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包