STM32F4_模数转换器(ADC)详解

news2024/11/19 18:41:08

目录

1. ADC是什么

2. ADC主要特性

3. ADC框图

3.1 ADC开关控制

3.2 ADC时钟

3.3 通道选择

3.4 单次转换模式和连续转换模式

3.5 时序图

3.6 模拟看门狗

4 温度传感器

5. ADC中断

6. ADC初始化结构体

6.1 ADC相关实验配置

7. 相关寄存器

7.1 ADC控制寄存器:ADC_CR1和ADC_CR2

7.2 ADC通用控制寄存器:ADC_CCR

7.3 ADC采样时间寄存器:ADC_SMPR1和ADC_SMPR2

7.4 ADC规则序列寄存器:ADC_SQRx(x取值1~3)

7.5 ADC规则数据寄存器:ADC_DR

7.6 ADC状态寄存器:ADC_SR

8. 库函数配置ADC1的通道5进行AD转换 

9. 实验程序

9.1 main.c

9.2 ADC.c

9.3 ADC.h


        首先明确,这里提到的ADC不是我们游戏中的ADC,这里提及的ADC是STM32的一种重要外设功能,ADC英文全程:Analog to Digital,又叫做模拟数字转换器。 

1. ADC是什么

在高中的物理中,我们学习过电压表、电流表和万用表的使用,这些器件可以用来测量电路中的分路电流、电压值;强大的STM32单片机中也存在着这样的外设,称作模数转换器ADC;

很好理解,模数转换器就是把模拟量转换成数字量;数字对于我们来说是很亲切的,之所以存在这样的外设,也是为了更方便于使用者的理解和操作。

模拟量就如电压值、光敏电阻阻值、热敏电阻阻值等,通过该转换器可以转换为我们肉眼可见的数字。

STM32F4的ADC是12位逐次趋近型模数转换器。具有多达19个复用通道,可测量来自16个外部源、两个内部源通道的信号。ADC的结果存储在一个左对齐或者右对齐的16位数据寄存器中。

ADC具有模拟看门狗特性,允许应用检测输入电压是否超过了用户自定义的阈值上限或者下限。

STM32F4xx系列一般都有3个ADC,这些ADC可以独立使用,也可以使用双重/三重模样,来提高采样率。STM32F4的ADC是12位逐次逼近型的模拟数字转换器,它有19个通道,可以测16个外部源、2个内部源和Vbat通道的信号。STM32F4的ADC最大的转换速率为2.4Mhz,也就是转换时间为0.41us。

2. ADC主要特性

  • 可配置12位、10位、8位或6位分辨率
  • 在转换结束、注入转换结束以及发生模拟看门狗或溢出事件时产生中断
  • 单次和连续转换模式
  • 用于自动将通道0转换为通道“n”的扫描模式
  • 数据对齐以保持内置数据一致性
  • 可独立设置各通道采样时间
  • 外部触发器选项,可为规则转换和注入转换配置极性
  • ADC电源要求:全速运行时2.4V到3.6V,慢速运行时1.8V

3. ADC框图

1. 电压输入范围

         V_{REF+}表示正模拟参考电压输入,代表ADC高/正参考电压;

        V_{DDA}表示模拟电源输入,代表模拟电源电压等于V_{DD}

        V_{REF-}表示负模拟参考电压输入,代表ADC低/负参考电压;

        V_{SSA}表示模拟电源接地输入,代表模拟电源接地电压等于V_{SS}

输入电压: V_{REF-} <= VIN <=  V_{REF+}   

    V_{SSA} 和V_{REF-} 接地,把V_{DDA}V_{REF+}接3V3,表示得到ADC的输入电压范围为0-3.3V;

STM32的ADC只能测0-3.3V的电压,如果超过了这个范围,只能在单片机上改变电压的范围(通过相应芯片的转电平作用),以保证能够被STM32的GPIO口识别。

2. 输入通道:

STM32的每个ADC都具有18个通道,其中外部通道16个:

STM32的ADC有16条复用通道。外部16个通道在转换的过程中又分为规则通道注入通道

        可以将转换分为两组:规则转换注入转换。每个组包含一个转换序列,该序列可按任意顺序在任意通道上完成。

        其中规则通道由规则序列寄存器ADC_SQRx(x可以取值为1 2 3)来配置,注入通道由注入序列寄存器ADC_JSQR来配置。

一个规则转换组最多由16个转换构成。必须在ADC_SQRx寄存器中选择转换序列的规则通道及其顺序。规则转换组中的转换总数必须写入ADC_SQRx寄存器中的L[3:0]位。

一个注入转换组最多由4个转换构成。必须在ADC_JSQR寄存器中选择转换序列的注入通道及其顺序。注入转换组中的转换总数必须写入ADC_JSQR寄存器中的L[1:0]位。

顾名思义,两个通道的区别就是:规则通道就是很规矩的意思,我们一般使用的就是这个规则通道。注入可以理解为插入、插队的意思,是一种不安分的通道,有点类似于中断程序;注入通道只有在规则通道存在时才会出现。

3.  转换顺序:

输入通道注入通道的转换顺序分别由规则序列寄存器ADC_SQRx(x可以取值为1 2 3)和注入序列寄存器ADC_JSQR来配置。

4. 触发源:

触发源相当于一个信号,用来告诉ADC可以开始转换了。

触发方式又分为软件触发外部事件触发(内部定时器/外部IO)。分别对应于上图中的左侧TIM和右侧TIM。

5. 转换时间:

转换时间:Tconv=采样时间+12个周期

采样时间:ADC需要若干个ADC_CLK周期完成对输入的模拟量进行采样,采样的周期数可通过ADC采样时间寄存器ADC_SMPR1和ADC_SMPR2的SMPx[2:0]位设置,ADC_SMPR2控制的是通道0~9,ADC_SMPR1控制的是通道10~17。每个通道可以分别用不同的时间采样。其中采样周期最小是1.5个,也就是说,我们要达到最快的采样,那么应该设置采样周期为31.5个周期,这里的周期就是1/ADC_CLK。

ADC_CLK:ADC模拟电路时钟,最大值为14M,由PCLK2提供,还可以进行分频,2/4/6/8,RCC_CFGR的ADCPRE[1:0]设置。PCLK2=72M。

数字时钟:RCC_APB2ENR,用于访问寄存器。

ag. 最短的转换时间:Tconv=采样时间+12个周期 (其中PCLK2=72M,ADC_CLK=72/6=12M ,Tconv=1.5+12.5=14=14/12us=1.17us)

6. 数据寄存器:

一切准备就绪后,ADC转换后的数据根据转换组不同,规则组的数据存放在ADC_DR寄存器中,注入组的数据放在JDRx寄存器中。

数据寄存器ADC_DR(ADC regular data register)

位31:16  保留,必须保持复位值

位15:0 DATA[15:0]:规则数据(Regular data) 这些位为只读。它们包括来自规则通道的转换结果。

该寄存器的1~16位有效,用于存放独立模式转换完成数据。当在双ADC模式(ADC1和ADC2同时使用)下,ADC1放在低16位上,ADC2放在高16位上。

7. 中断:

STM32F4相比于F1增加了DMA溢出标志。由模拟看门狗来检测采样的模拟量信号值的下限和上限。

电压转换:

所谓电压转换就是如何根据数字量去算出模拟量?  也可以说是外部电压假设是2.5V,通过ADC转换成数字量,也就是数字,存放在数据寄存器ADC_DR中,电压转换就是通过数据寄存器中的数字去反推出外部电压。

1. 电压输入范围为:0~3.3V 

2. 分辨率为12位

3. 最小精度为:3.3/2^12

4. 设数字量为x,则有模拟量Y=(3.3/2^12)* x

3.1 ADC开关控制

可以通过将ADC控制寄存器ADC_CR2寄存器中的ADON位置1来为ADC供电。首次将ADON位置1时,会将ADC从掉电模式中唤醒。

SWSTART或JSWSTART位置1,启动AD转换。

可通过将ADON位清零来停止转换并使ADC进入掉电模式,在此模式下,ADC几乎不耗电,也可以说进入了低功耗模式。

3.2 ADC时钟

用于模拟电路的时钟:ADCCLK,所有ADC共用

        此时钟来自于经可编程预分频器分频的APB2时钟,该预分频器允许ADC在f_{PCLK2}/2、/4、/6或/8下工作。

用于数字接口的时钟:(用于寄存器读/写访问)

        此时钟等效于APB2时钟。可以通过RCC APB2外设时钟使能寄存器(RCC_APB2ENR)分别为每个ADC使能/禁止数字接口时钟。

3.3 通道选择

STM32的ADC有16条复用通道。外部16个通道在转换的过程中又分为规则通道注入通道

        可以将转换分为两组:规则转换注入转换。每个组包含一个转换序列,该序列可按任意顺序在任意通道上完成。

一个规则转换组最多由16个转换构成。必须在ADC_SQRx寄存器中选择转换序列的规则通道及其顺序。规则转换组中的转换总数必须写入ADC_SQRx寄存器中的L[3:0]位。

一个注入转换组最多由4个转换构成。必须在ADC_JSQR寄存器中选择转换序列的注入通道及其顺序。注入转换组中的转换总数必须写入ADC_JSQR寄存器中的L[1:0]位。

顾名思义,两个通道的区别就是:规则通道就是很规矩的意思,我们一般使用的就是这个规则通道。注入可以理解为插入、插队的意思,是一种不安分的通道,有点类似于中断程序;注入通道只有在规则通道存在时才会出现。因为注入通道相当于中断,那么当程序正常执行的时候,中断是可以打断你的执行的。因此注入通道的转换可以打断规则通道的转换,在注入通道被转换完成之后,规则通道才得以继续转换。

如果在转换期间修改 ADC_SQRx 或 ADC_JSQR 寄存器,将复位当前转换并向 ADC 发送一 个新的启动脉冲,以转换新选择的组。

温度传感器、V_{REFINT}内部通道

        对于STM32F40x系列的开发板,温度传感器内部连接到ADC1_IN16。内部参考电压V_{REFINT}连接到ADC1_IN17。

注意: 温度传感器、V_{REFINT}只在主ADC1外设上可用。

3.4 单次转换模式和连续转换模式

单次转换模式下,ADC执行一次转换。CONT位为0时,可以通过以下三种方式启动此模式:

  •         将ADC_CR2寄存器中的SWSTART位置1(仅适用于规则通道)
  •         将JSWSTART位置1(适用于注入通道)
  •         外部触发(适用于规则通道和注入通道)

如果转化了规则通道:

  •         转换数据存储在16位ADC_DR寄存器中
  •         EOC(转换结束)标志位置1
  •         EOCIE位置1时将产生中断

如果转换了注入通道:

  •         转换数据存储在16位ADC_JCR1寄存器中        
  •         JEOC(注入转换结束)标志置1
  •         JEOCIE位置1时将产生中断

连续转换模式下,ADC结束一个转换后立即启动一个新的转换。CONT位为1时,可通过外部触发或将ADC_CR2寄存器中的SWSTRT位置1来启动该模式(仅适用于规则通道)

如果转换了规则通道组:

  •         上次转换的数据存储在16位ADC_DR寄存器中
  •         EOC(转换结束)标志置1
  •         EOCIE位置1时将产生中断

STM32F4的ADC在单次转换模式下,只执行一次转换,该模式可通过ADC_CR2寄存器的ADON位(只适用于规则通道)启动,也可以通过外部触发启动(适用于规则通道和注入通道),这时CONT位为0。

以规则通道为例,一旦所选择的通道转换完成,转换结果将被存储在ADC_DR寄存器中,EOC(转化结束)标志将被置位,如果设置了EOCIE,则会产生中断。然后ADC将停止,直到下次启动。

3.5 时序图

在时序图中, ADC_CLK表示ADC的时钟;ADON是ADC控制寄存器中的最低位,将该位置1表示开启寄存器;SWSTART/JSWSTART用来设置转换模式;

 ADC在开始精确转换之前需要一段稳定时间t_{STAB}。ADC开始转换并经过15个时钟周期后,EOC标志置1,转换结果存放在16位ADC数据寄存器中。

3.6 模拟看门狗

如果ADC转换的模拟电压低于阈值下限或者高于阈值上限,则AWR模拟看门狗状态位会置1。这些阈值在ADC_HTR或ADC_LTR 16位寄存器的12个最低有效位中进行编程。可以使用ADC_CR1寄存器中的AWDIE位使能中断。

4 温度传感器

我们都很清楚传感器的用处,那么显然温度传感器就是用来测量器件的环境温度(T_{A})的。

        对应STM32F40x系列的开发板器件(其他的型号开发板对应不同的ADC通道),温度传感器内部连接到ADC1_IN16通道,而ADC1用于将传感器输出电压转换为数字值。不使用时可以将传感器置于掉电模式。

注意:必须将TSVREFE位置1才能同时对两个通道进行转换。ADC1_IN16(温度传感器)和ADC1_IN17(VREFINT)。

主要特性

  •         支持的温度范围(可以通过ADC转换成的数字范围):-40℃到125℃
  •         精度:\pm1.5℃

 读取温度

  •         选择ADC1_IN16输入通道
  •         选择一个采样时间,该采样时间要大于数据手册上指定的最低采样时间
  •         在ADC_CCR寄存器中将TSVREFE位置1,以便将温度传感器从掉电模式中唤醒
  •         通过将SWSTART位置1开始ADC转换
  •         读取ADC数据寄存器中生成的V_{SENSE}数据

计算温度

温度(单位℃)={V_{SENSE}-V_{25}/Avg_Slope}+25

        其中:   V_{25}=25℃时的V_{SENSE}值          Avg_Slope=温度与V_{SENSE}曲线的平均斜率

注意

        传感器从掉电模式中唤醒需要一个启动时间,启动时间过后其才能正确输出V_{SENSE}。ADC在上电后同样需要一个启动时间,因此,为尽可能减少延迟时间,应同时将ADON和TSVREFE位置1。

        温度传感器的输出电压随温度线性变化。

5. ADC中断

当模拟看门狗状态位和溢出状态位分别置1时,规则组和注入组在转换结束时可能会产生中断。可以使用单独的中断使能位以实现灵活性。

ADC_SR寄存器中存在另外两个标志,但这两个标志不存在中断相关性:

  •         JSTRT(开始转换注入组的通道)
  •         STRT(开始转换规则组的通道)

6. ADC初始化结构体

ADC_InitTypeDef

typedef struct
{
  uint32_t ADC_Resolution;         //ADC分辨率                                        
  FunctionalState ADC_ScanConvMode;     //ADC扫描多通道或者ADC单通道模式选择  通过ADC_CR1的SCAN位来配置
  FunctionalState ADC_ContinuousConvMode;   //ADC单次转换或者连续转换选择 通过ADC_CR2的CON位来配置
  uint32_t ADC_ExternalTrigConvEdge;      //ADC转换触发信号范围选择
  uint32_t ADC_ExternalTrigConv;          //ADC外部触发转换模式选择  通过ADC_CR2的EXTTRIG和EXTSEL位来配置
  uint32_t ADC_DataAlign;                 //ADC数据寄存器对齐格式
  uint8_t  ADC_NbrOfConversion;           //ADC采集通道数
}ADC_InitTypeDef;

typedef struct 
{
  uint32_t ADC_Mode;              //ADC模式 通过ADC_CR1:DUALMOD位来配置                                                 
  uint32_t ADC_Prescaler;              //ADC预分频值                       
  uint32_t ADC_DMAAccessMode;           
  uint32_t ADC_TwoSamplingDelay;        //ADC多通道模式 
}ADC_CommonInitTypeDef;

6.1 ADC相关实验配置

1-独立模式-单通道-中断读取

  • 初始化ADC用到的GPIO
  • 初始化ADC初始化结构体
  • 配置ADC时钟,配置通道的转换顺序和采样时间
  • 使能ADC转换完成中断,配置中断优先级
  • 使能ADC,准备开始转换
  • 校准ADC   ADC_StartCalibration      ADC_GetCalibrationStatus
  • 软件触发ADC,真正开始转换   ADC_SoftwareStartConvCmd
  • 编写中断服务函数,读取ADC转换数据   
  • 编写main函数,把转换的数据打印出来

2-独立模式-单通道-DMA读取                DMA是一种直接存储器,DMA是不占用CPU的,可以一边读取数据,一边处理数据。

  • 初始化ADC用到的GPIO
  • 初始化ADC初始化结构体
  • 配置ADC时钟,配置通道的转换顺序和采样时间
  • 使能ADC转换完成中断,配置中断优先级

3-独立模式-多通道-DMA读取

  • 初始化ADC用到的GPIO
  • 初始化ADC初始化结构体
  • 配置ADC时钟,配置通道的转换顺序和采样时间
  • 使能ADC转换完成中断,配置中断优先级

配置过程相同,只不过初始化IO口时需要初始化多个IO口通道。并且调用函数ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 1, ADC_SampleTime_480Cycles );  获取多个通道执行多个功能即可。

7. 相关寄存器

7.1 ADC控制寄存器:ADC_CR1和ADC_CR2

ADC控制寄存器1:ADC_CR1(ADC control register 1)

SCAN位:设置扫描模式位,通过软件将该位置1或者清零可以使能/禁止扫描模式。 在扫描模式下,转换由规则序列寄存器ADC_SQRx注入序列寄存器ADC_JSQRx选中的通道被转换 。

        0:禁止扫描模式

        1:使能扫描模式

如果设置了EOCIE和JEOCIE,只在最后一个通道转换完毕后才会产生EOC和JEOC中断。

RES位[1:0]:通过该位来设置分辨率(Resolution)

        00:12位(15 ADCCLK周期)

        01:10位(13 ADCCLK周期)

        10:8位(11 ADCCLK周期)

        11:6位(9 ADCCLK周期)

ADC控制寄存器2:ADC_CR2(ADC control register 2)

ADON位:设置A/D转换器开启或者关闭

        0:禁止ADC转换并转至掉电模式

        1:使能ADC

CONT位:该位用来设置连续转换模式或者单次转换模式

        0:单次转换模式

        1:连续转换模式

ALIGN位:该位用来设置数据是左对齐还是右对齐

        0:右对齐

        1:左对齐

EXTEN位:该位用来设置规则通道的外部触发是否使能

        00:禁止触发检测

        01:上升沿上的触发检测

        10:下降沿上的触发检测

        11:上升沿和下降沿上的触发检测

SWSTART位:用于开始规则通道的转换,我们每次转换(单次转换模式下)都需要向该位写1

        0:复位状态

        1:开始转换规则通道

7.2 ADC通用控制寄存器:ADC_CCR

ADC通用控制寄存器:ADC_CCR(ADC common control register)

TSVREFE位:温度传感器和V_{REFINT}使能位

        0:禁止

        1:使能

ADCPRE位:ADC预分频器,该位由软件置1或者清0,以选择ADC的时钟频率。该时钟为所有ADC所共有。

        00:PCLK2    2分频

        01:PCLK2    4分频

        10:PCLK2    6分频

        11:PCLK2    8分频     STM32的ADC最大工作频率为36Mhz,而ADC时钟来自于APB2,APB2频率一般是84Mhz,所以一般的我们置ADCPRE=01,即4分频,这样得到ADCPRE频率为21Mhz。

MULTI位:该位用来选择ADC的多重模式,本次实验我们使用的是独立模式,将该5位置0即可

  • 所有 ADC 均独立:
  • 00000:独立模式
  • 00001 到 01001:双重模式,ADC1 和 ADC2 一起工作,ADC3 独立
  • 00001:规则同时 + 注入同时组合模式
  • 00010:规则同时 + 交替触发组合模式
  • 00011:Reserved
  • 00101:仅注入同时模式
  • 00110:仅规则同时模式 仅交错模式
  • 01001:仅交替触发模式
  • 10001 到 11001:三重模式:ADC1、ADC2 和 ADC3 一起工作
  • 10001:规则同时 + 注入同时组合模式
  • 10010:规则同时 + 交替触发组合模式
  • 10011:Reserved
  • 10101:仅注入同时模式
  • 10110:仅规则同时模式 仅交错模式
  • 11001:仅交替触发模式 

7.3 ADC采样时间寄存器:ADC_SMPR1和ADC_SMPR2

这两个寄存器用于设置通道0~18的采样时间,每个通道占用3个位

ADC采样时间寄存器:ADC_SMPR1(ADC sample time register 1)

ADC采样时间寄存器:ADC_SMPR2(ADC sample time register 2)

采样时间通俗的讲就是收集模拟量的时间,为了保证转换后的数字量更加精准,采样时间通常设置的尽量长一些。由此带来的负面影响会降低ADC的转换效率。

        ADC转换时间计算:T_{Conv}=采样时间+12个周期

7.4 ADC规则序列寄存器:ADC_SQRx(x取值1~3)

ADC规则序列寄存器1:ADC_SQR1(ADC regular sequence register 1)

L位:规则通道序列长度

        0000:1次转换

        0001:2次转换

        ……

        1111:16次转换

SQx位:分别对应规则序列中的第x次转换(x取值13 14 15 16)其余的1~12分别位于ADC规则序列寄存器2和3中

7.5 ADC规则数据寄存器:ADC_DR

ADC规则数据寄存器:ADC_DR(ADC regular data register)

DATA位: 规则数据位,这些位为只读,它们包括来自规则通道的转换结果。

注意:ADC转换完成后的数字量会存储在该寄存器中,且该寄存器的存储值受ADC_CR2的ALIGN位设置的左对齐还是右对齐控制,所以在读取时需要特别注意。

7.6 ADC状态寄存器:ADC_SR

ADC状态寄存器:ADC_SR(ADC status register)

EOC位: 通过该位来决定是否此次规则通道的AD转换已完成,如果该位为1,则表示转换已经完成了,这时就可以从ADC_DR中读取转换结果,否则等待转换完成。

8. 库函数配置ADC1的通道5进行AD转换 

1. 开启PA口时钟和ADC1时钟,设置PA5为模拟输入

STM32F407ZG的ADC12通道IN5位于引脚PA5上,所以我们要使能GPIOA时钟和ADC1时钟。

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);     //使能GPIOA时钟 

RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);       //使能ADC1时钟 

注意:对于IO口复用的ADC我们要设置模式为模拟输入,而不是复用功能。

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;      //模拟输入 

2. 设置ADC的通用控制寄存器CCR,配置ADC输入时钟分频,模式为独立模式

在库函数中, 初始化CCR寄存器是通过调用ADC_CommonInit来实现的;

typedef struct 
{
  uint32_t ADC_Mode;              //ADC模式 通过ADC_CR1:DUALMOD位来配置                                                 
  uint32_t ADC_Prescaler;              //ADC预分频值                       
  uint32_t ADC_DMAAccessMode;           //DMA模式禁止或者使能相应的DMA模式
  uint32_t ADC_TwoSamplingDelay;        //ADC两个采样阶段之间的延迟周期数
}ADC_CommonInitTypeDef;


第一个参数ADC_Mode:设置独立模式还是多重模式
第二个参数ADC_Prescaler:设置ADC预分频器,这里设置时一定保证ADC1的时钟频率不超过36MHz
第三个参数ADC_DMAAccessMode:DMA模式禁止或者使能相应的DMA模式
第四个参数ADC_TwoSamplingDelay:设置ADC两个采样阶段之间的延迟周期数

void ADC_CommonInit(ADC_CommonInitTypeDef* ADC_CommonInitStruct) 

ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;     //独立模式 

ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;    //ADC预分频值

ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;   //ADC的DMA模式禁止或者使能相应DMA模式

ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; 

3. 初始化ADC1参数,设置ADC1的转换分辨率,转换方式,对齐方式,以及规则序列等相关信息

void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct)  //初始化ADC函数

typedef struct
{
  uint32_t ADC_Resolution;         //ADC分辨率                                        
  FunctionalState ADC_ScanConvMode;     //ADC扫描多通道或者ADC单通道模式选择  通过ADC_CR1的SCAN位来配置
  FunctionalState ADC_ContinuousConvMode;   //ADC单次转换或者连续转换选择 通过ADC_CR2的CON位来配置
  uint32_t ADC_ExternalTrigConvEdge;      //ADC转换触发信号范围选择
  uint32_t ADC_ExternalTrigConv;          //ADC外部触发转换模式选择  通过ADC_CR2的EXTTRIG和EXTSEL位来配置
  uint32_t ADC_DataAlign;                 //ADC数据寄存器对齐格式
  uint8_t  ADC_NbrOfConversion;           //ADC采集通道数
}ADC_InitTypeDef;

第一个参数ADC_Resolution:设置ADC转换分辨率
第二个参数ADC_ScanConvMode:设置是否打开扫描模式
第三个参数ADC_ContinuousConvMode:设置时单次转换模式还是连续转换模式
第四个参数ADC_ExternalTrigConvEdge:设置外部通道的触发使能和检测方式
第五个参数ADC_ExternalTrigConv:设置ADC外部触发转换模式
第六个参数ADC_DataAlign:设置数据对齐方式  是左对齐还是右对齐
第七个参数ADC_NbrOfConversion:设置规则序列的长度   单次转换

ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//12位模式 

ADC_InitStructure.ADC_ScanConvMode = DISABLE;//非扫描模式 

ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//关闭连续转换 

ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; //禁止触发检测,使用软件触发 

ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//右对齐

ADC_InitStructure.ADC_NbrOfConversion = 1;//1个转换在规则序列中 

ADC_Init(ADC1, &ADC_InitStructure);//ADC初始化

4. 开启AD转换器

开启AD转换器通过ADC_CR2寄存器控制

ADC_Cmd(ADC1, ENABLE);//开启AD转换器

5. 读取ADC值

void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel,  uint8_t Rank, uint8_t ADC_SampleTime);

                                                                                                                                                                              // 设置规则序列通道及采样周期

ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 1, ADC_SampleTime_480Cycles );   //规则序列中的第一个转换,采样周期设置为480

ADC_SoftwareStartConvCmd(ADC1);          //使能指定的ADC1的软件转换启动功能 

ADC_GetConversionValue(ADC1);       //获取转换ADC转换结果数据

FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG)    //获取AD转换的状态信息函数

        ag.  while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束 

9. 实验程序

该实验需要用杜邦线将PA5引脚接到GND或者3.3V上,测其电压原始值和转化后的值,切记不能接5.5V,会损坏开发板的ADC;

9.1 main.c

#include "stm32f4xx.h"
#include "delay.h"
#include "usart.h"
#include "LED.h"
#include "lcd.h"
#include "usmart.h"
#include "Key.h"
#include "ADC.h"

//LCD状态设置函数
void led_set(u8 sta)//只要工程目录下有usmart调试函数,主函数就必须调用这两个函数
{
	LED1=sta;
}
//函数参数调用测试函数
void test_fun(void(*ledset)(u8),u8 sta)
{
	led_set(sta);
}

int main(void)
{
	u16 adcx;
	float temp;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	delay_init(168);
	uart_init(115200);
	LED_Init();
	LCD_Init();
	Adc_Init();
	POINT_COLOR=RED;
	LCD_ShowString(30,50,200,16,16,"Explorer STM32F4");
	LCD_ShowString(30,70,200,16,16,"ADC TEST");
	LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");
	LCD_ShowString(30,110,200,16,16,"2023/20/23");
	POINT_COLOR=BLUE;
	LCD_ShowString(30,130,200,16,16,"ADC1_CH5_VAL:");
	LCD_ShowString(30,150,200,16,16,"ADC1_CH5_VOL:0.000V");  //显示小数点
	while(1)
	{
		adcx=Get_Adc_Average(ADC_Channel_5,20);//adc通道5,取20次平均值
		LCD_ShowxNum(134,130,adcx,4,16,0); //显示ADC采样后的原始值
		temp=(float)adcx*(3.3/4096);  //获取计算后带小数的实际电压值,如3.1111
		adcx=temp;  //赋值整数部分给adcx
		LCD_ShowxNum(134,150,adcx,1,16,0);//显示电压值的整数部分
		temp=temp-adcx; //把已经显示的整数部分去掉,留下小数部分 3.1111-3=0.1111
		temp=temp*1000;//把小数部分乘以1000,变成整数打印出来,乘以1000相当于保留3位小数,乘以10000相当于保留四位小数
		LCD_ShowxNum(150,150,temp,3,16,0x80); //显示小数部分
		LED0=!LED0;
		delay_ms(250);
	}
}

9.2 ADC.c

#include "stm32f4xx.h"                
#include "ADC.h"
#include "delay.h"

//初始化ADC
void Adc_Init(void)
{
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);//使能GPIOA时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);// 使能ADC1时钟
	
	//初始化ADC1通道5 IO口
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AN;  //模式为模拟输入
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;  //PA5 通道5
	GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL; //不带上下拉
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1,ENABLE);   //ADC1复位
	RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1,DISABLE);    //复位结束
	
	//初始化CCR通用控制寄存器配置
	ADC_CommonInitTypeDef ADC_CommonInitStructure;
	ADC_CommonInitStructure.ADC_DMAAccessMode=ADC_DMAAccessMode_Disabled; //DMA失能
	ADC_CommonInitStructure.ADC_Mode=ADC_Mode_Independent;  //独立模式
	ADC_CommonInitStructure.ADC_Prescaler=ADC_Prescaler_Div4;  //预分频值设置
	ADC_CommonInitStructure.ADC_TwoSamplingDelay=ADC_TwoSamplingDelay_5Cycles;//两个采样阶段之间延迟5个时钟
	ADC_CommonInit(&ADC_CommonInitStructure);
	
	//初始化ADC1相关参数
	ADC_InitTypeDef ADC_InitStructure;
	ADC_InitStructure.ADC_ContinuousConvMode=DISABLE;  //关闭连续转换
	ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;  //右对齐
	ADC_InitStructure.ADC_ExternalTrigConvEdge=ADC_ExternalTrigConvEdge_None; //禁止触发检测,使用软件触发
	ADC_InitStructure.ADC_NbrOfConversion=1;  //1个转换在规则序列中
	ADC_InitStructure.ADC_Resolution=ADC_Resolution_12b;  //12位模式
	ADC_InitStructure.ADC_ScanConvMode=DISABLE; //非扫描模式
	ADC_Init(ADC1,&ADC_InitStructure); //ADC初始化
	
	ADC_Cmd(ADC1,ENABLE);   //开启AD转换器
}
//获取ADC值
//ch:通道值 0~16
//返回值:转换结果
u16 Get_Adc(u8 ch)
{
	ADC_RegularChannelConfig(ADC1,ch,1,ADC_SampleTime_480Cycles);//设置ADC规则组通道,一个序列,采样时间480
	ADC_SoftwareStartConv(ADC1);//使能指定的ADC1的软件转换启动功能
	while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));//读取状态寄存器的状态位EOC,等待转换结束
	return ADC_GetConversionValue(ADC1);//返回最近一次的ADC1规则组的转换结果
}
//获取通道ch的转换值,取times次,然后平均
//ch:通道编号  times:获取次数
//返回值:通道ch的times次转换结果平均值
u16 Get_Adc_Average(u8 ch,u8 times)
{
	u32 temp_val=0;
	u8 t;
	for(t=0;t<times;t++)
	{
		temp_val=temp_val+Get_Adc(ch); //取times次通道值进行求和
		delay_ms(5);
	}
	return temp_val/times; //返回平均值
}


9.3 ADC.h

#ifndef _ADC__H_
#define _ADC__H_

void Adc_Init(void);
u16 Get_Adc(u8 ch);
u16 Get_Adc_Average(u8 ch,u8 times);

#endif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/444662.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Deep Neural Network for YouTube Recommendation论文精读

这篇论文 Deep Neural Networks for YouTube Recommendations 是google的YouTube团队在推荐系统上DNN方面的尝试&#xff0c;发表在16年9月的RecSys会议。本文所介绍的YouTube的推荐系统主要包括Deep Candidate Generation model和Deep Ranking model两个部分&#xff1a;Deep …

AWS EC2使用过程总结

步骤1&#xff1a;开通AWS账号 需要一个邮箱、一个信用卡账号&#xff1b;有第一年的免费试用&#xff0c;EC2每个月免费试用750小时&#xff1b;注册完成后&#xff0c;得到实例管理平台&#xff1a; 步骤2&#xff1a;开通EC2实例 步骤3&#xff1a;开通网关和安全组&…

【Python小技巧】一步到位升级到pandas 2.0.0正式版

文章目录 前言一、Pandas是什么&#xff1f;二、Pandas 2.0.0的升级特性三、升级安装Pandas 2.0.0正式版总结 前言 工欲善其事必先利其器&#xff0c;大数据、AI时代&#xff0c;目前Python 最新版本是3.11 &#xff0c;而Pandas也刚刚完成大升级&#xff0c;进入 2.0.0时代。…

ChatGPT 中的人类反馈强化学习 (RLHF) 实战

目录 1 前言2 人类反馈强化学习 (RLHF)2.1 奖励模型 (RM)2.2 近端策略优化算法 (PPO) 3 总结4 参考 团队博客: CSDN AI小组 相关阅读 ChatGPT 简介大语言模型浅探一关于 ChatGPT 必看的 10 篇论文从 ELMo 到 ChatGPT&#xff1a;历数 NLP 近 5 年必看大模型 1 前言 在当今数字…

整型、浮点型与字符串相互转换(C/C++)

文章目录 1. 整型、浮点型 -> 字符串2. 字符串 -> 整型3.字符串 -> 浮点型 1. 整型、浮点型 -> 字符串 A. 函数原型&#xff1a;   B. 分析  通常整型转换一般都是准确的&#xff0c;但是浮点型进行转换的时候因为精度问题有效数字位可能会出现一些偏差.   C. …

pushmall推贴共享电商2023年4月计划

Pushmall推贴共享电商2023年4月计划 2023年 二月份优化完成 1、商圈套餐卡&#xff1a;商品、优惠券、活动优化&#xff1b; 2、会员预充值一卡通&#xff1a;指定商家会员卡充值优惠&#xff1b; 3、商家海报&#xff1a;店铺海报、商品海报、商圈卡海报优化。 4、首页重新布…

SpringBoot(5)整合缓存

Springboot整合缓存 缓存SpringBoot内置缓存整合Ehcache缓存数据淘汰策略整合Memcached缓存SpringBoot整合jetcache缓存纯远程方案纯本地方案本地远程方案方法缓存远程方案的数据同步数据报表 SpringBoot整合j2cache缓存 缓存 企业级应用主要作用是信息处理&#xff0c;当需要…

【STM32】基础知识 第六课 内核 架构

【STM32】基础知识 第六课 内核 & 架构 F1 系统架构F4 系统架构F7 系统架构H7 系统架构 F1 系统架构 4 个主动单元 4 个被动单元 主动单元被动单元Cortex M3 内核 DCode 总线 (D-Bus)内部 FLASHCortex M3 内核系统总线 (S-Bus)内部 SRAM通用 DMA1FSMC通用 DMA2AHB 到 AP…

PCA主成分分析 从零理解

一、PCA的目的 假设我们有一堆观测到的数据。 数据的格式是observation*feature&#xff0c;每一行是一个观测&#xff08;也就是图里的一个点&#xff09;&#xff0c;每一列是这个数据的某个特征&#xff08;即一个维度&#xff09;。 假设数据矩阵是A&#xff0c;有m个观测…

辉煌优配|刚刚!“中字头”再度爆发

今天早盘&#xff0c;A股全体持续震动收拾&#xff0c;上证50指数跌破2700点整数关口&#xff0c;沪深300亦失守4100点。 盘面上&#xff0c;国防军工、种业、中字头、电气设备等板块涨幅居前&#xff0c;前期抢手的人工智能、半导体、信创、软件服务等板块全线回调。北上资金净…

零售店铺管理系统有哪些作用?选择零售管理系统要注意这4大问题

零售店铺管理系统主要是帮助实体零售店提高销售效率、降低成本、提升服务质量和客户满意度。 对于零售店铺来说&#xff0c;选择一款合适的零售店铺管理系统&#xff0c;可以有效提高其管理效率和精准度&#xff0c;同时也有利于自家店铺在市场竞争中占据优势。 一、零售店铺管…

Keil系列教程02_新建基础软件工程

1写在前面 目前Keil的四款产品&#xff08;软件&#xff09;&#xff1a;MDK-ARM、C51、C251、C166&#xff0c;在用法上极为相似&#xff0c;包括本文讲述的新建软件工程。 本文以目前&#xff08;2018年10月&#xff09;最新Keil MDK-ARM V5.26、STM32F103标准外设库为例&am…

晨控CK-FR208-PN与西门子PLC工业Profinet协议通讯指南

晨控CK-FR208-PN是一款支持标准工业Profinet协议的多通道工业RFID读写器&#xff0c;读卡器工作频率为13.56MHZ&#xff0c;支持对I-CODE 2、I-CODE SLI等符合ISO15693国际标准协议格式标签的读写。 读卡器同时支持标准工业通讯协议Profinet&#xff0c;方便用户通集成到PLC等…

电子模块|外控集成 LED 光源 WS2812模块---软件驱动stm32版

电子模块|外控集成 LED 光源 WS2812模块---软件驱动stm32版 模块简介单线归零码通讯方式24bit 数据结构 stm32 驱动 模块简介 WS2812是一个集控制电路与发光电路于一体的智能外控LED光源。其外型与一个5050LED灯珠相同&#xff0c;每个元件即为一个像素点。像素点内部包含了智…

CxImage学习使用1:环境搭建

目录 前言 一、CxImage相关介绍 二、编译源码 三、将CxImage使用到自己的工程中 前言 CxImage是一个可以用于MFC 的C图像处理类库类&#xff0c;它可以打开&#xff0c;保存&#xff0c;显示&#xff0c;转换各种常见格式的图像文件&#xff0c;比如BMP, JPEG, GIF, PNG, TI…

“cnpm : 无法加载文件 C:\Users\xx\AppData\Roaming\npm\cnpm.ps1,因为在此系统上禁止运行脚本“ 解决办法

系统安全策略原因导致cnpm安装依赖包的时候提示以下错误&#xff0c;解决方案&#xff1a; 错误详情&#xff1a; cnpm : 无法加载文件 C:\Users\xx\AppData\Roaming\npm\cnpm.ps1&#xff0c;因为在此系统上禁止运行脚本。有关详细信息&#xff0c;请参阅 https:/go.microsof…

大家经常说的java八股文到底是什么?让我来总结一下吧!

八股文问题集合 面试必看java八股文 问题正在收录中&#xff0c;累了休息一会&#xff0c;如果有需要请&#xff0c;先关注&#xff0c;这几天会更帖子&#xff0c;答案后续补上 文章目录 八股文问题集合问题正在收录中&#xff0c;累了休息一会&#xff0c;如果有需要请&#…

AI大数据可视化EasyCVR视频融合平台的部署操作流程详解

EasyCVR视频融合平台基于云边端一体化架构&#xff0c;具有强大的数据接入、处理及分发能力&#xff0c;平台支持海量视频汇聚管理&#xff0c;能在复杂的网络环境中&#xff0c;将分散的各类视频资源进行统一汇聚、整合、集中管理&#xff0c;实现视频直播、云端录像、云存储、…

使用MyBatis实现CRUD操作

文章目录 简介&#xff08;一&#xff09;学习方向&#xff08;二&#xff09;学习事项 一&#xff0c;准备工作二&#xff0c;查询表记录&#xff08;一&#xff09;在映射器配置文件里引入结果映射元素&#xff08;二&#xff09;添加按姓名查询用户记录功能1&#xff0c;添加…

day02_第一个Java程序

在开发第一个Java程序之前&#xff0c;我们必须对计算机的一些基础知识进行了解。 常用DOS命令 Java语言的初学者&#xff0c;学习一些DOS命令&#xff0c;会非常有帮助。DOS是一个早期的操作系统&#xff0c;现在已经被Windows系统取代&#xff0c;对于我们开发人员&#xf…