STM32使用HAL库实现ADC单通道转换

发布者:CelestialSoul最新更新时间:2025-02-18 来源: cnblogs关键字:STM32  HAL库 手机看文章 扫描二维码
随时随地手机看文章

   STM32的ADC转换还是很强大的,它具有多个通道选择,这里我就不细说,不了解的可以自行百度,这里只是选取单通道,实现ADC转换。在文章开始之前,我说一下数据左对齐跟右对齐的差别,以前一直糊里糊涂的,记录下来以免以后自己忘记。12位二进制最大值为 0x0FFF 左对齐操作后的结果是 0xFFF0,右对齐后还是0x0FFF。反过来看 ,若寄存器里左对齐的数据值X (相当于实际数据*16,所以左对齐转换的值要/16才是实际的值),则X>>4才是实际的数据。而右对齐,则是数据保持不变,采集到多少就多少。至于是按左对齐保存到寄存器还是按照右对齐,就看你的配置里如何选了。

  好了,下面就开始说明怎么用STM32CUBEMX实现ADC单通道转换吧。

利用中断模式

1、配置ADC引脚

  

 2、开定时跟串口定时器用来定时打开ADC转换,这样可以达到1S内控制ADC转换次数的目的,不过有个限制,这里样子控制ADC转换次数的话,如果采样次数多,配置ADC采样速度时一定要够  快,正常配置ADC的采样频率可以通过改变其采样速度来设置的,这里我是为了方便处理,就直接用定时器去开启了;而串口则是打印转换后的电压用的。

  

3、配置时钟

  

4、配置ADC设置

  `

5、开启中断模式

  

6、串口配置默认即可

  

7、定时器配置,定时器配置的是进入定时器中断的频率,定时时间可以根据这个频率换算出来,这里定时器的频率 = 72M / 72 /1000 =1000Hz,所以定时时间为 T = 1S/f = 1S/1000 = 1ms,所以我这里配置定时为1ms。

  

8、基本配置我们完成了,现在我们生成工程用KEIL5打开

  

9、打开工程,我们现在进入代码部分

  这里我们只需要重写定时器中断回调函数跟,ADC转换回调中断函数即可。在main文件里添加这下面这两个函数


void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)    //定时器中断回调

{

    HAL_ADC_Start_IT(&hadc1); //定时器中断里面开启ADC中断转换,1ms开启一次采集    

}


void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)    //ADC转换完成回调

{

    HAL_ADC_Stop_IT(&hadc1);        //关闭ADC

    HAL_TIM_Base_Stop_IT(&htim3);    //关闭定时器

    AD_Value=HAL_ADC_GetValue(&hadc1);  //获取ADC转换的值

    Value_1=(float)(AD_Value*3.3/4096);     //ADC换算,这里参考电压3.3V,12位的ADC满量程为2^12=4096,转换出来的单位是V

    printf('%.4frn',Value_2[j-10000]);     //串口打印信息

    HAL_TIM_Base_Start_IT(&htim3);       //开启定时器

}


到这里就完成单通道ADC中断转换的所有步骤啦,通过串口助手实测转换结果误差为0.0008v。


至于串口查看信息打印输出重定向可以看我这篇文章:https://www.cnblogs.com/xingboy/p/9522940.html


不使用中断模式

不使用中断模式的情况下跟使用中断的类似的,首先配置的过程中不需要开启中断,至于定时器开不开看个人需要,想利用定时器定时采集的可以开,不想的不用开,其他的配置一样。生成代码后,在main文件的main函数中的while循环里添加下面代码:


  /* USER CODE BEGIN 3 */

        for(char n=0;n<22;n++) 

        {  //取22个值做滤波用

            HAL_ADC_Start(&hadc2);

            HAL_ADC_PollForConversion(&hadc2, 10);    //等待转换完成,第二个参数表示超时时间,单位ms        

            if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc2), HAL_ADC_STATE_REG_EOC))

            {

                Value[n]=HAL_ADC_GetValue(&hadc2);

                AD_Value += Value[n];

            }                

        }

        max=Value[0];

        min=Value[0];

        for(char n=0;n<22;n++)//取最大值、最小值

        {

            max=(Value[n]            min=(min        }    

        printf('PC0 ADC : %.4f rn',(float)((AD_Value -max-min)/20)*(3.1/4096));        

        AD_tr=(float)((AD_Value -max-min)/20)*(3.1/4096);    //这里我做了个去掉最大最小值后,取均值的软件滤波   

        AD_Value=0;


这里面的一些变量就你们自己去定义了,我就不列出来了,实测误差在0.001v以内。


补充注意事项:


   1、ADC初始化后要进行校准,使用下面函数校准,可以放在ADC初始化函数后面校准


HAL_ADCEx_Calibration_Start(&hadc2);    //AD校准

  2、传入ADC的电压不可以超过3.3V,就是不可以超过你的参考电压,不然结果不准,还有可能烧坏ADC引脚


使用DMA模式【转:http://www.stm32cube.com/article/37】


再次写写stm32cubemx中AD采集的问题,这次不用while里面的查询,也不用中断采样了,直接用DMA

先说下用DMA的好处:无论是中断采样还是查询采样,都需要在主程序中占用好多时间出来,嗯,你可以这样理解

那种采样都需要调用HAL_ADC_GetValue()这个函数,,,就是要取得转换后的值,中断还好点,要是查询的话,有可能会丢失数据啊. 用dma就可以避免了

DMA用的事总线时间,无线cpu干预,额,这种说法貌似有点问题.管它呢

在AD转换结束的时候自动连接你准备存取的变量的地址,数据一步到位.额,省了多少事..

使用stm32cubemx对AD的配置


5.png?imageView2/2/w/1000


然后对她的DMA配置,并开启DMA的中断



然后生成代码吧

打开main.c文件,在这个地方添加代码


/[i] USER CODE BEGIN 0 [/i]/

__IO uint16_t uhADCxConvertedValue = 0;

/[i] USER CODE END 0 [/i]/

在main()函数里添加


  /[i] USER CODE BEGIN 2 [/i]/

HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&uhADCxConvertedValue, 1);


  /[i] USER CODE END 2 [/i]/

意思是开启dma传输,传送一个字的数据到uhADCxConvertedValue这个变量里面

然后再文件的末尾处添加


/[i] USER CODE BEGIN 4 [/i]/

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle)

{

  /[i] Turn LED1 on: Transfer process is correct [/i]/

 // BSP_LED_On(LED1);

    HAL_GPIO_WritePin (GPIOF,GPIO_PIN_6,GPIO_PIN_SET );

}

/[i] USER CODE END 4 [/i]/


意思是AD转换完成调用这个函数,函数里使能led

也许,你会问,为毛是HAL_ADC_ConvCpltCallback()这个函数啊,这个函数不是当开启AD的中断的时候才调用的吗?

嗯,对,这个函数是这样的,但是你仔细去分析下开启AD的DMA中断函数里面,就会发现这个函数也在啊


关键字:STM32  HAL库 引用地址:STM32使用HAL库实现ADC单通道转换

上一篇:STM32 HAL库使用中断实现串口接收不定长数据
下一篇:STM32 使用Cubemx 建一个USB(HID)设备下位机,实现数据收发

推荐阅读最新更新时间:2026-03-21 14:09

STM32使用HAL库实现ADC单通道转换
  STM32的ADC转换还是很强大的,它具有多个通道选择,这里我就不细说,不了解的可以自行百度,这里只是选取单通道,实现ADC转换。在文章开始之前,我说一下数据左对齐跟右对齐的差别,以前一直糊里糊涂的,记录下来以免以后自己忘记。12位二进制最大值为 0x0FFF 左对齐操作后的结果是 0xFFF0,右对齐后还是0x0FFF。反过来看 ,若寄存器里左对齐的数据值X (相当于实际数据*16,所以左对齐转换的值要/16才是实际的值),则X 4才是实际的数据。而右对齐,则是数据保持不变,采集到多少就多少。至于是按左对齐保存到寄存器还是按照右对齐,就看你的配置里如何选了。   好了,下面就开始说明怎么用STM32CUBEMX实现ADC单通
[单片机]
<font color='red'>STM32</font>使用<font color='red'>HAL库</font>实现<font color='red'>ADC</font><font color='red'>单通道</font><font color='red'>转换</font>
STM32F10x_ADC三通道逐次转换 (单次、单通道软件触发)
Ⅰ、概述 本文讲述关于STM32功能比较强大的ADC模块。ADC(Analog to Digital Converter)也就是模拟量转化为数字量,而STM32的ADC模块功能比较多,本文主要讲述“三条通道逐次转换(单次、单通道软件触发)”。 根据笔者的经验,STM32所有系列芯片的ADC模块功能及配置都差不多。因此,本文虽是以F1为例,其实其他系列(F0、F2、F4等)都适用。 本文提供实例代码:三条通道,配置为逐次转换(间隔模式),适用软件触发转换(每触发一次转换一条通道),一个循环也就是需要软件触发三次。 实例实验效果: 通道1接地、通道2接1.5V电源、通道3接VCC 本文讲述的知识点相对较多,若初次学习S
[单片机]
STM32F10x_<font color='red'>ADC</font>三通道逐次<font color='red'>转换</font> (单次、<font color='red'>单通道</font>软件触发)
DMA+ADC单通道转换、多通道转换
在stm32中,使用ADC时往往采用DMA传输方式,由DMA把转换的数据传输到SRAM,再进行处理。 一、单通道转换 本章节选用ADC1进行配置实验: ADC通道与GPIO对应表: ADC结构体成员变量: typedef struct { uint32_t ADC_Mode; FunctionalState ADC_ScanConvMode; FunctionalState ADC_ContinuousConvMode; uint32_t ADC_ExternalTrigConv; uint32_t ADC_DataAlign; uint8_t ADC_NbrOfChannel; }ADC_Init
[单片机]
DMA+<font color='red'>ADC</font><font color='red'>单通道</font><font color='red'>转换</font>、多通道<font color='red'>转换</font>
adc12单通道单次转换例程(msp460f5529)
#include msp430f55529.h int main( void ) { // Stop watchdog timer to prevent time out reset WDTCTL = WDTPW + WDTHOLD; ADC12CTL0 = ASC12SHT02 + ADC12ON; ASC12CTL1 = ADC12SHP; ADC12IE = 0x01; ADC12CTL0 |= ADC12ENC; P6SEL |= 0x01; P1DIR |=BIT0; while (1) { ADC12CTL0 |= ADC12SC; __bis_SR_register(;PM0_b
[单片机]
msp430 ADC10单通道多次转换
MSP430 ADC10单通道多次转换 #include msp430x22x4.h #define uchar unsigned char #define uint unsigned int #define LCDen 0X80; //P3的高三位做控制线 #define lcdrw 0X40; #define lcdrs 0X20; void delay(uint z) //延时程序 { uint x,y; for(x=z;x 0;x--) for(y=100;y 0;y--); } void write_com(uchar com) //写指令 { P
[单片机]
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 GPIO操作深度解析:HAL库中的GPIO初始化艺术——不仅仅是配置寄存器的故事
???? 前言 你是不是也曾经天真地以为,控制几个LED灯只需要随便写两行代码?是不是觉得GPIO初始化不过是设置几个寄存器的小把戏?当你的按键检测出现抖动、LED莫名闪烁、通信接口罢工时,你是否怀疑过自己根本没真正理解GPIO?今天,就让我们把STM32的GPIO外衣一层层剥开,看看这个看似简单的功能模块背后藏着多少工程师的智慧结晶! 1. GPIO——被低估的硬件桥梁 GPIO(General Purpose Input/Output)是MCU与外部世界交互的物理接口。在STM32中,每个GPIO引脚都包含7个寄存器控制其行为: 4个32位配置寄存器(MODER, OTYPER, OSPEEDR, PUPDR) 2个3
[单片机]
<font color='red'>STM32</font> GPIO操作深度解析:<font color='red'>HAL库</font>中的GPIO初始化艺术——不仅仅是配置寄存器的故事
STM32标准库与HAL库比较
ST为开发者提供了非常方便的开发库。到目前为止,有标准外设库(STD库)、HAL库、LL库 三种。 其中标准库与HAL库最常用,LL库只是最近新添加的。 标准外设库(Standard Peripherals Library)是对STM32芯片的一个完整的封装,包括所有标准器件外设的器件驱动器。这应该是目前使用最多的ST库,几乎全部使用C语言实现。但是,标准外设库也是针对某一系列芯片而言的,没有可移植性。 HAL库与新增的LL库,都是ST公司提供的新标准库,包含在ST为新的标准库注册了一个新商标:STMCube™当中。LL库和HAL库两者相互独立,只不过LL库更底层。而且,部分HAL库会调用LL库(例如:USB驱动)。同
[单片机]
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

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

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

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