目录
什么是ADC
概念
3个ADC控制器
ADC的转换模式:
模式讲解
工作框图
ADC时钟
中断
ADC的主要特征
ADC配置
ADC单通道采样
使用连续采样模式打印电压值
中断方式读取电压值
DMA方式读取电压值
ADC DMA方式多通道采样
三通道,查询阻塞模式
Analog-to-Digital Converter的缩写。指模/数转换器或者模拟/数字转换器。是指将连续变量的模拟信号转换为离散的数字信号的器件。
典型的模拟数字转换器将模拟信号转换为表示一定比例电压值的数字信号。
简单地说就是将模拟电压值,转换成对应的肉眼可读数值
12位ADC是一种逐次逼近型模拟数字转换器。它有,3个ADC控制器,多达18个通道,可测量16个外部和2个内部信号源。各通道的A/D转换可以单次、连续、扫描或间断模式执行。ADC的结果可以左对齐或右对齐方式存储在16位数据寄存器中。
12位模拟数字转换器
就是ADC的数字存储是12位的 也就是说转换器通过采集转换所得到的最大值是4095 “111111111111”=4095 二进制的12位可表示0-4095个数, 对应着所测电压的实际值,转换的电压范围是0v-3.3v的话,转换器就会把0v-3.3v平均分成4096份。设转换器所得到的值为x,所求电压值为y。
同理,可以理解8位精度和10位精度
具体的转压范围下面我们会讲
就是说STM32一共有3个ADC ADC1,ADC2,ADC3
STM32 的ADC 多达18 个通道,
16个外部通道和2个内部信号源 具体是哪一个IO 口可以从手册查询到
STM32F10x系列芯片ADC通道和引脚对应关系 :
16个外部通道:芯片上有16个引脚是可以接到模拟电压上进行电压值检测的
2个内部信号源 : 一个是内部温度传感器,一个是内部参考电压
一共支持23个引脚支持ADC,包括21个外部和2个内部信号源
1 单次转换模式:ADC只执行一次转换;
2 连续转换模式:转换结束之后马上开始新的转换;
3 扫描模式:ADC扫描被规则通道和注入通道选中的所有通道,在每个组的每个通道上执行单次转换。在每个转换结束时,这一组的下一个通道被自动转换。如果设置了CONT位(开启了连续 转换模式),转换不会在选择组的最后一个通道上停止,而是再次从选择组的第一个通道继续转换。
4 间断模式:触发一次,转换一个通道,在触发,在转换。在所选转换通道循环,由触发信号启动新一轮的转换,直到转换完成为止。
扫描模式简单的说是一次对所有所选中的通道进行转换,比如开了ch0,ch1,ch4,ch5。 ch0转换完以后就会自动转换通道1,4,5直到转换完这个过程不能被打断。如果开启了连续转换模式,则会在转换完ch5之后开始新一轮的转换。
这就引入了间断模式,可以说是对扫描模式的一种补充。它可以把0,1,4,5这四个通道进行分组。可以分成0,1一组,4,5一组。也可以每个通道单独配置为一组。这样每一组转换之前都需要先触发一次。
ADC单通道:
只进行一次ADC转换:配置为“单次转换模式”,扫描模式关闭。ADC通道转换一次后,就停止转换。等待再次使能后才会重新转换
进行连续ADC转换:配置为“连续转换模式”,扫描模式关闭。ADC通道转换一次后,接着进行下一次转换,不断连续。
ADC多通道:
只进行一次ADC转换:配置为“单次转换模式”,扫描模式使能。ADC的多个通道,按照配置的顺序依次转换一次后,就停止转换。等待再次使能后才会重新转换
进行连续ADC转换:配置为“连续转换模式”,扫描模式使能。ADC的多个通道,按照配置的顺序依次转换一次后,接着进行下一次转换,不断连续。
也就是:多通道必须使能扫描模式
上面转换模式介绍一部分为转自他人
左对齐或右对齐
因为ADC得到的数据是12位精度的,但是数据存储在 16 位数据寄存器中,所以ADC的存储结果可以分为左对齐或右对齐方式(12位)
ADC的工作框图
间断/连续模式:
1.如果开启间断模式,每次需要先使用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数据,需重复执行上述步骤。
2.间断模式的缺点很明显:麻烦~ 优点就是节省系统资源,安全性更高,而间断模式会不断抛出DMA,IT中断,导致系统安全性降低~
3.如果开启连续模式,只需要使用一次HAL_ADC_Start(),开启转换,ADC会马不停蹄的电压转换成数字量,用户只需要调用HAL_ADC_GetValue(),读取ADC原始值
4.连续模式的优缺点和间断模式真好相反~
扫描模式(开启/关闭)
1.如果设置了多个ADC转换通道(不是勾选的通道数量,是Number Of Conversion里配置的数量),扫描模式自动开启,且无法关闭,如果只有一个转换通道,则扫描模式默认关闭,且无法开启。
2.假设开启了扫描模式,且RANK1 RANK2 RANK3分别对应IN3 IN2 IN1 通道,则转换一次通道顺序为IN3 IN2 IN1
接下来我们介绍下ADC的工作框图,让您有个更直白地了解,涉及到寄存器的一些部分不再详细讲解
ADC一般用于采集小电压,其输入值不能超过VDDA,即ADC输入范围:VREF- ≤ VIN ≤ VREF+。具体的定义见上图。
一般把VSSA和VREF- 接地, VREF+ 和 VDDA接3V3,那么ADC的输入范围是0~3.3V。
2ADC输入通道
从ADCx_INT0-ADCx_INT15 对应三个ADC的16个外部通道,进行模拟信号转换 此外,还有两个内部通道:温度检测或者内部电压检测
选择对应通道之后,便会选择对应GPIO引脚,相关的引脚定义和描述可在开发板的数据手册里找
3注入通道,规则通道
我们看到,在选择了ADC的相关通道引脚之后,在模拟至数字转换器中有两个通道,注入通道,规则通道,
规则通道至多16个,注入通道至多4个
规则通道:
规则通道相当于你正常运行的程序,看它的名字就可以知道,很规矩,就是正常执行程序
注入通道:
注入通道可以打断规则通道,听它的名字就知道不安分,如果在规则通道转换过程中,有注入通道进行转换,那么就
要先转换完注入通道,等注入通道转换完成后,再回到规则通道的转换流程
图:正点原子
你可以通过上图有一个更直观的认识,可以简单地把注入通道理解为中断形式,可以更好理解
图中的ADC预分频器的ADCCLK是ADC模块的时钟来源。通常,由时钟控制器提供的ADCCLK时钟和PCLK2(APB2时钟)同步。RCC控制器为ADC时钟提供一个专用的可编程预分频器。 分频因子由RCC_CFGR的ADCPRE[1:0]配置,可配置2/4/6/8分频
STM32的ADC最大的转换速率为1MHz,也就是说最快转换时间为1us,为了保证ADC转换结果的准确性,ADC的时钟最好不超过14M。T = 采样时
间 + 12.5个周期,其中1周期为1/ADCCLK
外部触发转换
ADC 转换可以由ADC 控制寄存器2: ADC_CR2 的ADON 这个位来控制,写1 的时候开始转换,写0 的时候停止转换
当然,除了ADC_CR2寄存器的ADON位控制转换的开始与停止,还可以支持外部事件触发转换(比如定时器捕捉、EXTI线)
包括内部定时器触发和外部IO触发。具体的触发源由ADC_CR2的EXTSEL[2:0]位(规则通道触发源 )和 JEXTSEL[2:0]位(注入通道触发源)控制。
同时ADC3的触发源与ADC1/2的触发源有所不同,上图已经给出,
具体查看第五部分框图即可理解
中断触发条件有三个,规则通道转换结束,注入通道转换结束,或者模拟看门狗状态位被设置时都能产生中断,转换结束中断就是正常的ADC完成一次转换,进入中断,这个很好理解
转换结束中断就是正常的ADC完成一次转换,进入中断,这个很好理解
模拟看门狗中断
,当被ADC转换的模拟电压值低于低阈值或高于高阈值时,便会产生中断。阈值的高低值由ADC_LTR和ADC_HTR配置
模拟看门狗,听他的名字就知道,在ADC的应用中是为了防止读取到的电压值超量程或者低于量程
DMA
同时ADC还支持DMA触发,规则和注入通道转换结束后会产生DMA请求,用于将转换好的数据传输到内存。
注意,只有ADC1和ADC3可以产生DMA请求
因为涉及到DMA传输,所以这里我们不再详细介绍,之后几节会更新DMA,一般我们在使用ADC 的时候都会开启DMA 传输。
STM32F10x ADC特点
12位逐次逼近型的模拟数字转换器。
最多带3个ADC控制器
最多支持18个通道,可最多测量16个外部和2个内部信号源。
支持单次和连续转换模式
转换结束,注入转换结束,和发生模拟看门狗事件时产生中断。
通道0到通道n的自动扫描模式 自动校准
采样间隔可以按通道编程
规则通道和注入通道均有外部触发选项
转换结果支持左对齐或右对齐方式存储在16位数据寄存器
ADC转换时间:最大转换速率 1us。(最大转换速度为1MHz,在ADCCLK=14M,采样周期为1.5个ADC时钟下得到。)
ADC供电要求:2.4V-3.6V
ADC输入范围:VREF- ≤ VIN ≤ VREF+
STM32F4x ADC特点
F1与F4区别
F4的ADC支持12位,10位,8位和6位精度,F1只支持12位
F1和F4都具有3个ADC,F1可提供21个输入通道,F4可以提供24个输入通道。
F1的ADC最大采样频率为1Msps,2路交替采样可到2Msps(F1不支持3路交替采样)。F4的ADC最大采样频率为2.4Msps,3路交替采样可到7.2Msps。
分辨率,读出的数据的长度,如8位就是最大值为255的意思,即范围[0,255],12位就是最大值为4096,即范围[0,4096]
l 通道,ADC输入引脚,通常一个ADC控制器控制多个通道,如果需要多通道的话,就得进行每个通道扫描了。
l ADC DMA功能,DMA是内存到内存或内存到存储的直接映射,数据不用经过单片机处理器而直接由硬件进行数据的传递。方便直接将读取的ADC值放到内存变量中。
ADC芯片通常有正参考电压和负参考电压,通常正参考电压连接到VCC,负参考电压连接到GND
在STM32中ADC还可以用于采集芯片的温度、RTC供电电压
一般来说,采样时间越长,结果越准确,采样时间要更具ADC的时钟周期和ADC通道设置的采样周期计算,如STM32F103C8T6配置的ADC时钟周期为12MHZ,采样周期配置的是239.5 Cycles。
ADCs_Common_Settings ADC模式设置
Mode ADC_Mode_Independent
这里设置为独立模式
独立模式模式下,双ADC不能同步,每个ADC接口独立工作。所以如果不需要ADC同步或者只是用了一个ADC的时候,应该设成独立模式,多个ADC同时使用时会有其他模式,如双重ADC同步模式,两个ADC同时采集一个或多个通道,可以提高采样率
Data Alignment (数据对齐方式): 右对齐/左对齐
这个上方有讲解,数据的左右对齐
Scan Conversion Mode( 扫描模式 ) :
如果只是用了一个通道的话,DISABLE就可以了(也只能DISABLE),如果使用了多个通道的话,会自动设置为ENABLE。 就是是否开启扫描模式
Continuous Conversion Mode(连续转换模式)
设置为ENABLE,即连续转换。如果设置为DISABLE,则是单次转换。两者的区别在于连续转换直到所有的数据转换完成后才停止转换,而单次转换则只转换一次数据就停止,要再次触发转换才可以进行转换
Discontinuous Conversion Mode(间断模式)
因为我们只用到了1个ADC,所以这个直接不使能即可
规则通道设置
Enable Regular Conversions (启用常规转换模式)
使能 否则无发进行下方配置
Number OF Conversion(转换通道数) 1
用到几个通道就设置为几
多个通道自动使能扫描模式
多个通道时会有多个Rank,可以设定每个通道的转换顺序
ADC总转换时间如下计算:
TCONV = 采样时间+ 12.5个周期
当ADCCLK=14MHz(最大),采样时间为1.5周期(最快)时,TCONV =1.5+12.5=14周期=1μs。
因此,ADC的最小采样时间1us(ADC时钟=14MHz,采样周期为1.5周期下得到)
扫描模式(开启/关闭)
1.如果设置了多个ADC转换通道(不是勾选的通道数量,是Number Of Conversion里配置的数量),扫描模式自动开启,且无法关闭,如果只有一个转换通道,则扫描模式默认关闭,且无法开启。
2.假设开启了扫描模式,且RANK1 RANK2 RANK3分别对应IN3 IN2 IN1 通道,则转换一次通道顺序为IN3 IN2 IN1
轮询方式单通道ADC读取电压
中断方式单通道ADC读取电压
DMA方式单通道ADC读取电压
DMA方式多通道ADC读取电压
三通道,查询阻塞模式
1.
轮询方式单通道ADC读取电压
配置串口,时钟树,打开中断,使能printf(串口里面有讲)
浮点型定义需要自己开启
Project -- C/C++ -- Settings --MCU Settings
HAL_Delay(500);
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 100);
ADC_Value = HAL_ADC_GetValue(&hadc1); //获取AD
HAL_ADC_Stop(&hadc1);
voltage=ADC_Value*(3.3/4096);
printf("ADC1 Reading : %f \r\n",voltage);
HAL_Delay(500);
// HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 100);
ADC_Value = HAL_ADC_GetValue(&hadc1); //获取AD
// HAL_ADC_Stop(&hadc1);
voltage=ADC_Value*(3.3/4096);
printf("ADC1 Reading : %f \r\n",voltage);
(模式:连续模式 非扫描模式)
使能ADC全局中断
(模式:连续模式 非扫描模式)
配置DMA
增大转换周期
CubeIDE默认配置1.5Cycles的转换周期,导致DMA触发的中断干扰CPU导致串口无法正常发送数据。
解决方法有二,一者取消DMA中断,但CubeIDE 图形化配置中 DMA全局中断无法取消,网上有很多大佬通过修改DMA初始化代码取消DMA中断,这样既麻烦还会影响到其他需要DMA的外设,所以博主采取第二种方法,即增大转换时间
HAL_ADC_Start_DMA(&hadc1,&ADC_Value,1);
HAL_Delay(500);
voltage=ADC_Value*(3.3/4096);
printf("ADC1 Reading : %f \r\n",voltage);
HAL_ADC_Start_DMA(&hadc1,adcdata,2);
HAL_Delay(500);
voltageCH2=adcdata[0]*(3.3/4096);
voltageCH3=adcdata[1]*(3.3/4096);
printf("ADC1 Reading : %f \r\n",voltageCH2);
printf("ADC1 Reading : %f \r\n",voltageCH3);
while里面写
uint16_t dong_get_adc()
{
//启动ADC1
HAL_ADC_Start(&hadc1);
//等待ADC转换完成,超时为100ms
HAL_ADC_PollForConversion(&hadc1,100);
//判断ADC是否转换成功
if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1),HAL_ADC_STATE_REG_EOC)){
//读取值
return HAL_ADC_GetValue(&hadc1);
}
return 0;
}
for(uint8_t i=0;i<3;i++)
{
//分别存放通道123的ADC值
ADC_Value[i]=dong_get_adc();
}
a1=ADC_Value[0]*(3.3/4096);
a2=ADC_Value[1]*(3.3/4096);
a3=ADC_Value[2]*(3.3/4096);
printf("ADC1 Reading : %f \r\n",a1);
printf("ADC2 Reading : %f \r\n",a2);
printf("ADC3 Reading : %f \r\n",a3);
HAL_Delay(999);