正点原子STM32(基于HAL库)4

ADC 实验

本章我们将介绍STM32F103 的ADCAnalog-to-digital converters模数转换器功能。
我们通过四个实验来学习ADC分别是单通道ADC 采集实验、单通道ADC 采集DMA 读取
实验、多通道ADC 采集DMA 读取实验和单通道ADC 过采样16 位分辨率实验。

ADC 简介

ADC 即模拟数字转换器英文详称Analog-to-digital converter可以将外部的模拟信号转换
为数字信号。
STM32F103 系列芯片拥有3 个ADCC8T6 只有2 个这些ADC 可以独立使用其中
ADC1 和ADC2 还可以组成双重模式提高采样率。STM32 的ADC 是12 位逐次逼近型的模
拟数字转换器。它有18 个通道可测量16 个外部和2 个内部信号源其中ADC3 根据CPU 引
脚的不同其通道数也不同一般有8 个外部通道。ADC 中的各个通道的A/D 转换可以单次、
连续、扫描或间断模式执行。ADC 的结果可以以左对齐或者右对齐存储在16 位数据寄存器中。
STM32F103 的ADC 主要特性我们可以总结为以下几条
1、12 位分辨率
2、转换结束、注入转换结束和发生模拟看门狗事件时产生中断
3、单次和连续转换模式
4、自校准
5、带内嵌数据一致性的数据对齐
6、采样间隔可以按通道分别编程
7、规则转换和注入转换均有外部触发选项
8、间断模式
9、双重模式带2 个或以上ADC 的器件
10、ADC 转换时间时钟为72MHz 为1.17us
11、ADC 供电要求2.4V 到3.6V
12、ADC 输入范围VREF–≤VIN≤VREF+
13、规则通道转换期间有DMA 请求产生
下面来介绍ADC 的框图

在这里插入图片描述

图中我们按照ADC 的配置流程标记了七处位置分别如下
①输入电压
在前面ADC 的主要特性也对输入电压有所提及ADC 输入范围VREF–≤VIN≤VREF+最终
还是由VREF–、VREF+、VDDA和VSSA决定的。下面看一下这几个参数的关系如图30.1.2 所示
在这里插入图片描述
从上图可以知道VDDA和VREF+接VCC3.3而VSSA和VREF-是接地所以ADC 的输入范
围即0~3.3V。
②输入通道
在确定好了ADC 输入电压后如何把外部输入的电压输送到ADC 转换器中呢在这里引
入了ADC 的输入通道在前面也提及到了ADC1 和ADC2 都有16 个外部通道和2 个内部通
道而ADC3 就有8 个外部通道。外部通道对应的是上图中的ADCx_IN0、ADCx_IN1…
ADCx_IN15。ADC1 的通道16 就是内部通道连接到芯片内部的温度传感器通道17 连接到
Vrefint。而ADC2 的通道16 和17 连接到内部的VSS。ADC3 的通道9、14、15、16 和17 连接
到的是内部的VSS。具体的ADC 通道表见表30.1.1 所示
在这里插入图片描述
③转换顺序
当ADC 的多个通道以任意顺序进行转换就诞生了成组转换这里有两种成组转换类型
规则组和注入组。规则组就是图中的规则通道注入组就是图中的注入通道。为了避免大家对
输入通道以及规则通道和注入通道的理解混淆后面规则通道以规则组来代称注入通道以
注入组来代称。
规则组最多允许16 个输入通道进行转换而注入组最多允许4 个输入通道进行转换。这里
讲解一下规则组和注入组。
规则组规则通道
规则组按字面理解“规则”就是按照一定的顺序相当于正常运行的程序平常用到最
多也是规则组。
注入组注入通道

注入组按字面理解“注入”就是打破原来的状态相当于中断。当程序执行的时候中
断是可以打断程序的执行。同这个类似注入组转换可以打断规则组的转换。假如在规则组转
换过程中注入组启动那么注入组被转换完成之后规则组才得以继续转换。
为了便于理解下面看一下规则组和注入组的执行优先级对比图如图30.1.3 所示
在这里插入图片描述
了解了规则组和注入组的概念后下面来看看它们的转换顺序即转换序列。转换序列可
以分为规则序列和注入序列。下面分别来介绍它们。
规则序列
规则组最多允许16 个输入通道进行转换那么就需要设置通道转换的顺序即规则序列。
规则序列寄存器有3 个分别为SQR1、SQR2 和SQR3。SQR3 控制规则序列中的第1 个到第
6 个转换SQR2 控制规则序列中第7 个到第12 个转换SQR1 控制规则序列中第13 个到第16
个转换。规则序列寄存器控制关系汇总如表30.1.2 所示
在这里插入图片描述
从上表可以知道当我们想设置ADC 的某个输入通道在规则序列的第1 个转换只需要
把相应的输入通道号的值写入SQR3 寄存器中的SQ1[4:0]位即可。例如想让输入通道5 先进行转换那么就可以把5 这个数值写入SQ1[4:0]位。如果还想让输入通道8 在第2 个转换那么
就可以把8 这个数值写入SQ2[4:0]位。最后还要设置你的这个规则序列的输入通道个数只需
把输入通道个数写入SQR1 的SQL[3:0]位。注意写入0 到SQL[3:0]位表示这个规则序列有
1 个输入通道的意思而不是0 个输入通道。
注入序列
注入序列跟规则序列差不多决定的是注入组的顺序。注入组最大允许4 个通道输入
它的注入序列由JSQR 寄存器配置。注入序列寄存器JSQR 控制关系如表30.1.3 所示

在这里插入图片描述
注入序列有多少个输入通道只需要把输入通道个数写入到JL [ 1 : 0 ]位范围是0~3。注
意写入0 表示这个注入序列有一个输入通道而不是0 个输入通道。这个内容很简单。编程
时容易犯错的是注入序列的转换顺序问题下面给大家讲解一下。
如果JL[ 1 : 0 ]位的值小于3即设置注入序列要转换的通道个数小于4则注入序列的转
换顺序是从JSQx[ 4 : 0 ]x=4-JL[1:0]开始。例如JL [ 1 : 0 ]=10、JSQ4 [ 4 : 0 ]= 00100、JSQ3 [ 4 : 0 ]= 00011、JSQ2 [ 4 : 0 ]= 00111、JSQ1 [ 4 : 0 ]= 00010意味着这个注入序列的转换顺序
是7、3、4而不是2、7、3。如果JL[ 1 : 0 ]=00那么转换顺序是从JSQ4 [ 4 : 0 ]开始。
④触发源
在配置好输入通道以及转换顺序后就可以进行触发转换了。ADC 的触发转换有两种方法
分别是通过ADON 位或外部事件触发转换。
1ADON 位触发转换
当ADC_CR2 寄存器的ADON 位为1 时再独立给ADON 位写1其它位不能一起改变
这是为了防止误触发这时会启动转换。这种控制ADC 启动转换的方式非常简单。
2外部触发转换
另一种方法是通过外部事件触发转换例如定时器捕获、EXTI 线和软件触发可以分为规
则组外部触发和注入组外部触发。
规则组外部触发使用方法是将EXTTRIG 位置1并且通过EXTSET[2:0]位选择规则组启动
转换的触发源。如果EXTSET[2:0]位设置为111那么可以通过SWSTART 为启动ADC 转换
相当于软件触发。
注入组外部触发使用方法是将JEXTTRIG 位置1并且通过JEXTSET[2:0]位选择注入组启
动转换的触发源。如果JEXTSET[2:0]位设置为111那么可以通过JSWSTART 为启动ADC 转
换相当于软件触发。
ADC1 和ADC2 的触发源是一样的ADC3 的触发源和ADC1/2 有所不同这个需要注意。
⑤转换时间
1ADC 时钟
在学习转换时间之前我们先来了解ADC 时钟。从标号⑤框出来部分可以看到ADC 时钟是
要经过ADC 预分频器的那么ADC 的时钟源是什么ADC 预分频器的分频系数可以设置的
范围又是多少以及ADC 时钟频率的最大值又是多少下面将为大家解答。
ADC 的输入时钟是由PCLK2 经过分频产生的分频系数是由RCC_CFGR 寄存器的
ADCPRE[1:0]位设置的可选择2/4/8/16 分频。需要注意的是ADC 的输入时钟频率最大值是
14MHz如果超过这个值将会导致ADC 的转换结果准确度下降。
一般我们设置PCLK2 为72MHz。为了不超过ADC 的最大输入时钟频率14MHz我们设
置ADC 的预分频器分频系数为6就可以得到ADC 的输入时钟频率为72MHz/6即12MHz。
例程中我们也是如此设置的。

2转换时间
STM32F103 的ADC 总转换时间的计算公式如下
在这里插入图片描述
⑥数据寄存器
ADC 转换完成后的数据输出寄存器。根据转换组的不同规则组的完成转换的数据输出到
ADC_DR 寄存器注入组的完成转换的数据输出到ADC_JDRx 寄存器。假如是使用双重模式
规则组的数据也是存放在ADC_DR 寄存器。下面给大家简单介绍一下这两个寄存器。
1ADC 规则数据寄存器ADC_DR
ADC 规则组数据寄存器ADC_DR 是一个32 位的寄存器独立模式时只使用到该寄存器低
16 位保存ADC1/2/3 的规则转换数据。在双ADC 模式下高16 位用于保存ADC2 转换的数
据低16 位用于保存ADC1 转换的数据。
因为ADC 的精度是12 位的ADC_DR 寄存器无论高16 位还是低16存放数据的位宽都
是16 位的所以允许选择数据对齐方式。由ADC_CR2 寄存器的ALIGN 位设置数据对齐方式
可选择右对齐或者左对齐。
细心的朋友可能发现规则组最多有16 个输入通道而ADC 规则数据寄存器只有一个
如果一个规则组用到好几个通道数据怎么读取如果使用多通道转换那么这些通道的数据
也会存放在DR 里面按照规则组的顺序上一个通道转换的数据会被下一个通道转换的数
据覆盖掉所以当通道转换完成后要及时把数据取走。比较常用的方法是使用DMA 模式。当
规则组的通道转换结束时就会产生DMA 请求这样就可以及时把转换的数据搬运到用户指
定的目的地址存放。注意只有ADC1 和ADC3 可以产生DAM 请求而由ADC2 转换的数据
可以通过双ADC 模式利用ADC1 的DMA 功能传输。
2ADC 注入数据寄存器xADC_JDRxx=1~4
ADC 注入数据寄存器有4 个注入组最多有4 个输入通道刚好每个通道都有自己对应的
数据寄存器。ADC_JDRx 寄存器是32 位的低16 位有效高16 位保留数据也同样需要选
择对齐方式。也是由ADC_CR2 寄存器的ALIGN 位设置数据对齐方式可选择右对齐或者左
对齐。
⑦中断
ADC 中断可分为三种规则组转换结束中断、注入组转换结束中断、设置了模拟看门狗状
态位中断。它们都有独立的中断使能位分别由ADC_CR 寄存器的EOCIE、JEOCIE、AWDIE
位设置对应的标志位分别是EOC、JEOC、AWD。
模拟看门狗中断

模拟看门狗中断发生条件首先通过ADC_LTR 和ADC_HTR 寄存器设置低阈值和高阈值
然后开启了模拟看门狗中断后当被ADC 转换的模拟电压低于低阈值或者高于高阈值时就
会产生中断。例如我们设置高阈值是3.0V那么模拟电压超过3.0V 的时候就会产生模拟看
门狗中断低阈值的情况类似。
DMA 请求
规则组和注入组的转换结束后除了可以产生中断外还可以产生DMA 请求我们利用
DMA 及时把转换好的数据传输到指定的内存里防止数据被覆盖。
注意只有ADC1 和ADC3 可以产生DAM 请求DMA 相关的知识请回顾DMA 实验。
⑧单次转换模式和连续转换模式
单次转换模式和连续转换模式在框图中是没有标号为了更好地学习后续的内容这里简
单给大家讲讲。
1单次转换模式
通过将ADC_CR2 寄存器的CONT 位置0 选择单次转换模式。该模式下ADC 只执行一
次转换由ADC_CR2 寄存器的ADON 位启动只适用于规则组也可以通过外部触发启动
适用于规则组或注入组。
如果规则组的一个输入通道被转换那么转换的数据被储存在16 位ADC_DR 寄存器中、
EOC转换结束标志位被置1、如果设置了EOCIE 位则产生中断然后ADC 停止。
如果注入组的一个输入通道被转换那么转换的数据被储存在16 位ADC_DRJx 寄存器中、
JEOC转换结束标志位被置1、如果设置了JEOCIE 位则产生中断然后ADC 停止。
2连续转换模式
通过将ADC_CR2 寄存器的CONT 位置1 选择连续转换模式。该模式下ADC 完成上一
个通道的转换后会马上自动地启动下一个通道的转换由ADC_CR2 寄存器的ADON 位启动
也可以通过外部触发启动。
如果规则组的一个输入通道被转换那么转换的数据被储存在16 位ADC_DR 寄存器中、
EOC转换结束标志位被置1、如果设置了EOCIE 位则产生中断。
如果注入组的一个输入通道被转换那么转换的数据被储存在16 位ADC_DRJx 寄存器中、
JEOC转换结束标志位被置1、如果设置了JEOCIE 位则产生中断。
⑨扫描模式
扫描模式在框图中是没有标号为了更好地学习后续的内容这里简单给大家讲讲。
可以通过ADC_CR1 寄存器的SCAN 位配置是否使用扫描模式。如果选择扫描模式ADC
会扫描所有被ADC_SQRx 寄存器或ADC_JSQR 选中的所有通道并对规则组或者注入组的每
个通道执行单次转换然后停止转换。但如果还设置了CONT 位即选择连续转换模式那么
转换不会在选择组的最后一个通道上停止而是再次从选择组的第一个通道继续转换。
如果设置了DMA 位在每次EOC 后DMA 控制器把规则组通道的转换数据传输到SRAM
中。而注入通道转换的数据总是存储在ADC_JDRx 寄存器中。
到这里我们基本上介绍了ADC 的大多数基础的知识点其它知识后面用到会继续补充
如果还有不懂的内容请参考《STM32F10xxx 参考手册_V10中文版.pdf》的第11 章。

单通道ADC 采集实验

本实验我们来学习单通道ADC 采集实验。本实验使用规则组单通道的单次转换模式并
且通过软件触发即由ADC_CR2 寄存器的SWSTART 位启动。下面先带大家来了解本实验要
配置的寄存器。

ADC 寄存器

这里我们只介绍本实验用到的寄存器的关键位其它寄存器后续用到会继续介绍。
⚫ ADC 控制寄存器1ADC_CR1
ADC 控制寄存器1 描述如图30.2.1.1 所示
在这里插入图片描述
SCAN 位用于选择是否使用扫描模式。本实验我们使用单通道采集所以没必要选择扫描
模式该位置0 即可。
DUALMOD[3:0]位用来设置ADC 的操作模式我们的例程中ADC 相关的实验都是使用独
立模式所以设置为0000 即可。
⚫ ADC 控制寄存器2ADC_CR2
ADC 控制寄存器2 描述如图30.2.1.2 所示
在这里插入图片描述
该寄存器我们针对性的介绍一些位ADON 位用于打开或关闭AD 转换器还可以用于触
发ADC 转换。CONT 位用于设置单次转换模式还是连续转换模式本实验我们使用单次转换
模式所以CONT 位置0 即可。CAL 位用于开启AD 校准。RSTCAL 位用于判断校准寄存器是
否已初始化。ALIGN 用于设置数据对齐我们使用右对齐所以该位置0。EXTSEL[2:0]位用
于选择规则组启动转换的外部事件触发源本实验使用的是软件触发SWSTART所以这三
个位置为111。EXTTRIG 位必须置1EXTSEL[2:0]位才能选择软件触发SWSTART别漏了
这步否则设置软件触发会不成功。SWSTART 位用于启动一次规则组通道的转换即软件触发转换。
⚫ ADC 采样事件寄存器1ADC_SMPR1
ADC 采样事件寄存器1 描述如图30.2.1.3 所示

在这里插入图片描述
⚫ ADC 采样事件寄存器2ADC_SMPR2
ADC 采样事件寄存器2 描述如图30.2.1.4 所示
在这里插入图片描述
ADC 采样时间设置需要由两个寄存器设置ADC_SMPR1 和ADC_SMPR1分别设置通道
10~17 和通道0~9 的采样时间每个通道用3 个位设置。可以看出ADC 的每个通道的采样时间
是支持单独设置的。
一般每个要转换的通道采样时间建议尽量长一点以获得较高的准确度但是这样会降
低ADC 的转换速率看大家怎么衡量选择了。本实验中我们设置采样时间是239.5 个周期。
结合前面介绍过的转换时间公式
在这里插入图片描述
⚫ ADC 规则序列寄存器1
ADC 规则序列寄存器共有3 个这几个寄存器的功能都差不多这里我们仅介绍一下ADC
规则序列寄存器1ADC_SQR1描述如图30.2.1.5 所示
在这里插入图片描述
L[3:0]用于设置规则组序列的长度取值范围015表示规则组的长度是116。本实验
只用了1 个输入通道所以L[3:0]位设置为0000 即可。
SQ13[4:0]SQ16[4:0]位设置规则组序列的第1316 个转换编号第1~12 个转换编号的设
置请查看ADC_SQR2 和ADC_SQR3 寄存器。设置过程非常简单忘记了请参考前面给大家整
理出来的规则序列寄存器控制关系汇总表。
本实验我们使用单通道ADC1 通道14所以规则组序列里只有一个输入通道我们将
ADC_SQR3 寄存器的SQ1[4:0]位的值设置为14 即可。
⚫ ADC 规则数据寄存器ADC_DR
ADC 规则数据寄存器描述如图30.2.1.6 所示
在这里插入图片描述
在规则序列中AD 转换结果都将被存在这个寄存器里面而注入通道的转换结果被保存在
ADC_JDRx 里面。该寄存器的数据可以通过ADC_CR2 的ALIGN 位设置左对齐还是右对齐。
在读取数据的时候要注意。
⚫ ADC 状态寄存器ADC_SR
ADC 状态寄存器描述如图30.2.1.7 所示
在这里插入图片描述
该寄存器保存了ADC 转换时的各种状态。本实验我们通过EOC 位的状态来判断ADC 转
换是否完成如果查询到EOC 位被硬件置1就可以从ADC_DR 寄存器中读取转换结果否
则需要等待转换完成。
至此本实验要用到的ADC 关键寄存器全部介绍完了对于未介绍的部分请大家参考
《STM32F10xxx 参考手册_V10中文版.pdf》第11 章相关内容。

硬件设计

  1. 例程功能
    采集ADC1 通道1PA1上面的电压并在LCD 模块上面显示ADC 规则数据寄存器12
    位的转换值以及将该值换算成电压后的电压值。使用杜邦线将ADC 和RV1 排针连接使得PA1
    连接到电位器上然后将ADC 采集到的数据和转换后的电压值在TFTLCD 屏中显示。用户可
    以通过调节电位器的旋钮改变电压值。LED0 闪烁提示程序运行。

  2. 硬件资源
    1LED 灯
    LED0 – PB5
    2串口1(PA9/PA10 连接在板载USB 转串口芯片CH340 上面)
    3正点原子2.8/3.5/4.3/7/10 寸TFTLCD 模块(仅限MCU 屏16 位8080 并口驱动)
    4ADC1
    通道1 –PA1

  3. 原理图
    ADC 属于STM32F103 内部资源实际上我们只需要软件设置就可以正常工作另外还需
    要将待测量的电压源连接到ADC 通道上以便ADC 测量。本实验我们通过ADC1 的通道1
    PA1来采集外部电压值开发板有一个电位器可调节的电压范围是0~3.3V。我们可以通
    过杜邦线将PA1 与电位器连接如下图所示

在这里插入图片描述

使用杜邦线将ADC 和RV1 排针连接好后并下载程序后就可以用螺丝刀调节电位器变
换多种电压值进行测量。
有的朋友可能还想测量其它地方的电压值我们只需要1 根杜邦线一端接到ADC 排针
上另外一端就接你要测试的电压点。一定要保证测试点的电压在0~3.3V 的电压范围否则可
能烧坏我们的ADC甚至是整个主控芯片。

程序设计(还没拷贝完)

30.2.3.1 ADC 的HAL 库驱动
ADC 在HAL 库中的驱动代码在stm32f1xx_hal_adc.c 和stm32f1xx_hal_adc_ex.c 文件及
其头文件中。

  1. HAL_ADC_Init 函数
    ADC 的初始化函数其声明如下
HAL_StatusTypeDef HAL_ADC_Init(ADC_HandleTypeDef *hadc);

⚫ 函数描述
用于初始化ADC。
⚫ 函数形参
形参1 是ADC_HandleTypeDef 结构体类型指针变量其定义如下

typedef struct
{
	ADC_TypeDef *Instance; /* ADC寄存器基地址*/
	ADC_InitTypeDef Init; /* ADC参数初始化结构体变量*/
	DMA_HandleTypeDef *DMA_Handle; /* DMA配置结构体*/
	HAL_LockTypeDef Lock; /* ADC锁定对象*/
	__IO uint32_t State; /* ADC工作状态*/
	__IO uint32_t ErrorCode; /* ADC错误代码*/
}ADC_HandleTypeDef;

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

typedef struct {
	uint32_t DataAlign; /* 设置数据的对齐方式*/
	uint32_t ScanConvMode; /* 扫描模式*/
	FunctionalState ContinuousConvMode; /* 开启连续转换模式否则就是单次转换模式*/
	uint32_t NbrOfConversion; /* 设置转换通道数目*/
	FunctionalState DiscontinuousConvMode; /* 是否使用规则通道组间断模式*/
	uint32_t NbrOfDiscConversion; /* 配置间断模式的规则通道个数*/
	uint32_t ExternalTrigConv; /* ADC外部触发源选择*/
} ADC_InitTypeDef;
  1. DataAlign用于设置数据的对齐方式这里可以选择右对齐或者是左对齐该参数可选为
    ADC_DATAALIGN_RIGHT 和ADC_DATAALIGN_LEFT。
  2. ScanConvMode配置是否使用扫描。如果是单通道转换使用ADC_SCAN_DISABLE如果
    是多通道转换使用ADC_SCAN_ENABLE。
  3. ContinuousConvMode可选参数为ENABLE 和DISABLE配置自动连续转换还是单次转换。
    使用ENABLE 配置为使能自动连续转换使用DISABLE 配置为单次转换转换一次后停止
    需要手动控制才重新启动转换。
  4. NbrOfConversion指定规则组转换通道数目范围是1~16。
  5. DiscontinuousConvMode配置是否使用规则通道组间断模式比如要转换的通道有1、2、
    5、7、8、9那么第一次触发会进行通道1 和2下次触发就是转换通道5 和7这样不连
    续的转换依次类推。此参数只有将ScanConvMode 使能还有ContinuousConvMode 失能
    的情况下才有效不可同时使能。
  6. NbrOfDiscConversion配置间断模式的通道个数禁止规则通道组间断模式后此参数忽略。
  7. ExternalTrigConv外部触发方式的选择如果使用软件触发那么外部触发会关闭。
    ⚫ 函数返回值
    HAL_StatusTypeDef 枚举类型的值。
  1. HAL_ADCEx_Calibration_Start 函数
    ADC 的自校准函数其声明如下
HAL_StatusTypeDef HAL_ADCEx_Calibration_Start(ADC_HandleTypeDef *hadc);

⚫ 函数描述
首先调用HAL_ADC_Init 函数配置了相关的功能后再调用此函数进行ADC 自校准功能。
⚫ 函数形参
ADC_HandleTypeDef 结构体类型指针变量。
⚫ 函数返回值
HAL_StatusTypeDef 枚举类型的值。
3. HAL_ADC_ConfigChannel 函数
ADC 通道配置函数其声明如下

HAL_StatusTypeDef HAL_ADC_ConfigChannel(ADC_HandleTypeDef *hadc,
				ADC_ChannelConfTypeDef *sConfig);

⚫ 函数描述
调用了HAL_ADC_Init 函数配置了相关的功能后就可以调用此函数配置ADC 具体通道。
⚫ 函数形参
形参1 是ADC_HandleTypeDef 结构体类型指针变量。
形参2 是ADC_ChannelConfTypeDef 结构体类型指针变量用于配置ADC 采样时间使
用的通道号单端或者差分方式的配置等。该结构体定义如下

typedef struct {
	uint32_t Channel; /* ADC转换通道*/
	uint32_t Rank; /* ADC转换顺序*/
	uint32_t SamplingTime; /* ADC采样周期*/
} ADC_ChannelConfTypeDef;
  1. ChannelADC 转换通道范围0~19。
  2. Rank在常规转换中的常规组的转换顺序可以选择1~16。
  3. SamplingTimeADC 的采样周期最大810.5 个ADC 时钟周期要求尽量大以减少误差。
    ⚫ 函数返回值
    HAL_StatusTypeDef 枚举类型的值。
  1. HAL_ADC_Start 函数
    ADC 转换启动函数其声明如下
HAL_StatusTypeDef HAL_ADC_Start(ADC_HandleTypeDef *hadc);

⚫ 函数描述
当配置好ADC 的基础的功能后就调用此函数启动ADC。
⚫ 函数形参
ADC_HandleTypeDef 结构体类型指针变量。
⚫ 函数返回值
HAL_StatusTypeDef 枚举类型的值。
5. HAL_ADC_PollForConversion 函数
等待ADC 规则组转换完成函数其声明如下

HAL_StatusTypeDef HAL_ADC_PollForConversion(ADC_HandleTypeDef *hadc,
										uint32_t Timeout);

⚫ 函数描述
一般先调用HAL_ADC_Start 函数启动转换再调用该函数等待转换完成然后再调用
HAL_ADC_GetValue 函数来获取当前的转换值。
⚫ 函数形参
形参1 是ADC_HandleTypeDef 结构体类型指针变量。
形参2 是等待转换的等待时间单位是毫秒ms。
⚫ 函数返回值
HAL_StatusTypeDef 枚举类型的值。
6. HAL_ADC_GetValue 函数
获取常规组ADC 转换值函数其声明如下

uint32_t HAL_ADC_GetValue(ADC_HandleTypeDef *hadc);

⚫ 函数描述
一般先调用HAL_ADC_Start 函数启动转换再调用HAL_ADC_PollForConversion 函数等
待转换完成然后再调用HAL_ADC_GetValue 函数来获取当前的转换值。
⚫ 函数形参
形参1 是ADC_HandleTypeDef 结构体类型指针变量。
⚫ 函数返回值
当前的转换值uint32_t 类型数据。

单通道ADC 采集配置步骤

1开启ADCx 和ADC 通道对应的IO 时钟并配置该IO 为模拟功能
首先开启ADCx 的时钟然后配置GPIO 为模拟模式。本实验我们默认用到ADC1 通道1
对应IO 是PA1它们的时钟开启方法如下

__HAL_RCC_ADC1_CLK_ENABLE(); /* 使能ADC1时钟*/
__HAL_RCC_GPIOA_CLK_ENABLE(); /* 开启GPIOA时钟*/

2初始化ADCx配置其工作参数
通过HAL_ADC_Init 函数来设置ADCx 时钟分频系数、分辨率、模式、扫描方式、对齐方
式等信息。
注意该函数会调用HAL_ADC_MspInit 回调函数来存放ADC 及GPIO 时钟使能、GPIO
初始化等代码。
3配置ADC 通道并启动AD 转换器
在HAL 库中通过HAL_ADC_ConfigChannel 函数来选择要配置ADC 的通道并设置规
则序列、采样时间等。
配置好ADC 通道之后通过HAL_ADC_Start 函数启动AD 转换器。
4读取ADC 值
这里选择查询方式读取在读取ADC 值之前需要调用HAL_ADC_PollForConversion 等待
上一次转换结束。然后就可以通过HAL_ADC_GetValue 来读取ADC 值。

程序流程图

在这里插入图片描述

程序解析
这里我们只讲解核心代码详细的源码请大家参考光盘本实验对应源码。ADC 驱动源码包
括两个文件adc.c 和adc.h。本章有四个实验每一个实验的代码都是在上一个实验后面追加。
adc.h 文件针对ADC 及通道引脚定义了一些宏定义具体如下

/* ADC及引脚定义*/
#define ADC_ADCX_CHY_GPIO_PORT GPIOA
#define ADC_ADCX_CHY_GPIO_PIN GPIO_PIN_1
#define ADC_ADCX_CHY_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOC_CLK_ENABLE();\
}while(0) /* PA口时钟使能*/
#define ADC_ADCX ADC1
#define ADC_ADCX_CHY ADC_CHANNEL_1 /* 通道Y, 0 <= Y <= 16 */
/* ADC1时钟使能*/
#define ADC_ADCX_CHY_CLK_ENABLE() do{ __HAL_RCC_ADC1_CLK_ENABLE();}while(0)

ADC 的通道与引脚的对应关系在《STM32F103ZET6.pdf》数据手册可以查到我们这里使
用ADC1 的通道1在数据手册中的表格为
在这里插入图片描述

单通道ADC 采集DMA 读取实验

本实验我们来学习单通道ADC 采集DMA 读取实验。本实验使用规则组单通道的连续
转换模式并且通过软件触发即由ADC_CR2 寄存器的SWSTART 位启动。由于使用连续转
换模式所以使用DMA 读取转换结果的方式。下面先带大家来了解本实验要配置的寄存器。

ADC & DMA 寄存器

本实验我们很多的设置和单通道ADC 采集实验是一样的所以下面介绍寄存器的时候我
们不会继续全部都介绍而是针对性选择与单通道ADC 采集实验不同设置的ADC_CR2 寄存
器进行介绍其他的配置基本一样的。另外因为我们用到DMA 读取数据所以还会介绍如何配置相关DMA 的寄存器。
⚫ ADC 配置寄存器ADC_CR2
ADCx 配置寄存器描述如图30.3.1.1 所示

在这里插入图片描述
ADC_CR2 寄存器中我们主要跟前面设置不同的有两个位分别如下
DMA 位用于配置使用DMA 模式本实验该位置1。在单通道ADC 采集实验中默认设
置为0即不使用DMA 模式规则组转换的结果存储在ADC_DR 寄存器然后通过手动读取
ADC_DR 寄存器的方式得到转换结果。本实验我们使用ADC 的连续转换模式并通过DMA
读取转换结果这样DMA 就会自动在ADC_DR 寄存器中读取转换结果。
CONT 位用于设置单次转换模式还是连续转换模式本实验我们使用连续转换模式所以
CONT 位置1 即可。
这里介绍ADC_CR2 寄存器的这两个位其它请参考上一个实验的配置。下面介绍DMA
一些比较重要的寄存器配置。
⚫ DMA 通道x 外设地址寄存器DMA_CPARxx = 1…7
DMA 通道x 外设地址寄存器描述如图30.3.1.2 所示
在这里插入图片描述
该寄存器存放的是DMA 通道x 外设地址。本实验我们需要通过DMA 读取ADC 转换后
存放在ADC 规则数据寄存器(ADC_DR) 的结果数据。所以我们需要给DMA_CPARx 寄存器
写入ADC_DR 寄存器的地址。这样配置后DMA 就会从ADC_DR 寄存器的地址读取ADC 的
转换后的数据到某个内存空间。这个内存空间地址需要我们通过DMA_CMARx寄存器来设置
比如定义一个变量把这个变量的地址值写入该寄存器。
注意DMA_CPARx 寄存器受到写保护只有DMA_CCRx 寄存器中的EN 为“0”时才可
以写入即先要禁止通道开启才可以写入。
⚫ DMA 通道x 存储器地址寄存器DMA_CMARxx = 1…7
DMA 通道x 存储器地址寄存器描述如图30.3.1.3 所示

在这里插入图片描述
该寄存器存放的是DMA 通道x 存储器地址。同样的该寄存器也是受写保护只有当
DMA_CCRx 的EN 位为0 时才可以写入。
⚫ DMA 通道x 传输数量寄存器DMA_CNDTRxx = 1…7
DMA 通道x 传输数量寄存器描述如图30.3.1.4 所示
在这里插入图片描述

该寄存器控制着DMA 通道x 的每次传输所要传输的数据量。其设置范围为0~65535。并
且该寄存器的值随着传输的进行而减少当该寄存器的值为0 的时候就代表此次数据传输已经
全部发送完成。所以可以通过这个寄存器的值来获取当前DMA 传输的进度。
其它的DMA 寄存器我们就不一一介绍了请大家看着寄存器源码对照手册理解都不难。

硬件设计

  1. 例程功能
    使用ADC 采集DMA 读取通道1PA1上面的电压在LCD 模块上面显示ADC 转
    换值以及换算成电压后的电压值。使用短路帽将ADC 和RV1 排针连接使得PA1 连接到电位
    器上然后将ADC 采集到的数据和转换后的电压值在TFTLCD 屏中显示。用户可以通过调节
    电位器的旋钮改变电压值。LED0 闪烁提示程序运行。
  2. 硬件资源
    1LED 灯
    LED0 –PB5
    2串口1(PA9/PA10 连接在板载USB 转串口芯片CH340 上面)
    3正点原子2.8/3.5/4.3/7/10 寸TFTLCD 模块(仅限MCU 屏16 位8080 并口驱动)
    4ADC 通道1 –PA1
    5DMADMA1 通道1
  3. 原理图
    ADC 属于STM32F103 内部资源实际上我们只需要软件设置就可以正常工作另外还需
    要将待测量的电压源连接到ADC 通道上以便ADC 测量。本实验我们通过ADC1 的通道1
    PA1来采集外部电压值开发板有一个电位器可调节的电压范围是0~3.3V。我们可以通
    过杜邦线将PA1 与电位器连接如下图所示

在这里插入图片描述
使用杜邦线将ADC 和RV1 排针连接好后并下载程序后就可以用螺丝刀调节电位器变
换多种电压值进行测量。
有的朋友可能还想测量其它地方的电压值我们只需要1 根杜邦线一端接到ADC 排针
上另外一端就接你要测试的电压点。一定要保证测试点的电压在0~3.3V 的电压范围否则可
能烧坏我们的ADC甚至是整个主控芯片。

多通道ADC 采集DMA 读取实验

本实验我们来学习多通道ADC 采集DMA 读取实验。本实验使用规则组多通道的连续
转换模式并且通过软件触发即由ADC_CR2 寄存器的SWSTART 位启动。由于使用连续转
换模式所以使用DMA 读取转换结果的方式。下面先带大家来了解本实验要配置的寄存器。

ADC 寄存器

本实验我们很多的设置和单通道ADC 采集DMA 读取实验是一样的所以下面介绍寄
存器的时候我们不会继续全部都介绍而是针对性选择与单通道ADC 采集DMA 读取实验
不同设置的ADC_SQRx 寄存器进行介绍其他的配置基本一样的。另外我们用到DMA 读取数据配置上和单通道ADC 采集DMA 读取实验是一样的。
ADC 规则序列寄存器有四个ADC_SQR1~ ADC_SQR3具体怎么配置需要看我们用多少个通道比如本实验我们使用6 个通道同时采集ADC 数据具体配置如下
⚫ ADC 规则序列寄存器1ADC_SQR1
ADC 规则序列寄存器1 描述如图30.4.1.1 所示
在这里插入图片描述
L[3:0]位用于设置规则序列的长度取值范围015表示规则序列长度为116。本实验
使用到6 个通道所以设置这几个位的值为5 即可。
SQ13[4:0]SQ16[4:0]位设置规则组序列的第1316 个转换编号第1~12 个转换编号的设
置请查看ADC_SQR2 和ADC_SQR3 寄存器。设置过程非常简单忘记了请参考前面给大家整
理出来的规则序列寄存器控制关系汇总表。
下面我们来看看本实验是怎么设置的SQ1[4:0]位赋值为0、SQ2[4:0]位赋值为1、SQ3[4:0]
位赋值为2、SQ4[4:0]位赋值为3、SQ5[4:0]位赋值为4、SQ6[4:0]位赋值为5即规则序列1 到
6 分别对应的输入通道是0 到5。SQ1~SQ6 位都是在ADC_SQR3 寄存器中配置。

硬件设计

  1. 例程功能
    使用ADC1 采集DMA 读取通道1\2\3\4\5\6 的电压在LCD 模块上面显示对应的ADC
    转换值以及换算成电压后的电压值。可以使用杜邦线连接PA0\PA1\PA2\PA3\PA4\PA5 到你想测
    量的电压源0~3.3V然后通过TFTLCD 显示的电压值。LED0 闪烁提示程序运行。

  2. 硬件资源
    1LED 灯
    LED0 –PE5
    2串口1(PA9/PA10 连接在板载USB 转串口芯片CH340 上面)
    3正点原子2.8/3.5/4.3/7/10 寸TFTLCD 模块(仅限MCU 屏16 位8080 并口驱动)
    4ADC1 通道1–PA0、通道2–PA1、通道3–PA2、
    通道4–PA3、通道5–PA4、通道6–PA5
    5DMADMA1 通道1

  3. 原理图
    ADC 和DMA 属于STM32F103 内部资源实际上我们只需要软件设置就可以正常工作
    另外还需要将待测量的电压源连接到ADC 通道上以便ADC 测量。本实验我们通过ADC1
    的通道1\2\3\4\5\6 来采集外部电压值并通过DMA 来读取。

单通道ADC 过采样16 位分辨率实验

本实验我们来学习单通道ADC 过采样16 位分辨率实验。STM32F103 自带的ADC 分
辨率只有12 位虽然可以满足一般的应用但是有些场合可能需要更高的分辨率怎么办呢
可以使用外部专用的ADC或者换一个带更高分辨率ADC 的主控芯片。这样做往往会增加额
外的成本那么有没有其它办法呢答案是有的可以通过引入过采样技术来实现。
ADC 过采样技术是利用ADC 多次采集的方式来提高ADC 分辨率。下面简单介绍一
下怎么提高ADC 测量的分辨率
下面直接给大家介绍一个方程根据要增加分辨率计算过采样频率方程方程如下
fos = 4w ⋅ fs

其中w 是希望增加的分辨率位数fs是初始采样频率要求fos是过采样频率。
方程的推导过程比较复杂这里就不带大家去推导感兴趣的朋友可以通过下面这个链接
自行学习https://max.book118.com/html/2018/0506/165038217.shtm。
由该方程可以知道采样速度每提高4 倍分辨率位数可以提高1 位。结合ADC 的实际
情况换个思路来说分辨率位数每提高1 位如果采样频率不变的情况下那么采样速度就
会降低4 倍。本实验要求得到16 位分辨率即需要增加4 位分辨率那么采样速度就会降低
256 倍即需要采集256 次才能得出1 次数据相当于ADC 速度慢了256 倍。
理论上只要ADC 足够快我们可以无限提高ADC 精度但实际上ADC 并不是无限快的
而且由于ADC 性能限制并不是位数无限提高结果就越好需要根据自己的实际需求和ADC
的实际性能来权衡的。
下面来看一下我们怎么实现单通道ADC 过采样16 位分辨率实验的。

ADC 寄存器

本实验我们很多的设置和单通道ADC 采集DMA 读取实验是一样的代码实现也是基
于该实验实现的寄存器的介绍请参考前面的ADC 实验。

硬件设计

  1. 例程功能
    使用ADC1 通道1PA1通过软件方式实现16 位分辨率采集外部电压并在LCD 模块
    上面显示对应的ADC 转换值以及换算成电压后的电压值。可以使用杜邦线连接PA1 到你想测
    量的电压源0~3.3V然后通过TFTLCD 显示的电压值。LED0 闪烁提示程序运行。
  2. 硬件资源
    1LED 灯
    LED0 –PB5
    2串口1(PA9/PA10 连接在板载USB 转串口芯片CH340 上面)
    3正点原子2.8/3.5/4.3/7/10 寸TFTLCD 模块(仅限MCU 屏16 位8080 并口驱动)
    4ADC1 通道1 –PA1
  3. 原理图
    ADC 属于STM32F103 内部资源实际上我们只需要软件设置就可以正常工作另外还需
    要将待测量的电压源连接到ADC 通道上以便ADC 测量。本实验我们通过ADC1 通道1
    PA1来采集外部电压值。开发板有一个电位器可调节的电压范围是0~3.3V可以通过断
    路帽将PA1 与电位器连接从而测量电位器的电压。

内部温度传感器实验

本章我们将介绍STM32F103 的内部温度传感器并使用它来读取温度值然后在LCD 模
块上显示出来。

内部温度传感器简介

STM32 有一个内部的温度传感器可以用来测量CPU 及周围的温度(内部温度传感器更
适合于检测温度的变化需要测量精确温度的情况下应使用外置传感器)。对于STM32F103
来说该温度传感器在内部和ADC1_IN16 输入通道相连接此通道把传感器输出的电压转换
成数字值。温度传感器模拟输入推荐采样时间是17.1us。STM32F103 内部温度传感器支持的温
度范围为-40~125 度。精度为±1.5℃左右。
STM32 内部温度传感器的使用很简单只要设置一下内部ADC并激活其内部温度传感
器通道就差不多了。关于ADC 的设置我们在上一章已经进行了详细的介绍这里就不再多
说。接下来我们介绍一下和温度传感器设置相关的两个地方。
第一个地方我们要使用STM32 的内部温度传感器必须先激活ADC 的内部通道这里
通过ADC_CR2 的AWDEN 位bit23设置。设置该位为1 则启用内部温度传感器。
第二个地方STM32 的内部温度传感器固定的连接在ADC1 的通道16 上所以我们在
设置好ADC1 之后只要读取通道16 的值就是温度传感器返回来的电压值了。根据这个值
我们就可以计算出当前温度。计算公式如下
在这里插入图片描述

硬件设计

  1. 例程功能
    通过ADC 的通道16 读取STM32F103 内部温度传感器的电压值并将其转换为温度值
    显示在TFTLCD 屏上。LED0 闪烁用于提示程序正在运行。
  2. 硬件资源
    1LED 灯
    LED0 –PB5
    2串口1(PA9/PA10 连接在板载USB 转串口芯片CH340 上面)
    3正点原子2.8/3.5/4.3/7/10 寸TFTLCD 模块(仅限MCU 屏16 位8080 并口驱动)
    4ADC1 通道16
    5内部温度传感器
  3. 原理图
    ADC 和内部温度传感器都属于STM32F103 内部资源实际上我们只需要软件设置就可以正常工作我们需要用到TFTLCD 模块显示结果。

光敏传感器实验

本章我们将学习使用STM32 开发板板载的一个光敏传感器。我们还是要使用到ADC 采
集通过ADC 采集电压获取光敏传感器的电阻变化从而得出环境光线的变化并在TFTLCD
上面显示出来。

光敏传感器简介

光敏传感器是最常见的传感器之一它的种类繁多主要有光电管、光电倍增管、光敏
电阻、光敏三极管、太阳能电池、红外线传感器、紫外线传感器、光纤式光电传感器、色彩传
感器、CCD 和CMOS 图像传感器等。光传感器是目前产量最多、应用最广的传感器之一它在
自动控制和非电量电测技术中占有非常重要的地位。
光敏传感器是利用光敏元件将光信号转换为电信号的传感器它的敏感波长在可见光波长
附近包括红外线波长和紫外线波长。光传感器不只局限于对光的探测它还可以作为探测元
件组成其他传感器对许多非电量进行检测只要将这些非电量转换为光信号的变化即可。
STM32F103 战舰开发板板载了一个光敏二极管光敏电阻作为光敏传感器它对光的
变化非常敏感。光敏二极管也叫光电二极管。光敏二极管与半导体二极管在结构上是类似的
其管芯是一个具有光敏特征的PN 结具有单向导电性因此工作时需加上反向电压。无光照
时有很小的饱和反向漏电流即暗电流此时光敏二极管截止。当受到光照时饱和反向漏
电流大大增加形成光电流它随入射光强度的变化而变化。当光线照射PN 结时可以使PN
结中产生电子一空穴对使少数载流子的密度增加。这些载流子在反向电压下漂移使反向电
流增加。因此可以利用光照强弱来改变电路中的电流。
利用这个电流变化我们串接一个电阻就可以转换成电压的变化从而通过ADC 读取电
压值判断外部光线的强弱。
本章我们利用ADC3 的通道6PF8来读取光敏二极管电压的变化从而得到环境光线
的变化并将得到的光线强度显示在TFTLCD 上面。关于ADC 的介绍前面已经有详细介
绍了这里我们就不再细说了。

硬件设计

  1. 例程功能
    通过ADC3 的通道6PF8读取光敏传感器LS1的电压值并转换为0~100 的光线强
    度值显示在LCD 模块上面。光线越亮值越大光线越暗值越小。大家可以用手指遮挡LS1
    和用手电筒照射LS1来查看光强变化。LED0 闪烁用于提示程序正在运行。
  2. 硬件资源
    1LED 灯
    LED : LED0 –PB5
    2串口1(PA9/PA10 连接在板载USB 转串口芯片CH340 上面)
    3正点原子2.8/3.5/4.3/7/10 寸TFTLCD 模块(仅限MCU 屏16 位8080 并口驱动)
    4ADC3 通道6 –PF8
    5光敏传感器
  3. 原理图
    我们主要来看看光敏传感器和开发板的连接如下图所示
    在这里插入图片描述
    图中LS1 是光敏二极管外观看起像与贴片LED 类似战舰位于OLED 插座旁边LS1
    R34 为其提供反向电压当环境光线变化时LS1 两端的电压也会随之改变通过ADC3_IN6
    通道读取LIGHT_SENSORPF8上面的电压即可得到环境光线的强弱。光线越强电压越
    低光线越暗电压越高。

DAC 实验

本章我们将介绍STM32F103 的DACDigital -to- analog converters数模转换器功能。
我们通过三个实验来学习DAC分别是DAC 输出实验、DAC 输出三角波实验和DAC 输出正
弦波实验。

DAC 简介

STM32F103 的DAC 模块数字/模拟转换模块是12 位数字输入电压输出型的DAC。
DAC 可以配置为8 位或12 位模式也可以与DMA 控制器配合使用。DAC 工作在12 位模式
时数据可以设置成左对齐或右对齐。DAC 模块有2 个输出通道每个通道都有单独的转换器。
在双DAC 模式下2 个通道可以独立地进行转换也可以同时进行转换并同步地更新2 个通道
的输出。DAC 可以通过引脚输入参考电压Vref+以获得更精确的转换结果。
STM32 的DAC 模块主要特点有
①2 个DAC 转换器每个转换器对应1 个输出通道
②8 位或者12 位单调输出
③12 位模式下数据左对齐或者右对齐
④同步更新功能
⑤噪声\三角波形生成
⑥双DAC 双通道同时或者分别转换
⑦每个通道都有DMA 功能
DAC 通道框图如图33.1.1 所示
图33.1.1 DAC 通道框图
在这里插入图片描述
图中VDDA 和VSSA 为DAC 模块模拟部分的供电而VREF+则是DAC 模块的参考电压。
DAC_OUTx 就是DAC 的两个输出通道了对应PA4 或者PA5 引脚。ADC 的这些输入/输出
引脚信息如下表所示
在这里插入图片描述
从图33.1.1 可以看出DAC 输出是受DORxx=1/2下同寄存器直接控制的但是我们
不能直接往DORx 寄存器写入数据而是通过DHRx 间接的传给DORx 寄存器实现对DAC
输出的控制。
前面我们提到STM32F103 的DAC 支持8/12 位模式8 位模式的时候是固定的右对齐的
而12 位模式又可以设置左对齐/右对齐。DAC 单通道模式下的数据寄存器对齐方式总共有3
种情况如下图所示
在这里插入图片描述
①8 位数据右对齐用户将数据写入DAC_DHR8Rx[7:0]位实际存入DHRx[11:4]位。
②12 位数据左对齐用户将数据写入DAC_DHR12Lx[15:4]位实际存入DHRx[11:0]位。
③12 位数据右对齐用户将数据写入DAC_DHR12Rx[11:0]位实际存入DHRx[11:0]位。
我们本章实验中使用的都是单通道模式下的DAC 通道1采用12 位右对齐格式所以采
用第③种情况。另外DAC 还具有双通道转换功能。
对于DAC 双通道可用时也有三种可能的方式如下图所示
在这里插入图片描述
①8 位数据右对齐用户将DAC 通道1 的数据写入DAC_DHR8RD[7:0]位实际存入
DHR1[11:4]位将DAC 通道2 的数据写入DAC_DHR8RD[15:8]位实际存入
DHR2[11:4]位。
②12 位数据左对齐用户将DAC 通道1 的数据写入DAC_DHR12LD[15:4]位实际存入
DHR1[11:0]位将DAC 通道2 的数据写入DAC_DHR12LD[31:20]位实际存入
DHR2[11:0]位。
③12 位数据右对齐用户将DAC 通道1 的数据写入DAC_DHR12RD[11:0]位实际存入
DHR1[11:0]位将DAC 通道2 的数据写入DAC_DHR12RD[27:16]位实际存入
DHR2[11:0]位。
DAC 可以通过软件或者硬件触发转换通过配置TENx 控制位来决定。
如果没有选中硬件触发寄存器DAC_CR 的TENx 位置0存入寄存器DAC_DHRx 的数
据会在1 个APB1 时钟周期后自动传至寄存器DAC_DORx。如果选中硬件触发寄存器DAC_CR
的TENx 位置1数据传输在触发发生以后3 个APB1 时钟周期后完成。一旦数据从DAC_DHRx寄存器装入DAC_DORx 寄存器在经过时间tSETTLING之后输出即有效这段时间的长短依电
源电压和模拟输出负载的不同会有所变化。我们可以从《《STM32F103ZET6.pdf》数据手册查到
tSETTLING的典型值为3us最大是4us所以DAC 的转换速度最快是333K 左右。
不使用硬件触发TEN=0其转换的时间框图如图33.1.4 所示

在这里插入图片描述
当DAC 的参考电压为Vref+的时候DAC 的输出电压是线性的从0~Vref+12 位模式下
DAC 输出电压与Vref+以及DORx 的计算公式如下

DACx 输出电压= Vref *DORx/4096

如果使用硬件触发TENx=1可通过外部事件定时计数器、外部中断线触发DAC 转
换。由TSELx[2:0]控制位来决定选择8 个触发事件中的一个来触发转换。触发事件如下表所示
在这里插入图片描述
原表见《STM32F10xxx 参考手册_V10中文版.pdf》第185 页表71。
每个DAC 通道都有DMA 功能两个DMA 通道分别用于处理两个DAC 通道的DMA 请
求。如果DMAENx 位置1 时如果发生外部触发而不是软件触发就会产生一个DMA 请
求然后DAC_DHRx 寄存器的数据被转移到DAC_NORx 寄存器。

DAC 输出实验

本实验我们来学习DAC 输出实验。

DAC 寄存器

下面我们介绍要实现DAC 的通道1 输出需要用到的一些DAC 寄存器。
⚫ DAC 控制寄存器DAC_CR
DAC 控制寄存器描述如图33.2.1.1 所示
在这里插入图片描述
DAC_CR 的低16 位用于控制通道1高16 位用于控制通道2下面介绍本实验需要设置
的一些位
EN1 位用于DAC 通道1 的使能我们需要用到DAC 通道1 的输出该位必须设置为1。
BOFF1 位用于DAC 输出缓存控制这里STM32 的DAC 输出缓存做的有些不好如果使
能的话虽然输出能力强一点但是输出没法到0这是个很严重的问题。所以本章的三个实
验我们都不使用输出缓存即该位设置为1。
TEN1 位用于DAC 通道1 的触发使能我们设置该位为0不使用触发。写入DHR1 的值
会在1 个APB1 周期后传送到DOR1然后输出到PA4 口上。
TSEL1[2:0]位用于选择DAC 通道1 的触发方式这里我们没有用到外部触发所以这几位
设置为0 即可。
WAVE1[1:0]位用于控制DAC 通道1 的噪声/波形输出功能我们这里没用到波形发生器
所以默认设置为00不使能噪声/波形输出。
MAMP[3:0]位是屏蔽/幅值选择器用来在噪声生成模式下选择屏蔽位在三角波生成模式
下选择波形的幅值。本实验没有用到波形发生器所以设置为0 即可。

DMAEN1 位用于DAC 通道1 的DMA 使能本实验没有用到DMA 功能所以设置为0。
⚫ DAC 通道1 12 位右对齐数据保持寄存器DAC_DHR12R1
DAC 通道1 的12 位右对齐数据保持寄存器描述如图33.2.1.3 所示
在这里插入图片描述

该寄存器用来设置DAC 输出通过写入12 位数据到该寄存器就可以在DAC 输出通道
1PA4得到我们所要的结果。

硬件设计

  1. 例程功能
    使用KEY1/KEY_UP 两个按键控制STM32 内部DAC 的通道1 输出电压大小然后通过
    ADC2 的通道14 采集DAC 输出的电压在LCD 模块上面显示ADC 采集到的电压值以及DAC
    的设定输出电压值等信息。也可以通过usmart 调用dac_set_voltage 函数来直接设置DAC 输
    出电压。LED0 闪烁提示程序运行。
  2. 硬件资源
    1LED 灯LED0 –PB5
    2串口1(PA9/PA10 连接在板载USB 转串口芯片CH340 上面)
    3正点原子2.8/3.5/4.3/7/10 寸TFTLCD 模块(仅限MCU 屏16 位8080 并口驱动)
    4独立按键KEY1 - PE3、WK_UP - PA0
    5ADC3 通道1 –PA1
    6DAC1 通道1 –PA4
  3. 原理图
    我们来看看原理图上ADC3 通道1PA1和DAC1 通道1PA4引出来的引脚如下图
    所示

在这里插入图片描述
我们只需要通过跳线帽连接ADC 和DAC就可以使得ADC3 通道1PA1和DAC 1 通
道1PA4连接起来。对应的硬件连接如图33.2.2.2 所示
在这里插入图片描述

DAC 输出三角波实验

本实验我们来学习使用如何让DAC 输出三角波DAC 初始化部分还是用DAC 输出实验
的所以做本实验的前提是先学习DAC 输出实验。

DAC 寄存器

本实验用到的寄存器在DAC 输出实验都有介绍。

硬件设计

  1. 例程功能
    使用DAC 输出三角波通过KEY0/KEY1 两个按键控制DAC1 的通道1 输出两种三角
    波需要通过示波器接PA4 进行观察。也可以通过usmart 调用dac_triangular_wave 函数来控
    制输出哪种三角波。LED0 闪烁提示程序运行。
  2. 硬件资源
    1LED 灯
    LED0 –PB5
    2串口1(PA9/PA10 连接在板载USB 转串口芯片CH340 上面)
    3正点原子2.8/3.5/4.3/7/10 寸TFTLCD 模块(仅限MCU 屏16 位8080 并口驱动)
    4独立按键KEY0 –PE4、KEY1 –PE3
    5DAC1 通道1 - PA4
  3. 原理图
    我们只需要把示波器的探头接到DAC1 通道1PA4引脚就可以在示波器上显示DAC
    输出的波形。PA4 对应P10 的DAC 排针如图33.3.2.1 所示

在这里插入图片描述

DAC 输出正弦波实验

本实验我们来学习使用如何让DAC 输出正弦波。实验将用定时器7 来触发DAC 进行转换
输出正弦波以DMA 传输数据的方式。

DAC 寄存器

本实验用到的寄存器在前面的实验都有介绍。

硬件设计

  1. 例程功能
    使用DAC 输出正弦波通过KEY0/KEY1 两个按键控制DAC1 的通道1 输出两种正弦
    波需要通过示波器接PA4 进行观察。TFTLCD 显示DAC 转换值、电压值和ADC 的电压值。
    LED0 闪烁提示程序运行。
  2. 硬件资源
    1LED 灯
    LED0 –PB5
    2串口1(PA9/PA10 连接在板载USB 转串口芯片CH340 上面)
    3正点原子2.8/3.5/4.3/7/10 寸TFTLCD 模块(仅限MCU 屏16 位8080 并口驱动)
    4独立按键KEY0 –PE4、KEY1 –PE3
    5ADC1 通道1 –PA1
    6DAC1 通道1 –PA4
    7DMA(DMA2_Channel13)
    8定时器7
  3. 原理图
    我们只需要把示波器的探头接到DAC1 通道1PA4引脚就可以在示波器上显示DAC
    输出的波形。PA4 对应P10 的DAC 排针硬件连接如图33.4.2.1 所示
    在这里插入图片描述
阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6