ADC简介
1.
Analog-to-Digital Converter的缩写。指模/数转换器或者模拟/数字转换器。是指将连续变量的模拟信号转换为离散的数字信号的器件。典型的模拟数字转换器将模拟信号转换为表示一定比例电压值的数字信号。
2.
12位ADC是一种逐次逼近型模拟数字转换器。它有3个ADC控制器(ADC1,ADC2,ADC3),多达18个通道,可测量16个外部和2个内部--信号源(内部温度传感器,内部参考电压)。各通道的A/D转换可以单次、连续、扫描或间断模式执行。ADC的结果可以左对齐或右对齐方式存储在16位数据寄存器中。
3.
ADC的数字存储是12位的 也就是说转换器通过采集转换所得到的最大值是4095 “111111111111”=4095 二进制的12位可表示0-4095个数, 对应着所测电压的实际值,转换的电压范围是0v-3.3v的话,转换器就会把0v-3.3v平均分成4096份,设转换器所得到的值为x,所求电压值为y
ADC相关
左/右对齐
ADC得到的数据是12位精度的,但是数据存储在 16 位数据寄存器中,所以ADC的存储结果可以分为左对齐或右对齐方式(12位)
电压输入范围
ADC一般用于采集小电压,其输入值不能超过VDDA,即ADC输入范围:VREF- ≤ VIN ≤ VREF+。一般把VSSA和VREF- 接地, VREF+ 和 VDDA接3V3,那么ADC的输入范围是0~3.3V。
ADC通道
ADC输入通道
从ADCx_INT0-ADCx_INT15 对应三个ADC的16个外部通道,进行模拟信号转换 此外,还有两个内部通道:温度检测或者内部电压检测选择对应通道之后,便会选择对应GPIO引脚
注入通道,规则通道
模拟至数字转换器中有两个通道,注入通道,规则通道,规则通道至多16个,注入通道至多4个。规则通道:规则通道就是正常执行程序;注入通道:注入通道可以打断规则通道,如果在规则通道转换过程中有注入通道进行转换,那么就要先转换完注入通道,等注入通道转换完成后,再回到规则通道的转换流程(可以理解为中断模式)
ADC时钟
ADC预分频器的ADCCLK是ADC模块的时钟来源。STM32的ADC最大的转换速率为1MHz,也就是说最快转换时间为1us,为了保证ADC转换结果的准确性,ADC的时钟最好不超过14M
-
1选择外部时钟HSE 8MHz
-
2PLL锁相环倍频9倍
-
3系统时钟来源选择为PLL
-
4设置APB1分频器为 /2
-
5 设置ADC时钟分频 ,只能是6/8分频
即选择/6时,数值为12M(最大)
采样时间
TCONV = 采样时间+ 12.5个周期(当采样时间为1.5时,采样频率最大)
ADCCLK=14MHz时(最大),采样时间为1.5周期(最快)时,TCONV =1.5+12.5=14周期=1μs
外部触发转换
ADC 转换可以由 ADC_CR2 的ADON 这个位来控制,写1 的时候开始转换,写0 的时候停止转换当然,除了ADC_CR2寄存器的ADON位控制转换的开始与停止,还可以支持外部事件触发转换(比如定时器捕捉、EXTI线)包括内部定时器触发和外部IO触发。具体的触发源由ADC_CR2的EXTSEL[2:0]位(规则通道触发源 )和 JEXTSEL[2:0]位(注入通道触发源)控制。同时ADC3的触发源与ADC1/2的触发源有所不同.
中断
中断触发条件有三个,规则通道转换结束,注入通道转换结束,或者模拟看门狗状态位被设置时都能产生中断
-
转换结束中断:正常的ADC完成一次转换,进入中断
-
模拟看门狗中断 ,当被ADC转换的模拟电压值低于低阈值或高于高阈值时,便会产生中断。阈值的高低值由ADC_LTR和ADC_HTR配置 模拟看门狗,在ADC的应用中是为了防止读取到的电压值超量程或者低于量程
DMA
ADC还支持DMA触发,规则和注入通道转换结束后会产生DMA请求,用于将转换好的数据传输到内存。
关键点总结
ADC(STM32F10x)的主要特征:
-
12位逐次逼近型的模拟数字转换器。
-
最多带3个ADC控制器
-
最多支持18个通道,可最多测量16个外部和2个内部信号源。
-
支持单次和连续转换模式
-
转换结束,注入转换结束,和发生模拟看门狗事件时产生中断。
-
通道0到通道n的自动扫描模式 自动校准
-
采样间隔可以按通道编程
-
规则通道和注入通道均有外部触发选项
-
转换结果支持左对齐或右对齐方式存储在16位数据寄存器
-
ADC转换时间:最大转换速率 1us。(最大转换速度为1MHz( (1.5+12.5)* 1/14 = 1) -> 在ADCCLK=14M,采样周期为1.5个ADC时钟下得到)
-
ADC供电要求:2.4V-3.6V
-
ADC输入范围:VREF- ≤ VIN ≤ VREF+
转换模式
-
独立模式:不需要ADC同步或者只是用一个ADC的时候(独立模式模式下,双ADC不能同步)
-
单次转换模式 :ADC只执行一次转换(不会自动从头开始)
-
连续转换模式 :转换结束之后马上开始从头开始新的转换
-
扫描模式 :ADC扫描被规则通道和注入通道选中的所有通道,在每个组的每个通道上执行单次转换(不从头开始)。在每个转换结束时,自动转换到这一组的下一个通道。如果设置了CONT位(开启了连续 转换模式),转换不会在选择组的最后一个通道上停止,而是再次从选择组的第一个通道继续转换
-
间断模式 :每次需要先使用HAL_ADC_Start()(或HAL_ADC_Start_IT(),HAL_ADC_Start_DMA()启动转换(需要不断触发)。需要使用HAL_ADC_PollForConversion()等待转换完成,HAL_ADC_GetState()获取ADC转换状态(若返回值为HAL_OK说明转换完成),转换完成后使用HAL_ADC_GetValue()读取ADC原始值,读取完成后,使用HAL_ADC_Stop()停止转换,如需再次获取ADC数据,需重复执行上述步骤。
在所选转换通道循环,触发信号再启动新一轮的转换,直到转换完成。比如 ch0,ch1,ch4,ch5。 ch0转换完以后就会自动转换通道1,4,5直到转换完这个过程不能被打断。如果开启了连续转换模式,则会在转换完ch5之后开始新一轮的转换。它可以把0,1,4,5这四个通道进行分组。可以分成0,1一组,4,5一组。也可以每个通道单独配置为一组。如果开启连续模式,只需要使用一次HAL_ADC_Start(),开启转换,ADC会马不停蹄的电压转换成数字量,用户只需要调用HAL_ADC_GetValue(),读取ADC原始值
函数分解
开启ADC 3种模式( 查询模式 中断模式 DMA模式 )
• HAL_ADC_Start(&hadcx); //查询模式开启ADC • HAL_ADC_Start_IT(&hadcx); //中断轮询模式开启ADC • HAL_ADC_Start_DMA(&hadcx); //DMA模式开启AD
关闭ADC3种模式 ( 轮询模式 中断模式 DMA模式 )
• HAL_ADC_Stop() • HAL_ADC_Stop_IT() • HAL_ADC_Stop_DMA()
ADC校准函数 :
• HAL_ADCEx_Calibration_Start(&hadcx);
读取ADC转换值
• HAL_ADC_GetValue()
等待转换结束函数
• HAL_ADC_PollForConversion(&hadc1, 50); //50为最大等待时间
ADC中断回调函数
• HAL_ADC_ConvCpltCallback()
实战1:单通道 非扫描 连续转换 查询
1.设置RCC:设置高速外部时钟HSE (选择外部时钟源)
2.设置ADC通道(设置了ADC的引脚,才能够设置ADC的时钟分频)
3.配置时钟树(这里用的是外部晶振8MHz)
4.配置ADC
图例讲解:
-
ADCs_Common_Settings :ADC模式设置
Mode ADC_Mode_Independent:选择独立模式(因为这里就设置了一个ADC通道)
-
Data Alignment Right alignment :选择右对齐
Scan Conversion Mode Disable:不使能扫描模式(因为就一个ADC通道)
-
Continuous Conversion Mode DISABLE :不使能连续转换模式(不使能就是单次转换)
-
Discontinuous Conversion Mode DISABLE :不使能间断模式(因为就一个ADC通道)
-
Enable Regular Conversions ENABLE :使能规则通道(否则无法配置规则通道)
-
Number OF Conversion 1 :转换通道数为1(多个通道会自动使能扫描模式)
-
Extenal Trigger Conversion Source :外部触发转换源
Regular Conversion launched by software :规则的软件触发 调用函数触发即可
Timer X Capture Compare X event : 外部引脚触发,
Timer X Trigger Out event : 定时器通道输出触发 需要设置相应的定时器设置
-
Rank :转换顺序(这里就一个ADC通道,只需要修改采样时间)
-
ADC_lnjected_ConversionMode : 注入通道(与转换通道配置相同)
-
-
WahchDog : 看门狗
-
ADC转换结束中断
-
ADC的DMA传输
-
GPIO的模拟模式
具体参数配置(未配置中断和DMA)
后续配置
代码编写
-
步骤
启动ADC
等待EOC标志位
读取寄存器数据
-
设置变量
/* USER CODE BEGIN 0 */ uint16_t ADC_Value; /* USER CODE END 0 */
-
ADC初始化之后加上AD校准函数
MX_ADC1_Init(); HAL_ADCEx_Calibration_Start(&hadc1); //AD校准 MX_USART1_UART_Init(); /* USER CODE BEGIN 2 */
-
while中
HAL_ADC_Start(&hadc1); //启动ADC转换 HAL_ADC_PollForConversion(&hadc1, 50); //等待转换完成,50为最大等待时间,单位为ms if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC)) //判断ADC状态是不是完成了转换 { ADC_Value = HAL_ADC_GetValue(&hadc1); //获取AD值 printf("ADC1 Reading : %d \r\n",ADC_Value); printf("PA3 True Voltage value : %.4f \r\n",ADC_Value*3.3f/4096); printf("Z小旋测试\r\n"); } HAL_Delay(1000);
实战2:单通道 非扫描 连续转换 中断
-
步骤:
启动ADC,使能中断
EOC自动触发中断
在中断中读取寄存器数据
-
使能扫描模式
-
ADC全局中断
-
代码展示
实战3:单通道 非扫描 连续 DMA
-
步骤
启动ADC
配置DMA缓存区
读取缓存区数据
-
配置DMA
Stream:分配DMA流托管道(可以默认)
Direction:Peripheral To Memory(从外设到存储空间)
Priority:优先级(用到的不多,选low)
Mode:Circle(缓存区填满之后会重新更新)
Increment Address:选择Memory(地址不断增加)
Date Width:选择Half Word
"half word"是计算机存储数据的一种单元,它通常表示半个字(word)的大小。在大多数情况下,一个字(word)表示一个完整的数据单位,一个半字(half word)则表示数据的一半。一个半字通常由两个字节组成,相当于16位(2个字节)的数据单元。
注意:CubeIDE默认配置1.5Cycles的转换周期,导致DMA的触发干扰CPU导致串口无法正常发送数据(方法:加大转换周期)
-
代码展示
HAL_ADC_Start_DMA(&HADC1,(UINT32_T *)adc_value,40); //16位数据强转为32 启动后数值自动存到ADC_value里 //数据区的长度为40 while(1) { uint16_t i; for(i=0;i<40;i++) buf[i]=adc_value[i]*相关数值 }