1)实验平台:alientek NANO STM32F411 V1开发板2)摘自《正点原子STM32F4 开发指南(HAL 库版》关注官方微信号公众号,获取更多资料:正点原子

正点原子stm32芯片包(STM32开发板资料连载)(1)

第二十一章 ADC 实验

本章我们将向大家介绍 STM32F4 的 ADC 功能。在本章中,我们将利用 STM32F4 的 ADC1

通道 9 来采样外部电压值,并在数码管上显示出来。本章将分为如下几个部分:

21.1 STM32F4 ADC 简介

21.2 硬件设计

21.3 软件设计

21.4 下载验证

21.1 STM32F4 ADC 简介

STM32F411xC/E 只拥有 1 个 ADC。STM32F4 的 ADC 是 12 位逐次逼近型的模拟数字转换器。它有 19 个通道,可测量 16 个外部和 2 个内部信号源和 Vbat 通道的信号。各通道的 A/D 转换可以单次、连续、扫描或间断模式执行。ADC 的结果可以左对齐或右对齐方式存储在 16 位数据寄存器中。模拟看门狗特性允许应用程序检测输入电压是否超出用户定义的高/低阀值。

STM32F411xC/E 系列只有有 1 个 ADC,我们选择的 STM32F411RCT6 包含有 1 个 ADC。

STM32F4 的 ADC 最大的转换速率为 2.4Mhz,也就是转换时间为 1us(在 ADCCLK=36M,采样周期为 3 个 ADC 时钟下得到),不要让 ADC 的时钟超过 36M,否则将导致结果准确度下降。STM32F4 将 ADC 的转换分为 2 个通道组:规则通道组和注入通道组。规则通道相当于你正常运行的程序,而注入通道呢,就相当于中断。在你程序正常执行的时候,中断是可以打断你的执行的。同这个类似,注入通道的转换可以打断规则通道的转换, 在注入通道被转换完成之后,规则通道才得以继续转换。通过一个形象的例子可以说明:假如你在家里的院子内放了 5 个温度探头,室内放了 3个温度探头;你需要时刻监视室外温度即可,但偶尔你想看看室内的温度;因此你可以使用规则通道组循环扫描室外的 5 个探头并显示 AD 转换结果,当你想看室内温度时,通过一个按钮启动注入转换组(3 个室内探头)并暂时显示室内温度,当你放开这个按钮后,系统又会回到规则通道组继续检测室外温度。从系统设计上,测量并显示室内温度的过程中断了测量并显示室外温度的过程,但程序设计上可以在初始化阶段分别设置好不同的转换组,系统运行中不必再变更循环转换的配置,从而达到两个任务互不干扰和快速切换的结果。可以设想一下,如果没有规则组和注入组的划分,当你按下按钮后,需要从新配置 AD 循环扫描的通道,然后在释放按钮后需再次配置 AD 循环扫描的通道。上面的例子因为速度较慢,不能完全体现这样区分(规则通道组和注入通道组)的好处,但在工业应用领域中有很多检测和监视探头需要较快地处理,这样对 AD 转换的分组将简化事件处理的程序并提高事件处理的速度。

STM32F4 其 ADC 的规则通道组最多包含 16 个转换,而注入通道组最多包含 4 个通道。

关于这两个通道组的详细介绍,请参考《STM32F411xC/E 参考手册》第 219 页,第 11 章。

STM32 的 ADC 可以进行很多种不同的转换模式,这些模式在《STM32F411xC/E 参考

手册》的第 11 章也都有详细介绍,我们这里就不在一一列举了。我们本章仅介绍如何使用

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

以规则通道为例,一旦所选择的通道转换完成,转换结果将被存在 ADC_DR 寄存器中,

EOC(转换结束)标志将被置位,如果设置了 EOCIE,则会产生中断。然后 ADC 将停止,

直到下次启动。

接下来,我们介绍一下我们执行规则通道的单次转换,需要用到的 ADC 寄存器。第一

个要介绍的是 ADC 控制寄存器(ADC_CR1 和 ADC_CR2)。ADC_CR1 的各位描述如图 21.1.1

所示:

正点原子stm32芯片包(STM32开发板资料连载)(2)

图 21.1.1 ADC_CR1 寄存器各位描述

这里我们不再详细介绍每个位,而是抽出几个我们本章要用到的位进行针对性的介绍,

详细的说明及介绍,请参考《STM32F411xC/E 参考手册》第 11 章的相关章节。

ADC_CR1 的 SCAN 位,该位用于设置扫描模式,由软件设置和清除,如果设置为 1,

则使用扫描模式,如果为 0,则关闭扫描模式。在扫描模式下,由 ADC_SQRx 或 ADC_JSQRx

寄存器选中的通道被转换。如果设置了 EOCIE 或 JEOCIE,只在最后一个通道转换完毕后才

会产生 EOC 或 JEOC 中断。

ADC_CR1[19:16]用于设置 ADC 的操作模式,详细的对应关系如图 21.1.2 所示:

正点原子stm32芯片包(STM32开发板资料连载)(3)

图 21.1.2 ADC 操作模式

本章我们要使用的是 12 位分辨率,所以设置这几位为 0 就可以了。接着我们介绍

ADC_CR2,该寄存器的各位描述如图 21.1.3 所示:

正点原子stm32芯片包(STM32开发板资料连载)(4)

图 21.1.3 ADC_CR2 寄存器操作模式

该寄存器我们也只针对性的介绍一些位:ADON 位用于开关 AD 转换器。而 CONT 位

用于设置是否进行连续转换,我们使用单次转换,所以 CONT 位必须为 0。ALIGN 用于设

置数据对齐,我们使用右对齐,该位设置为 0。

EXTEN[1:0]用于规则通道的外部触发使能设置,详细的设置关系如图 21.1.4 所示:

正点原子stm32芯片包(STM32开发板资料连载)(5)

图 21.1.4 ADC 选择启动规则转换事件设置

我们这里使用的是软件触发,即不使用外部触发,所以设置这2个位为0即可。ADC_CR2

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

写 1。

第二个要介绍的是 ADC 通用控制寄存器(ADC_CCR),该寄存器各位描述如图 21.1.5所示:

正点原子stm32芯片包(STM32开发板资料连载)(6)

图 21.1.5 ADC_CCR 寄存器各位描述

该寄存器我们也只针对性的介绍一些位:TSVREFE 位是内部温度传感器和 Vrefint 通道

使能位,这里我们直接设置为 0。ADCPRE[1:0]用于设置 ADC 输入时钟分频,00~11 分别对

应 2/4/6/8 分频,STM32F4 的 ADC 最大工作频率是 36Mhz,而 ADC 时钟(ADCCLK)来

自 APB2,APB2 频率一般是 96Mhz,所以我们一般设置 ADCPRE=01,即 4 分频,这样得

到 ADCCLK 频率为 24Mhz。

第三个要介绍的是 ADC 采样时间寄存器(ADC_SMPR1 和 ADC_SMPR2),这两个寄

存器用于配置通道 0~18 的采样时间,每个通道占用 3 个位。ADC_SMPR1 各位描述如图

21.1.6 所示:

正点原子stm32芯片包(STM32开发板资料连载)(7)

图 21.1.6 ADC_ SQR1 寄存器各位描述

ADC_SMPR2 的各位描述如下图 21.1.7 所示:

正点原子stm32芯片包(STM32开发板资料连载)(8)

图 21.1.7 ADC_SMPR2 寄存器各位描述

对于每个要转换的通道,采样时间建议尽量长一点,以获得较高的准确度,但是这样会

降低 ADC 的转换速率。ADC 的转换时间可以由以下公式计算:

Tcovn=采样时间 12 个周期

其中:Tcovn 为总转换时间,采样时间是根据每个通道的 SMP 位的设置来决定的。例

如,当 ADCCLK=21Mhz 的时候,并设置 3 个周期的采样时间,则得到:Tcovn=3 12=15

个周期=0.71us。

第四个要介绍的是 ADC 规则序列寄存器(ADC_SQR1~3),该寄存器总共有 3 个,这几

个寄存器的功能都差不多,这里我们仅介绍一下 ADC_SQR1,该寄存器的各位描述如图

21.1.8 所示:

正点原子stm32芯片包(STM32开发板资料连载)(9)

图 21.1.8 ADC_ SQR1 寄存器各位描述

L[3:0]用于存储规则序列的长度,我们这里只用了 1 个,所以设置这几个位的值为 0。其他的 SQ13~16 则存储了规则序列中第 13~16 个通道的编号(0~18)。另外两个规则序列

寄存器同 ADC_SQR1 大同小异,我们这里就不再介绍了,要说明一点的是:我们选择的是

单次转换,所以只有一个通道在规则序列里面,这个序列就是 SQ1,至于 SQ1 里面那个通

道,完全由用户自己设置,通过 ADC_SQR3 的最低 5 位(也就是 SQ1)设置。

第五个要介绍的是 ADC 规则数据寄存器(ADC_DR)。规则序列中的 AD 转化结果都将

被存在这个寄存器里面,而注入通道的转换结果被保存在 ADC_JDRx 里面。ADC_DR 的各

位描述如图 21.1.9:

这里要提醒一点的是,该寄存器的数据可以通过 ADC_CR2 的 ALIGN 位设置左对齐还

是右对齐。在读取数据的时候要注意。

最后一个要介绍的 ADC 寄存器为 ADC 状态寄存器(ADC_SR),该寄存器保存了 ADC

转换时的各种状态。该寄存器的各位描述如图 21.1.10 所示:

正点原子stm32芯片包(STM32开发板资料连载)(10)

图 21.1.10 ADC_ SR 寄存器各位描述

这里我们要用到的是 EOC 位,我们通过判断该位来决定是否此次规则通道的 AD 转换

已经完成,如果该位位 1,则表示转换完成了,就可以从 ADC_DR 中读取转换结果,否则

等待转换完成。

至此,本章要用到的 ADC 相关寄存器全部介绍完毕了,对于未介绍的部分,请大家参

考《STM32F411xC/E 参考手册》第 11 章相关章节。通过以上寄存器的介绍,我们了解了

STM32 的单次转换模式下的相关设置,下面我们介绍使用库函数的函数来设定使用 ADC1

的通道 1 进行 AD 转换。这里需要说明一下,使用到的库函数分布在 stm32f4xx_hal_adc.c

文件和 stm32f4xx_hal_adc.h 文件中。下面讲解其详细设置步骤:

1)开启 PB 口时钟和 ADC1 时钟,设置 PB1 为模拟输入。

STM32F411RCT6 的 ADC 通道 9 在 PB1 上,所以,我们先要使能 PORTB 的时钟和 ADC1

时钟,然后设置 PB1 为模拟输入。

这里特别要提醒,对于 IO 口复用为 ADC 我们要设置模式为模拟输入,而不是复用功

能。

使能 GPIOB 时钟和 ADC1 时钟都很简单,具体方法为:

__HAL_RCC_ADC1_CLK_ENABLE();

//使能 ADC1 时钟

__HAL_RCC_GPIOB_CLK_ENABLE();

//开启 GPIOB 时钟

初始化 GPIOB1 为模拟输入,方法也多次讲解,关键代码为:

GPIO_InitTypeDef GPIO_Initure;

GPIO_Initure.Pin=GPIO_PIN_1;

//PB1

GPIO_Initure.Mode=GPIO_MODE_ANALOG; //模拟输入

GPIO_Initure.Pull=GPIO_NOPULL;

//不带上下拉

HAL_GPIO_Init(GPIOB,&GPIO_Initure);

2)初始化 ADC,设置 ADC 时钟分频系数,分辨率,模式,扫描方式,对齐方式等信

息。

在 HAL 库中,初始化 ADC 是通过函数 HAL_ADC_Init 来实现的,该函数声明为:

HAL_StatusTypeDef HAL_ADC_Init(ADC_HandleTypeDef* hadc);

该函数只有一个入口参数 hadc,为 ADC_HandleTypeDef 结构体指针类型,结构体定义

为:

typedef struct

{

ADC_TypeDef

*Instance;

//ADC1/ ADC2/ ADC3

ADC_InitTypeDef

Init;

//初始化结构体变量

__IO uint32_t

NbrOfCurrentConversionRank; //当前转换序列

DMA_HandleTypeDef

*DMA_Handle; //DMA 方式使用

HAL_LockTypeDef

Lock;

__IO uint32_t

State;

__IO uint32_t

ErrorCode;

}ADC_HandleTypeDef;

该结构体定义和其他外设比较类似,我们着重看第二个成员变量 Init 含义,它是结构体

ADC_InitTypeDef 类型,结构体 ADC_InitTypeDef 定义为:

typedef struct

{

uint32_t ClockPrescaler;//分频系数 2/4/6/8 分频 ADC_CLOCK_SYNC_PCLK_DIV4

uint32_t Resolution;

//分辨率 12/10/8/6 位:ADC_RESOLUTION_12B

uint32_t DataAlign;

//对齐方式:左对齐还是右对齐:ADC_DATAALIGN_RIGHT

uint32_t ScanConvMode; //扫描模式 DISABLE

uint32_t EOCSelection; //EOC 标志是否设置 DISABLE

uint32_t ContinuousConvMode;//开启连续转换模式或者单次转换模式 DISABLE

uint32_t NbrOfConversion; //规则序列中有多少个转换 1

uint32_t DiscontinuousConvMode;//不连续采样模式 DISABLE

uint32_t NbrOfDiscConversion;//不连续采样通道数 0

uint32_t ExternalTrigConv; //外部触发方式 ADC_SOFTWARE_START

uint32_t ExternalTrigConvEdge;//外部触发边沿

uint32_t DMAContinuousRequests;//开启 DMA 请求连续模式或者单独模式 DISABLE

}ADC_InitTypeDef;

我们直接把每个成员变量含义注释在结构体定义的后面,请大家仔细阅读上面注释。

这里我们需要说明一下,和其他外设一样,HAL 库同样提供了 ADC 的 MSP 初始化函

数,一般情况下,时钟使能和 GPIO 初始化都会放在 MSP 初始化函数中。函数声明为:

void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc);

3)开启 AD 转换器。

在设置完了以上信息后,我们就开启 AD 转换器了(通过 ADC_CR2 寄存器控制)。

HAL_ADC_Start(&ADC1_Handler); //开启 ADC

4)配置通道,读取通道 ADC 值。

在上面的步骤完成后,ADC 就算准备好了。接下来我们要做的就是设置规则序列 1 里

面的通道,然后启动 ADC 转换。在转换结束后,读取转换结果值值就是了。

设置规则序列通道以及采样周期的函数是:

HAL_StatusTypeDef HAL_ADC_ConfigChannel(ADC_HandleTypeDef* hadc,

ADC_ChannelConfTypeDef* sConfig);

该函数有两个入口参数,第一个就不用多说了,接下来我们看看第二个入口参数

sConfig,它是 ADC_ChannelConfTypeDef 结构体指针类型,结构体定义如下:

typedef struct

{

uint32_t Channel;

//ADC 通道

uint32_t Rank;

//规则通道中的第几个转换

uint32_t SamplingTime;

//采样时间

uint32_t Offset;

//备用,暂未用到

}ADC_ChannelConfTypeDef;

该结构体有四个成员变量,对于 STM32F4 只用到前面三个。Channel 用来设置 ADC 通

道,Rank 用来设置要配置的通道是规则序列中的第几个转换,SamplingTime 用来设置采样

时间。使用实例为:

ADC1_ChanConf.Channel= ADC_CHANNEL_9; //通道 9

ADC1_ChanConf.Rank=1;

//第 1 个序列,序列 1

ADC1_ChanConf.SamplingTime=ADC_SAMPLETIME_480CYCLES; //采样时间

ADC1_ChanConf.Offset=0;

HAL_ADC_ConfigChannel(&ADC1_Handler,&ADC1_ChanConf); //通道配置

配置好通道并且使能 ADC 后,接下来就是读取 ADC 值。这里我们采取的是查询方式

读取,所我们还要等待上一次转换结束。次过程 HAL 库提供了专用函数

HAL_StatusTypeDef HAL_ADC_PollForConversion(ADC_HandleTypeDef* hadc,

uint32_t Timeout);

等待上一次转换结束之后,接下来就是读取 ADC 值,函数为:

uint32_t HAL_ADC_GetValue(ADC_HandleTypeDef* hadc);

这两个函数的使用方法都比较简单,这里我们就不累赘了。

这 里 还 需 要 说 明 一 下 ADC 的 参 考 电 压 , NANO STM32 开 发 板 使 用 的 是

STM32F411RCT6,该芯片的参考电压引脚为 Vref ,我们直接 3.3V 为参考电压。

通过以上几个步骤的设置,我们就能正常的使用 STM32F4 的 ADC1 来执行 AD 转换了。

21.2 硬件设计

本实验用到的硬件资源有:

1) 指示灯 DS0

2) 数码管

3) ADC

4) 电位器

前面 2 个均已介绍过,而 ADC 属于 STM32F4 内部资源,实际上我们只需要软件设置

就可以正常工作,不过我们需要在外部连接其端口到被测电压上面。本章,我们通过 ADC1

的通道 9(PB1)来读取外部电压值,NANO STM32F4 板载设计了电位器,电位器是连接电

源 3.3V 的,而调节端是连接到 ADC 采样端,通过调节电位器,实现采集 0~3.3V 区域间的

电压。

在测试前需要将多功能端口 P3 的 VR 与 ADC 用跳线帽进行连接(与 PB9 连接)。当

然你可以用杜邦线一头插在 P3 的 ADC 插针上(与 PB9 连接),另外一头就接你要测试的

电压点(确保该电压不大于 3.3V 即可)。

21.3 软件设计

打开我们的 ADC 转换实验,可以看到工程中多了一个 adc.c 文件和 adc.h 文件。同时

ADC 相关的库函数是在 stm32f4xx_hal_adc.c 文件和 stm32f4xx_hal_adc.h 文件中。

打开 adc.c,可以看到代码如下:

ADC_HandleTypeDef ADC1_Handler;//ADC 句柄

//初始化 ADC

//ch: ADC_channels

//通道值 0~16 取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_16

void Adc_Init(void)

{

ADC1_Handler.Instance=ADC1;

ADC1_Handler.Init.ClockPrescaler=ADC_CLOCK_SYNC_PCLK_DIV4;

//4 分频,ADCCLK=PCLK2/4=96/4=24MHZ

ADC1_Handler.Init.Resolution=ADC_RESOLUTION_12B;

//12 位模式

ADC1_Handler.Init.DataAlign=ADC_DATAALIGN_RIGHT; //右对齐

ADC1_Handler.Init.ScanConvMode=DISABLE;

//非扫描模式

ADC1_Handler.Init.EOCSelection=DISABLE;

//关闭 EOC 中断

ADC1_Handler.Init.ContinuousConvMode=DISABLE;

//关闭连续转换

ADC1_Handler.Init.NbrOfConversion=1;

//1 个转换在规则序列中 也就是只转换规则序列 1

ADC1_Handler.Init.DiscontinuousConvMode=DISABLE; //禁止不连续采样模式

ADC1_Handler.Init.NbrOfDiscConversion=0;

//不连续采样通道数为 0

ADC1_Handler.Init.ExternalTrigConv=ADC_SOFTWARE_START; //软件触发

ADC1_Handler.Init.ExternalTrigConvEdge=ADC_EXTERNALTRIGCONVEDGE

_NONE;//使用软件触发

ADC1_Handler.Init.DMAContinuousRequests=DISABLE; //关闭 DMA 请求

HAL_ADC_Init(&ADC1_Handler); //初始化

}

//ADC 底层驱动,引脚配置,时钟使能

//此函数会被 HAL_ADC_Init()调用

//hadc:ADC 句柄

void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)

{

GPIO_InitTypeDef GPIO_Initure;

__HAL_RCC_ADC1_CLK_ENABLE();

//使能 ADC1 时钟

__HAL_RCC_GPIOB_CLK_ENABLE();

//开启 GPIOB 时钟

GPIO_Initure.Pin=GPIO_PIN_1;

//PB1

GPIO_Initure.Mode=GPIO_MODE_ANALOG; //模拟

GPIO_Initure.Pull=GPIO_NOPULL;

//不带上下拉

HAL_GPIO_Init(GPIOB,&GPIO_Initure);

}

//获得 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=1;

//第 1 个序列,序列 1

ADC1_ChanConf.SamplingTime=ADC_SAMPLETIME_480CYCLES; //采样时间

ADC1_ChanConf.Offset=0;

HAL_ADC_ConfigChannel(&ADC1_Handler,&ADC1_ChanConf); //通道配置

HAL_ADC_Start(&ADC1_Handler); //开启 ADC

HAL_ADC_PollForConversion(&ADC1_Handler,10); //轮询转换

return (u16)HAL_ADC_GetValue(&ADC1_Handler);

//返回最近一次 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);

}

return temp_val/times;

}

此部分代码就 4 个函数,Adc_Init 函数调用函数 HAL_ADC_Init 初始化 ADC1 相关参数。

第二个函数 HAL_ADC_MspInit 是 MSP 初始化回调函数,用来使能时钟和初始化 IO 口,第

三个函数 Get_Adc,用于读取某个通道的 ADC 值,例如我们读取通道 9 上的 ADC 值,就

可以通过 Get_Adc(ADC_CHANNEL_9)得到。最后一个函数 Get_Adc_Average,用于多次

获取 ADC 值,取平均,用来提高准确度。

接下来看看 main.c 的代码如下:

// 共阴数字数组

// 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F, .,全灭

u8 smg_num[]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6,0xee,

0x3e,0x9c,0x7a,0x9e,0x8e,0x01,0x00};

int main(void)

{

HAL_Init();

//初始化 HAL 库

Stm32_Clock_Init(96,4,2,4);

//设置时钟,96Mhz

delay_init(96);

//初始化延时函数

uart_init(115200);

//初始化串口 115200

LED_Init();

//初始化 LED

LED_SMG_Init();

//数码管初始化

Adc_Init();

//ADC 初始化

TIM3_Init(20-1,9600-1);

//数码管 2ms 定时显示

while(1)

{

}

}

//ADC 变量

static u16 adcx=0;

static u16 adcx1=0;

static float temp=0;

u8 num=0;//数码管值

u8 smg_wei=0;//数码管位选

u8 adc_t=0;//adc 采样时间值

u8 led_t=0;//led 显示时间值

//回调函数,定时器中断服务函数调用

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)

{

if(htim==(&TIM3_Handler))

{

adc_t ;

if(adc_t==100)//ADC 200ms 采样

{

adc_t=0;

adcx=Get_Adc_Average(ADC_CHANNEL_9,3);//ADC 原始值

temp=(float)adcx*(3.3/4096);//ADC 电压值

adcx1=temp;

temp-=adcx1;

temp*=1000;

}

switch(smg_wei)

{

//ADC 采样值

case 0:

if(adcx>1000)num = smg_num[adcx/1000];

else

num = 0x00;

break;

case 1:

if(adcx>100) num = smg_num[adcx00/100];

else

num = 0x00;

break;

case 2:

if(adcx>10) num = smg_num[adcx0/10];

else

num = 0x00;

break;

case 3:

num = smg_num[adcx]; break;

case 4: num = 0x00; break;

//ADC 换算后的电压值

case 5: num = smg_num[adcx1]|0x01;break;

case 6: num = smg_num[(u16)temp/100]; break;

case 7: num = smg_num[(u16)temp0/10];break;

}

LED_Write_Data(num,smg_wei);

LED_Refresh();

smg_wei ;

if(smg_wei==8) smg_wei=0;

led_t ;

if(led_t==250)//500ms 闪烁

{

led_t=0;

LED0=!LED0;

}

}

}

在数码管上显示采集的数据,同样数码管在定时器中断中每隔 2ms 刷新显示,每隔

200ms 读取一次 ADC 通道 9 的值,并显示读到的 ADC 值(数字量,在左四位数码管显示),

以及其转换成模拟量后的电压值(在右四位数码管显示),调节电位器采集的数据会实时的

变化。同时控制 LED0 闪烁,以提示程序正在运行。

21.4 下载验证

在代码编译成功之后,我们通过下载代码到 ALIENTEK NANO STM32F4 上,可以看到

数码管显示如图 21.4.1 所示:

正点原子stm32芯片包(STM32开发板资料连载)(11)

图 21.4.1 ADC 实验实际测试图

上图中,我们已经将 ADC 和 VR 连接在一起(跳线帽短接),调节 VR1 电位器向右调

采集电压值增大,向左调采集电压值减少。同时伴随 DS0 的不停闪烁,提示程序在运行。

图上可以看到 ADC 采样原始值:2719,换算后的电压值:2.19V。

大家可以试试用杜邦线接到其他地方,看看电压值是否准确?但是一定别接到 5V 上面

去,否则可能烧坏 ADC!

通过这一章的学习,我们了解了 STM32F4 ADC 的使用,但这仅仅是 STM32F4 强大的

ADC 功能的一小点应用。STM32F4 的 ADC 在很多地方都可以用到,另外,ADC 的 DMA

功能是很不错的,建议有兴趣的大家深入研究下 STM32F4 的 ADC,相信会给你以后的开发

带来方便

,