【STM32 ADC】

时间:2024-10-25 13:41:49

STM32 ADC功能简介

文章目录

  • 前言
  • 一、ADC简介
  • 二、逐次逼近型ADC
  • 三、STM32的ADC内部框图
  • 四、STM32ADC输入通道
  • 五、规则组的四种转换模式
  • 六、规则组的触发源
  • 七、数据对齐
  • 八、转换时间
  • 九、校准部分
  • 十.ADC采样测量电压的程序设计
  • 十一、ADC的迟滞比较、滤波设计
  • 十二、四通道ADC采用问题
  • 总结


前言

学习ADC转换的基本原理,学会使用STM32配置ADC转换功能


一、ADC简介

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

12为逐次逼近型ADC,1us的转换时间(转换频率为1MHZ);
输入电压范围0~3.3V,转换结果范围:0 ~ 4095;

STM32F1系列单片机(最多)有18个输入通道,(最多)可以测量16个外部(GPIO口)和两个内部信号源(内部温度、内部基准电压,该电压是不随外部供电电压的变化而变化的,当外部供电不是标准的3.3v可以使用这个参考电压 );

STM32F1系列单片机的规则组和注入组两个转换单元
普通AD转换流程是启动一次转换就读取一次值,循环往复操作;
STM32可以一次性启动一个组,连续转换多个值;

模拟看门狗自动检测输入电压范围;
模拟看门狗可以检测指定某些通道,当AD值高于它设定的上阈值或者低于下阈值时,就会申请中断,此时可以在中断函数里执行相应的操作;

STM32F103C8T6 ADC资源:ADC1、ADC2,10个外部输入通道;

二、逐次逼近型ADC

下列是比较经典的ADC0809数码转换器内部构造图:
在这里插入图片描述
地址锁存和译码详单与一个数据选择器,ADDA、ADDB、ADDC用于控制八路INx信号的输入;
ALE是一个锁存信号;
信号通路配置完成后会经过电压比较器,电压比较器可以判断两个输入信号电压的大小,这里比较电压是DAC(数模转换器)的输出端;
数模转换器(DAC)的作用是给定一个数值,它可以输出对应的电压,DAC的内部是通过加权电阻网络实现的;
当DAC输出的电压比较大,就调小DAC数据,反之就增大DAC数据,直到DAC数据和输入电压数据近似相等;

比较过程可以采用2分法来实现;
假如ADC的数值是0~255,每次使用2分法比较的数可以为128、64、32…对应二进制数的位权,也就是说比较过程相当于对二进制数从高位到地位判断是0还是1的过程;
对于8位的ADC,从高位到低位依次判断8次就可以找到未知电压的编码了,而对于STM32F1系列的单片机,由于其ADC是12位,则需要依次判断12位才可以得到未知电压的编码;

ADC转换结束后,输出得到的数值,存储到地址锁存器其中,地址锁存器对于8位的ADC就是8位的,对于12位ADC就是12位的;
EOF(End Of Convert),转换结束信号;
START开始转换,给一个输入脉冲,开始转换;

CLOCK是ADC时钟,因为ADC内部是一步一步进行判断的,需要时钟来推动这个过程;
VREF+与VREF-是DAC的参考电压,比如给定一个数值255是对应5V还是3.3v由参考电压决定;

DAC的参考电压也决定了ADC的输入范围,所以这个电压也是ADC的参考电压;
VCC是整个芯片电路的供电;
通常参考电压的正极和VCC是接在一起的,参考电压的负极VREF-和GND是接在一起的;

三、STM32的ADC内部框图

回到STM32的ADC内部框图:
在这里插入图片描述
对于普通的ADC,多路开关一般都是只选中其中的一个的,即选中某个通道、开始转换、等待转换结果完成、取出转换结果;
STM32的ADC可以一次选中多个通道进行转换,而且在转换的时候分为规则通道组和注入通道组;
规则通道组可以一次最多选中16个通道,不过其只有一个数据寄存器,最多只能放一个通道转换数据,存在数据覆盖的问题;对于规则组转换最好搭配DMA来实现,DMA可以将16个转化数据转移到其它地方,防止数据被覆盖;
注入通道组最多可以选中4个通道,同时注入组有四个数据寄存器,不用担心数据被覆盖的问题;

在STM32中触发ADC转换的方式有两种:
1.软件触发
在程序里调用一条代码就可以启动转换;
2.硬件触发
选中触发源,触发源分为规则组和注入组;
触发源主要是来自于定时器,定时器的各个通道、TRGO定时器主模式的输出;

定时器可以通向ADC、DAC这些外设,用于触发转换;

由于ADC经常需要过一个固定的时间段转化一次,比如每隔1ms转换一次,通常的做法是用定时器每隔1ms申请一次中断,在中断里手动开始一次转换。

但是频繁进入中断对主程序是有一定影响的,中断过多可能会阻塞主程序的执行,并且不同中断之间由于优先级的不同也会导致某些中断不能及时得到响应,如果触发ADC的中断不能及时响应,那么ADC的转换频率就会产生影响了。

因此,对于这种需要频繁进中断,并且在中断里只完成了简单工作的情况,一般都会有硬件的支持,例如可以给TIM3定时1ms的时间,把TIM3的更新时间选择作为TRGO输出,在ADC规则通道组中选择触发信号为TIM3的TRGO,这样TIM3的更新事件就能通过硬件自动触发ADC的转换了,整个过程不需要进行中断,节省了中断资源;

另外还可以选择外部中断引脚来触发ADC的转换;
VREF+、VREF-、VDDA、VSSA,其中VREF+、VREF-是ADC的参考电压,决定了ADC输入电压的范围,VDDA和VSSA是ADC的供电引脚,一般情况下VREF+需要接VDDA,VREF-需要接VSSA(电路连接已经在芯片内部完成);
VDDA与VSSA是内部模拟部分的电源,比如ADC、RC振荡器、锁相环,在单片机的外围电路中VDDA接3.3v,VSSA接GND,因此ADC的输入参考电压范围就是0~3.3v;

ADCCLK是ADC的时钟,是用于驱动其内部逐次比较的时钟;
ADCCLK来自ADC的预分频器,这个ADC预分频器是来自RCC的;
对于ADC预分频器,选择4分频是18MHZ,超过了上限14MHZ,所以只能选择6分频、8分频;
在这里插入图片描述
DAC的内部框图中DMA请求用于触发DMA进行数据转运的;

DAC数据寄存器用于存放DAC转换结果;
DAC的模拟看门狗可以用于存放阈值高限和阈值低限,如果启用了看门狗并且指定了看门的通道,看门狗就会关注它看门的通道,一旦超过这个阈值范围,他就会申请一个模拟看门狗的中断;

标志位解释:
内部框图中规则组和注入组转换完成标志通过一个或门电路生成EOF信号;
EOC是规则或者注入组组完成的信号,JEOC是注入组完成的信号,读取EOC信号就可以判断转换是否结束了,同时这两个标志位也可以去到NVIC申请中断;

四、STM32ADC输入通道

ADC通道和引脚复用关系:
在这里插入图片描述
在STM32中ADC1与ADC2通道的外部输入引脚映射是完全相同的;

双ADC模式的简单介绍:
双ADC模式就是ADC1和ADC2一起工作,它们可以配合组成同步模式、交叉模式等,交叉模式表示ADC1和ADC2交叉地对一个通道进行采样,这样可以进一步提高采样率;
ADC1和ADC2也可以同时单独工作,配置不同引脚进行采样输入和ADC转换;

五、规则组的四种转换模式

单次转换、非扫描模式
单次转换每次触发一次才会有开始一次ADC转换,转换结束后置EOC结束标志位,等待下一次触发;(触发一次转换一次,转换之后等待一段时间,再触发再转换)
在非扫描模式下,只有单个通道位置有效;

连续转换、非扫描模式
在单次转换结束后不会停止,而是立刻开始下一轮的转换,然后一直转换下去(触发一次即可不停转换,开启转换后不需要等待一段时间);
当想要读取ADC转换结果的值,直接从数据寄存器中读取即可;

单次转换、扫描模式
单次转换,每触发一次,转换结束后就会停下来;
扫描模式,需要选择通道数目;
为了防止数据被覆盖,需要用DMA及时将数据挪走;

连续转换、扫描模式
一次转换完成后,立刻开启下一次的转换;

六、规则组的触发源

在这里插入图片描述
至于是选择定时器还是外部引脚/片上定时器的内部信号,需要通过AFIO映射选择;
触发信号可以通过EXTSE[2:0]寄存器来完成;

七、数据对齐

在这里插入图片描述
STM32F1的ADC是12位的,其转换结果就是一个12位的数据,由于数据寄存器是16位的,所以存在一个数据对齐的问题;
左对齐相当于把数据向左移动了4位,二进制数左移一位相当于把原数据乘以2,左移4位相当于乘以2^4 (X16),直接读取该数据会比原数据大16倍;
一般情况选择右对齐;

八、转换时间

AD转换的步骤:采样,保持,量化,编码
STM32 ADC的总采样时间为:
Tconv = 采样时间 + 12.5个ADC周期
例如:当ADCCLK = 14MHZ,采样时间为1.5个ADC周期,
Tconv = 1.5 + 12.5 = 14 个采样周期 = 1 us

采样保持电路的解释:
AD转换的量化、编码是需要一小段时间的,如果在这段时间内电压不断变化将会不利于量化和编码,于是在量化和编码前需要设置一个采样开关,采样时打开这个开关采集外部电压(比如用小电容存储这个电压),断开开关再进行后面的AD转换,再量化编码的期间,电压时钟保持不变,这样才能精确地定位未知电压的位置;

采样时间是采样保持花费的时间,这个可以再程序中进行配置,采样时间越大,越能避免一些毛刺信号的干扰,不过转换时间也会相应延长;

12.5个ADC周期是量化编码花费的时间,因为是12位的ADC,所以需要花费12个周期,多花半个周期可能是为了做一些其它东西;

ADC周期就是从RCC分频过来的ADCCLK,ADCCLK最大是14MHZ;

九、校准部分

ADC内部有一个自校准模式,校准可大幅减小因为内部电容器组的变化造成的精准度误差。校准期间,每个电容器上都会计算出一个误差修正码(数字值),这个码用于消除再随后的转换中每个电容器上产生的误差;
建议在每次上电后执行一次校准;
校准前,ADC必须处于关电状态超过至少两个ADC时钟周期;

十.ADC采样测量电压的程序设计

在这里插入图片描述
配置流程:
①开启GPIO与ADC外设的RCC时钟,ADCCLK的分频器也需要配置;
代码如下(示例):
②配置GPIO,将所需的GPIO配置成模拟输入的模式;
③配置多路开关,输入通道接入到规则组的列表中;
④配置ADC转换器,包括ADC是单次转换还是连续转换、扫描还是非扫描、有几个通道,触发源是什么,数据对齐是左对齐还是右对齐;
⑤(可选)如果需要看门狗可以配置看门狗的的检测阈值和监测通道,如果需要开启中断需要在中断输出控制里用ITConfig函数开启对应的中断输出,之后需要在NVIC里配置优先级即可触发中断;
⑥调用ADC_Cmd函数开启ADC。

关于ADC的校准部分可以参考数据手册,对ADC进行校准可以减小误差;

在stm32f10x_rcc.h里可以找到ADC的时钟配置相关的库函数;

void RCC_ADCCLKConfig(uint32_t RCC_PCLK2);

在stm32f10x_adc.h里可以找到ADC相关配置,下面简单介绍部分所需的各个库函数的作用;

获取ADC转换结束标志位

FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG);

规则组配置
ADCx:ADC模块选择
ADC_Channel:ADC通道选择
Rank:序列的位置
ADC_SampleTime:采样时间

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

ADC外部触发转换控制,是否允许外部触发转换;

void ADC_ExternalTrigConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);

ADC获取转换值

uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx);

开启ADC

void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState);

校准ADC

void ADC_ResetCalibration(ADC_TypeDef* ADCx);
FlagStatus ADC_GetResetCalibrationStatus(ADC_TypeDef* ADCx);
void ADC_StartCalibration(ADC_TypeDef* ADCx);
FlagStatus ADC_GetCalibrationStatus(ADC_TypeDef* ADCx);

1.调用复位校准函数
void ADC_ResetCalibration(ADC_TypeDef* ADCx);
2.等待复位校准完成
ADC_GetResetCalibrationStatus(ADC_TypeDef* ADCx);
3.开启校准
void ADC_StartCalibration(ADC_TypeDef* ADCx);
4.等待校准完成
ADC_GetCalibrationStatus(ADC_TypeDef* ADCx);


十一、ADC的迟滞比较、滤波设计

ADC采样值会发送波动,如果直接用作阈值判断,可能会出现控制逻辑频繁切换,例如用光敏电阻去控制LED的亮灭,设定某一阈值开启或关闭LED,在这个阈值附近会因为ADC采样的波动而发生LED灯的来回亮灭,此时可以使用迟滞比较的设计,比如设定两个阈值,当电压低于下阈值时开灯,高于上阈值才关灯,这个设计可以类比TTL施密特触发器的设计;

针对ADC转换出来的数值频繁跳变不稳定的现象,可以采用均值滤波的方式,比如读取10~20个值,取平均值作为AD的值;

此外也可以通过裁剪分辨率的方式,把ADC转换值的尾数去掉,达到稳定的效果;

十二、四通道ADC采用问题

当一次性采集4个引脚的模拟电压值时,为什么不将ADC数据连接到规则组1 ~ 4中,在规则组连续扫描1~4组ADC数据?

问题1.在扫描模式下,启动列表后,其中每个单独的通道转换完成后不会产生任何的标志位,也不会触发中断,无法知道某一个通道是不是转换完了,只有在整个列表都转换完成后才会产生一次EOC标志位,并触发中断,但是由于规则组只有一个数据寄存器,在EOC标志位置位时,前面的数据已经覆盖丢失了;

问题2.AD转换是非常快的,转换一个通道所用的时间在几微米的量级,如果不能在几us的时间把数据转运走,那么数据就会丢失,这样对软件手动转换数据的要求比较苛刻;

针对上述问题,在不使用DMA的情况下可以使用ADC的间断模式,即在扫描的时候每转换一个通道就暂停一次,等软件程序取走数据后再扫描下一个通道的数据,不过这样依旧不能解决单次转换完成后没有EOC标志位的问题,启动转换完成一次后只能通过delay延迟的方式延迟足够长的时间才能确保下一通道的转换完成,这种做法依旧不推荐;

如果是采用单次转换,非扫描方式呢?
这种方式每次转换一个通道的数据后会产生一次EOC标志位,下次转换更换扫描通道即可依次扫描出四个通道的ADC值;

总结

例如:以上就是今天要讲的内容,本文仅仅简单介绍了STM32的ADC部分的内容,更多内容请参照数据手册。