目录
硬件和原理:
(如果想快速入手使用的话,这边可以略过直接上手配置代码和cubeMX)
稍微了解,加深对代码进行配置的理解。
STM32G431内部集成2个有最高12位的ADC(ADC1和ADC2)他们是逐次逼近型数模转换器。
主要特性:
可配置的转换精度: 6 位, 8 位, 10 位, 12 位转换电压范围: 0 ~ V REF+ ( 一般接到 3.3V 电源 ,不能超过 STM32 芯片电源电压)19 个转换通道: 16 个外部通道( IO 引脚) + 3 个内部通道(温度传感器、内部电压参考、电池供电监测)采样时间可配置扫描方向可配置多种转换模式:单次,连续数据存放对齐方式可配置:左对齐,右对齐( ADC 的结果存储在一个左对齐或右对齐的 16 位数据寄存器中)启动转换方式可配置:软件触发,硬件触发可设置上下门限的模拟看门狗DMA 功能在转换结束、注入转换结束以及发生模拟看门狗或溢出事件时产生中断
一个ADC可以处理十九个通道
功能框图:
大致可分为七个部分:
1、电源和参考电压:
如果有低功耗的要求,那就配置内部寄存器,控制ADC的电源开关/
2、输入通道:
0~15个外部通道和三个内部通道,
考试的时候想要知道是哪一个引脚可以去芯片手册上查找
3、通道和转换顺序:
实际就是排序
规则通道:
意思就是规规矩矩的按照顺序来转换,平时用的就是这类通道
规则通道序列:
规则通道序列由四个寄存器控制着,ADC_SQR1~ADC_SQR4四个寄存器,从SQR1到SQR4这四个32位寄存器中规定了16个转换,而这16个转换也不是必须全部都用,可以编程控制的,并且每一个转换可以存放ADCx_IN0~15的任何一个输入通道,
注入通道:
这里和规则通道就不同了,注入可以理解为插队。他是一种在规则通道转换的时候强行插入要转换的一种。这点和中断有点像,当规则通道转换中,有注入通道插队那么得先传换注入通道,然后在倒回来转换规则通道。
注入通道顺序:
四个注入通道也能进行排序。
但是整体上来看注入通道的优先级更高。
转换时序图:
ADC在开始精确转换之前需要一段稳定时间t.,ADC 开始转换并经过十五个周期后,EOC标志1,转换结果存放在16位ADC数据寄存器中。
ADC_CLK:时钟
ADON:ADC的开关,寄存器的一个位,打开这个位了,AD就正式使能了
SWS:软件触发
ADC:进行转换
EOC:发送转换结束的标志
4、触发源:
使用控制寄存器启动时,很简单,为ADOD位写1开始转换,写0停止转换。
使用外部事件来触发转换,这个触发包括内部定时器触发和外部IO触发。
触发源的选择由ADC_CFGR的EXTSEL[3:0]和ADC_JSQR的JEXTSEL[3:0]位来控制,
EXTSEL[3:0]用于规则通道的触发源,
JEXTSEL[3:0]用于选择注入通道的触发源。
5、转换时间
时钟来源:1、System clock 或 2、PLL 'P'output 或 3、adc_hclk
采样时间和转换时间:
ADC_SMPR1和ADC_SMPR2的SMP[2:0]位设置,
每个通道可以分别设置成不同的时间经行采样,
采样的周期最少是三个,
周期等于1/ADC_CLK ,
TCONV=采样时间+12个周期,
当ADC_CLK = 30MHz,ADC为三周期,那么总转换时间为:TCONV=3+12=15个周期=(1/30000000)*15=0.5us
6、数据寄存器
将注入通道和规则通道排完的数据分别送到下边的寄存器当中
对齐问题:一般通道的精度都为12位,然后将转换完的数据放到相应的寄存器当中 但是寄存器有16位,那么这样就有两种对齐方式,在数据寄存器中12个数据靠左或者靠右*(左对齐和右对齐)。
注入通道可以连续转换4个通道的数据,而规则通道可以连续转换16个通道的数据
数据寄存器也就是数据暂存的地方,注入数据寄存器有四个,分别对应四个注入通道,
但是规则数据寄存器不同,它只有一个数据寄存器,必须要等到CPU将转换过来的数据读走之后才能继续读下一个(效率相对较低)
相关寄存器:
7、模拟看门狗和中断
注入数据和规则数据全部来自于它们对应的注入规则通道,这些数据在AD里边是有盯着的
,这个盯着的部分叫做看门狗
如果ADC转换的模拟电压低于阀值下限或者高于阀值上限(也就是寄存器内的数据的上限和下限),则AWD模拟看门狗状态会置1,产生一个事件,生成ADC的中断去告诉CPU。
对于ADC来说除了看门狗产生中断事件,ADC转换完成后也相应的产生一个中断事件。
但是对于一个ADC中断来说,只有一个中断线,所以在函数当中还要判断是哪类型的中断
ADC工作模式:
单次传输模式:
对应上边给的相关寄存器来看。
单次转换一次转换一个通道。
在单次转换模式下,ADC执行一次转换。ADC_CFGRD的CCONT位为0时,可通过以下方式启动此模式:
• 将 ADC_CR 寄存器中的 ADSTART 位置 1 (仅适用于规则通道)• 将 JADSTART 位置 1 (适用于注入通道)• 外部触发(适用于规则通道或注入通道)完成所选通道的转换之后:
if转换了规则通道
• 转换数据存储在 16 位 ADC_DR 寄存器中• EOC (转换结束)标志置 1• EOCIE 位置 1 时将产生中断if转换了注入通道:
• 转换数据存储在 16 位 ADC_JDRy 寄存器中• JEOC (注入转换结束)标志置 1• JEOCIE 位置 1 时将产生中断然后,ADC停止。
不连续采样模式:
一次触发转换N个
规则组:
示例:
n=3,要转换的通道=0、1、2、3、6、7、9、10(L[3:0]=8)
第1次触发:转换序列0、1、2
第2次触发:转换序列3、6、7
第3次触发:转换序列9、10并生成EOC事件
第4次触发:转换序列0、1、2
注入组:
n=1,要转换的通道=1、2、3(JL[1:0]=3)
第1次触发:转换通道1
第2次触发:转换通道2
第3次触发:转换通道3并生成EOC和JEOC事件
第4次触发:通道1
常规扫描模式(连续采样):
将此位置1后,ADC会扫描在ADC_SQRx寄存器(对于规则通道)或者ADC_JSQR(对于注入通道)中选择的所有通道。为组中每一个通道都执行一次转换。每次自定转换完后会自动进入该组中下一个通道。如果将CONT位置1 ,规则通道转换不会再组中最后一个所选通道处停止,而是再一次从第一个通道继续转换。
连续循环转换模式:
在连续转换模式下,ADC结束一个转换后立即启动一个新的转换。ADC_CFGRD的CONT位为1时,可通过外部触发或将ADC_CR寄存器中的ADC_DR位置1来启动此模式(仅适用于规则通道)。
每次转换之后:
如果转换了规则通道组:
• 上次转换的数据存储在 16 位 ADC_DR 寄存器中• EOC (转换结束)标志置 1• EOCIE 位置 1 时将产生中断注意,无法连续转换注入通道,连续模式下唯一的例外情况是,注入通道配置在为规则通道之后自动转换(使用JAUTO位)。
注入转换扫描模式:
一种中断的意思,单次触发完成之后,如果产生了注入通道,那么注入通道会打断原来的规则通道,注入通道转换完后又会回到之前的规则通道了转换。
触发注入
在规则通道组转换期间出现外部注入,
则当前的转换会复位,并且注入通道序列会切换为单次扫描模式。
然后,规则通道组的规则转换会从上次中断的规则转换处恢复。
如果在注入转换期间出现规则事件,注入转换不会中断,
但在注入序列结束时会执行规则序列。
自动注入
注入组中的通道会在规则组通道之后自动转换。
这可用于转换最多由20个转换构成的序列
DMA应用模式:
由于规则通道组只有一个数据寄存器,
通常,对于多个规则通道的转换,每次转换完一个数据,需要发出中断请求,CPU读取信息,但是如果转换数据量特别的时候,给CPU带来负担,有可能还没读走就转换了新的数据。
在使能DMA模式的情况下,每完成规则通道组中的一个通道转换后,都会生成一个DMA请求。这样便可将转换的数据从ADC_DR寄存器传输到用软件选择的目标位置。摆脱对CPU的依赖。
多重ADC同时模式:
一次触发多个ADC同时转换通道数据
在具有两个或更多ADC的器件中,可使用双重(具有两个ADC)和三重(具有三个ADC)ADC模式。
多重ADC模式主要解决的问题是:在保证高精度下,提高采样率。
多重ADC交替模式:
多重ADC交替触发模式:
不常用
双重ADC模式
发生第一次触发时,将转换 ADC1 中注入组的所有通道
发生第二次触发时,将转换 ADC2 中注入组的所有通道
以此类推,一般放在通用数据寄存器当中,而不是规则或者注入数据寄存器当中。
软件和CUBEMX配置:
采集一路ADC:
原理图:
根据官方提供的原理图可知ADC的引脚接线为ADC1的PB12,和ADC2的PB15
CubeMX的配置:
先配置好基础的时钟等配置,
在PB12位置选择:对应的通道为IN11,然后在Analog中选择ADC1,对通道11的模式进行选择,
差分模式和单端模式:
单端模式:就是一个电压,
差分模式:输入的一个差分信号,eg:输入一个5V和1V那么他得到的数据就是4V
然后到Configuration里进行ADC的基本配置:
Mode:
对通道进行配置:
然后点击工程生成:
代码编写:
参考一下官方提供的代码,先进行初始化,然后在while中
转跳到getADC()函数当中,该ADC代码在比赛中需要自己编写的。
//ADC1数据采集
uint16_t getADC1(void)
{
uint16_t adc = 0;
HAL_ADC_Start(&hadc1);
adc = HAL_ADC_GetValue(&hadc1);
return adc;
}
采集两路ADC:
ADC1和ADC2为两个独立的工作模式
ADC2我们用的是通道15,然后仿照ADC1的配置,然后同样读ADC2的数据进行获取
//ADC2数据采集
uint16_t getADC2(void)
{
uint16_t adc = 0;
HAL_ADC_Start(&hadc2);
adc = HAL_ADC_GetValue(&hadc2);
return adc;
}
数据转换和显示参照ADC即可。
效果展示: