STM32模数转换器ADC
Posted 宇努力学习
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STM32模数转换器ADC相关的知识,希望对你有一定的参考价值。
目录
一、ADC模数转换概述
ADC的作用
采集传感器的数据,测量输入电压,检查电池电量剩余,监测温湿度等。
ADC的性能指标
量程:能测量的电压范围 分辨率:ADC的分辨率通常以输出二进制数的位数表示,位数越多,分辨率越高,一般来说分辨率越高,转化时间越长。 转化时间:模拟输入电压在允许的最大变化范围内,从转换开始到获得稳定的数字量输出所需要的时间称为转换时间12位精度下转换速度可高达1MHz 可配置的转换精度:6位,8位,10位,12位 转换电压范围:0 ~ 3.6V,V SSA ~ V DDA 供电范围:2.4V ~ 3.6V 19个转换通道: 16个外部通道、 3个内部通道 采样时间可配置 ADC 的结果可以左对齐或右对齐方式存储在 16 位数据寄存器中
APB时钟的2或4分频,最高14MHz优点:不会有时钟域之间的同步带来的抖动,触发事件和转换的起始时刻之间的延迟是确定 的,从 而保证转换之间的时间间隔是固定的
缺点: ADC的转换时间和系统时钟频率相关,受系统频率的影响较大
片上14MHZ HSI RC振荡器优点:无论MCU的运行频率,都可以保证最高的ADC工作频率可以使用自动节电模式(自动开启或关闭14MHz的内部振荡器)
缺点:触发信号的同步会带来抖动,触发事件和转换的起始时刻之间的延迟不确定
19路复用通道● 16 个从 GPIO 引脚引入的模拟输入 (ADC_IN0...ADC_IN15)
● 3 个内部模拟输入 ( 温度传感、内部参考电压、 VBAT 通道 )
ADC 可以转换一个单一通道或自动扫描一个序列通道。被转换的通道序列必须在通道选择寄存器 ADC_CHSELR 中编程选择:每个模拟输入通道有专门的一位选择位 (CHSEL0...CHSEL18).
注:
ADC 通知应用每次转换结束 (EOC) 事件
ADC 通知应用每次序列转换结束 (EOS) 事件。
这些标志位都是在ADC 中断和状态寄存(ADC_ISR)中
ADC_CFGR1可配置COUNT位 。
可编程采样时间 (SMP)T Sampling 可配置: SMP[2:0]@ADC_SMPR
需要和外部电路的输入阻抗匹配,采样时间适用于所有通道
转化的时间T conversion 取决于转换精度: RES[1:0]@ADC_CFGR1
每个通道总的转换时间等于:
T Sampling + T conversion
n 转换时间快速预览表不需要高转换精度的应用,可以通过降低精确度来提高转换速度
假设ADC模块工作在14MHz的最高工作频率下
软件触发软件设置ADC_CR的ADSTART=1 时,触发选择有效。
外部事件触发外部事件 ( 例如:定时器TRGO、输入引脚 ) 触发,可以设置触发源以及触发极性
检测待转换的模拟电压
电压超出检测范围就置位AWD@ADC_ISR,并条件性地产生中断
检测范围由上下门限寄存器指定、 12位的ADC_HTR和ADC_LTR有效值
模拟看门狗的使能控制
AWDEN@ADC_CFGR1
检测所有通道还是单个通道由AWDSEL@ADC_CFGR1决定
检测哪个单个通道由AWDCH[4:0]@ADC_CFGR1决定
二、单通道采集和多通道采集
int main(void)
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration----------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_ADC_Init();
/* USER CODE BEGIN 2 */
HAL_ADC_Start_IT(&hadc);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
HAL_Delay(1000);
HAL_ADC_Start_IT(&hadc);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
/* USER CODE END 3 */
uint32_t light_value;
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
light_value = HAL_ADC_GetValue(hadc);
printf("light_value = %d\\n",light_value);
有两种方式来进行多通道采集,第一种是判断EOC标志,来了就赶紧取走不然会被覆盖
第二种是DMA,也是正常使用时最推荐用的
这次用的EOC判断
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
uint32_t temp = 0;
if(GPIO_Pin == GPIO_PIN_8)
HAL_ADC_Start(&hadc);
while( !(hadc.Instance->ISR & (1<<2))); //如果退出表示EOC置位,当前通道转化结束
temp = HAL_ADC_GetValue(&hadc);
printf("key adc value = %d\\n", temp);
while( !(hadc.Instance->ISR & (1<<2))); //如果退出表示EOC置位,当前通道转化结束
temp = HAL_ADC_GetValue(&hadc);
printf("light adc value = %d\\n", temp);
HAL_ADC_Stop(&hadc);
stm32F103之ADC模数转换
一、ADC简介
通常是指一个将模拟信号转变为数字信号的电子元件。通常的模数转换器是把经过与标准量比较处理后的模拟量转换成以二进制数值表示的离散信号的转换器。
12位ADC是一种逐次逼近型模拟数字转换器。它有多达18个通道,可测量16个外部和2个内部信号源。各通道的A/D转换可以单次、连续、扫描或间断模式执行。ADC的结果可以左对齐或右对齐方式存储在16位数据寄存器中。 模拟看门狗特性允许应用程序检测输入电压是否超出用户定义的高/低阀值。
二、ADC功能框图
掌握了ADC 的功能框图,就可以对ADC 有一个整体的把握,在编程的时候可以做到了然如胸,不会一知半解。框图讲解采用从左到右的方式,跟ADC 采集数据,转换数据,传输数据的方向大概一致。
三、ADC功能描述
1、电压输入范围
ADC 输入范围为:VREF- ≤ VIN ≤ VREF+。由VREF-、VREF+ 、VDDA 、VSSA、这四个外部引脚决定。
设计原理图的时候一般把VSSA和VREF-接地,把VREF+和VDDA 接3V3,得到ADC的输入电压范围为:0~3.3V。
2、输入通道
我们确定好ADC 输入电压之后,那么电压怎么输入到ADC?这里我们引入通道的概念,STM32 的ADC 多达18 个通道,其中外部的16 个通道就是框图中的ADCx_IN0、ADCx_IN1...ADCx_IN5。这16 个通道对应着不同的IO 口,具体是哪一个IO 口可以从手册查询到。其中ADC1/2/3 还有内部通道:ADC1的通道16连接到了芯片内部的温度传感器,Vrefint 连接到了通道17。ADC2 的模拟通道16 和17 连接到了内部的VSS。ADC3 的模拟通道9、14、15、16 和17 连接到了内部的VSS。
我们在编程的时候需要根据使用的IO引脚来确定具体的通道。外部的16 个通道在转换的时候又分为规则通道和注入通道,其中规则通道最多有16路,注入通道最多有4 路。那这两个通道有什么区别?在什么时候使用?
规则通道
规则通道:顾名思意,规则通道就是很规矩的意思,我们平时一般使用的就是这个通道。
注入通道
注入,可以理解为插入,插队的意思,是一种不安分的通道。它是一种在规则通道转换的时候强行插入要转换的一种。如果在规则通道转换过程中,有注入通道插队,那么就要先转换完注入通道,等注入通道转换完成后,再回到规则通道的转换流程。这点跟中断程序很像,都是不安分的主。所以,注入通道只有在规则通道存在时才会出现。
3、转换顺序
规则序列
规则序列寄存器有3 个,分别为SQR3、SQR2、SQR1。SQR3 控制着规则序列中的第一个到第六个转换,对应的位为:SQ1[4:0]~SQ6[4:0],第一次转换的是位4:0 SQ1[4:0],如果通道16 想第一次转换,那么在SQ1[4:0]写16 即可。SQR2 控制着规则序列中的第7 到第12 个转换,对应的位为:SQ7[4:0]~SQ12[4:0],如果通道1 想第8 个转换,则SQ8[4:0]写1即可。SQR1 控制着规则序列中的第13 到第16 个转换,对应位为:SQ13[4:0]~SQ16[4:0],如果通道6 想第10 个转换,则SQ10[4:0]写6 即可。具体使用多少个通道,由SQR1 的位L[3:0]决定,最多16 个通道。
注入序列
注入序列寄存器JSQR 只有一个,最多支持4 个通道,具体多少个由JSQR 的JL[2:0]决定。如果JL 的 值小于4 的话,则JSQR 跟SQR决定转换顺序的设置不一样,第一次转换的不是JSQR1[4:0],而是JCQRx[4:0] ,x = (4-JL),跟SQR 刚好相反。如果JL=00(1 个转换),那么转换的顺序是从JSQR4[4:0]开始,而不是从JSQR1[4:0]开始,这个要注意,编程的时候不要搞错。当JL 等于4 时,跟SQR 一样。
4、触发源
通道选好了,转换的顺序也设置好了,那接下来就该开始转换了。ADC 转换可以由ADC 控制寄存器2: ADC_CR2 的ADON 这个位来控制,写1 的时候开始转换,写0 的时候停止转换,这个是最简单也是最好理解的开启ADC 转换的控制方式,理解起来没啥技术含量。
除了这种庶民式的控制方法,ADC 还支持触发转换,这个触发包括内部定时器触发和外部IO 触发。触发源有很多,具体选择哪一种触发源,由ADC 控制寄存器2:ADC_CR2 的EXTSEL[2:0] 和JEXTSEL[2:0]位来控制。EXTSEL[2:0]用于选择规则通道的触发源,JEXTSEL[2:0]用于选择注入通道的触发源。选定好触发源之后,触发源是否要激活,则由ADC 控制寄存器2:ADC_CR2 的EXTTRIG 和JEXTTRIG 这两位来激活。其中ADC3 的规则转换和注入转换的触发源与ADC1/2 的有所不同,在框图上已经表示出来。
5、数据寄存器
一切准备就绪后,ADC 转换后的数据根据转换组的不同,规则组的数据放在ADC_DR寄存器,注入组的数据放在JDRx。
规则数据寄存器
ADC 规则组数据寄存器ADC_DR 只有一个,是一个32 位的寄存器,低16 位在单ADC时使用,高16 位是在ADC1 中双模式下保存ADC2 转换的规则数据,双模式就是ADC1 和ADC2 同时使用。在单模式下,ADC1/2/3 都不使用高16 位。因为ADC 的精度是12 位,无论ADC_DR 的高16 或者低16 位都放不满,只能左对齐或者右对齐,具体是以哪一种方式存放,由ADC_CR2 的11 位ALIGN 设置。
规则通道可以有16 个这么多,可规则数据寄存器只有一个,如果使用多通道转换,那转换的数据就全部都挤在了DR 里面,前一个时间点转换的通道数据,就会被下一个时间点的另外一个通道转换的数据覆盖掉,所以当通道转换完成后就应该把数据取走,或者开启DMA 模式,把数据传输到内存里面,不然就会造成数据的覆盖。最常用的做法就是开启DMA 传输。
注入数据寄存器
ADC 注入组最多有4 个通道,刚好注入数据寄存器也有4 个,每个通道对应着自己的寄存器,不会跟规则寄存器那样产生数据覆盖的问题。ADC_JDRx 是32 位的,低16 位有效,高16 位保留,数据同样分为左对齐和右对齐,具体是以哪一种方式存放,由ADC_CR2 的11 位ALIGN 设置。
6、中断
转换结束中断
数据转换结束后,可以产生中断,中断分为三种:规则通道转换结束中断,注入转换通道转换结束中断,模拟看门狗中断。其中转换结束中断很好理解,跟我们平时接触的中断一样,有相应的中断标志位和中断使能位,我们还可以根据中断类型写相应配套的中断服务程序。
模拟看门狗中断
当被ADC 转换的模拟电压低于低阈值或者高于高阈值时,就会产生中断,前提是我们开启了模拟看门狗中断,其中低阈值和高阈值由ADC_LTR 和ADC_HTR 设置。例如我们设置高阈值是2.5V,那么模拟电压超过2.5V 的时候,就会产生模拟看门狗中断,反之低阈值也一样。
DMA 请求
规则和注入通道转换结束后,除了产生中断外,还可以产生DMA 请求,把转换好的数据直接存储在内存里面。要注意的是只有ADC1 和ADC3 可以产生DMA 请求。有关DMA请求需要配合《STM32F10X-中文参考手册》DMA控制器这一章节来学习。一般我们在使用ADC 的时候都会开启DMA 传输。
以上是关于STM32模数转换器ADC的主要内容,如果未能解决你的问题,请参考以下文章