Stm32之单ADC模数转换
1.单ADC总体框图:
-
由上图可以看出:Stm32 (大容量) 共有3个ADC转换器:其中ADC1有18个通道 (16个外部通道,2个内部:1个温度,1个V_refint 内部参考电压通道),ADC2 3则只有16个通道;
-
拥有三种可触发中断(EOC (规则通道转换完成) ,JEOC (注入通道转换完成),AWD (模拟看门狗阈值触发) )
-
改ADC为12位逐次比较性ADC,其最大速度为1us;所以输入时钟不可超过14Mhz*(具体见下)*
-
注入通道与规则通道:
注入通道可以理解为 ”ADC采集通道中的中断“ ,注意是ADC通道中,与Stm的中断没有关系,即在规则通道采集时,注入通道可以打断规则通道,使用ADC转换器进行AD转换。
注意:ADC检测的电压只能在0-3.3之间,不能是5V
2.寄存器:
-
ADC_SR :[4:0]主要是 开始转换 [4:3] 和转换完成 [2:1] 和模拟看门狗 [0] 的标志位;
-
ADC_CR1和ADC_CR2:
主要是 1.ADC模式的控制(包括双ADC和单ADC的单次,循环,扫描,间断模式)2.中断使能位,还有 3. 触发ADC事件的选择,及4. 数据对齐、ADC数据DMA输出的使能,和 5. 校准的控制.具体的控制位参考手册即可。
-
ADC_SMPR1和ADC_SMPR2:(Channel x Sample Register)
每3个位控制一个一个通道的采样周期;
-
ADC_JOFRx (x=1…4): ADC注入通道数据偏移寄存器x
-
ADC_HTR和ADC_LTR: ADC看门狗的高低阈值设置,均是12位。
-
ADC_SQR1 和ADC_SQR2和ADC_SQR2:(SeQuence Register)
除ADC_SQR1[23:20]决定规则通道序列的长度(即开启的通道个数)外,接下来的每5位 都是指第几个转换序列是那个通道;
-
ADC_JSQR: [21:20]决定注入通道序列的长度(即注入通道的个数,最多4个);
-
ADC_JDRx (x=1…4): 四个注入通道的数据存放寄存器;16位,12位数据是左对齐还是右对齐,由ADC_CR->ALIGN*([11]数据对齐位)*决定;
-
ADC_DR :规则通道的数据存放寄存器;高16位用于双ADC模式下的ADC2,低16位存放ADC1的转换数据,对齐方式如上。
-
有关ADC的采样时间:
需要根据晶振的频率和所需采样时间的大小,设置时钟的预分频系数:
- 12.5个周期是芯片的额外消耗。
- 其中14MHz需要由(Stm32ZET6中)是APB2,72MHz,故需要至少6分频 (即下图的ADC分频器)。
3.库函数操作:
-
常用库函数:
-
ADC_Init()输入结构体详解:
其中,单ADC的四种模式区别如下:
-
没有开启扫描模式的情况下,只能开启1个通道,因为只有一个ADC转换器(指单ADC1的情况),如果需要多通道,则必须等上一个通道扫描结束后重新配置通道转换,此时:
- 单次转换:(即ADC_CR2->CONT([0])被置为0的时候) 对这个通道,只转换一次;要在次转换需重新触发开启;
- 循环转换:(即ADC_CR2->CONT([0])被置为1的时候) 对这个通道,转换结束后,自动开启这个通道的下一次转换;
-
如果开启了扫描模式,可以对一组ADC通道按SQR1-3中设置好的序列逐个进行AD转换*(即扫描)*,此时:
-
单次转换:(即ADC_CR2->CONT([0])被置为0的时候) 对这组通道;按序读取AD转换完后,停止转换,等待再次触开启扫描;
-
循环转换:(即ADC_CR2->CONT([0])被置为1的时候) 对这组通道;按序读取AD转换完后,又从序列头开始,重新扫描;
-
-
间断模式:间断模式于扫描开启时很像,均是对一组多个通道进行逐个的AD转换;但其扫描检测的顺序不是按序列来,而是进行间断错开的分组,在这些分组*(小序列)*内进行扫描。(其单次与循环的效果与扫描模式开启时一样)。
-
用一个不是很恰当的比喻:
-
(无扫描)单次模式就像播放一首歌后自动暂停,要听歌得重新手动播放;
-
(无扫描)循环模式就像单曲循环;
-
单次扫描模式就像:顺序播放;播完整个歌单后自动暂停;
-
循环扫描模式就像:顺序播放的整个歌单,播完后自动循环;
-
间断模式就是随机播放了(不是很恰当)。
-
-
-
ADC转换基本步骤(原子的例子,单次(无扫描),软件触发)
-
官方的手册建议每次上电后要使用ADC前都要进行ADC校准:
原子的校准代码如下:(校准时只需复制即可)
ADC_ResetCalibration(ADC1); //使能复位校准 while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束 ADC_StartCalibration(ADC1); //开启AD校准 while(ADC_GetCalibrationStatus(ADC1)); //等待校准结束
-
注意:开启软件单次转换后,需等待其EOC标志位置1,即转换完成,才可以将值读出:(如下)
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能 while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束 return ADC_GetConversionValue(ADC1); //返回最近一次ADC1规则组的转换结果
对于库函数的使用,不要疏忽了以下两点:
-
不要忘了对规则通道的配置即
ADC_RegularChannelConfig(ADCx, ADC_Channel_y, 所排序列数, ADC_SampleTime_55Cycles5 (采样周期));因为初始化函数是对整个ADC转换器的初始化,并没有对通道进行相关的配置;
-
如果不启用外部通道开启AD转换,之后不要忘了开启软件转换即
ADC_SoftwareStartConvCmd(ADCx,ENABLE);
4.ADC_通道16,内部温度传感器
-
特性:
-
注意事项:
-
开启内部温度传感器时,除了使能对应的ADC1_ch16外 , 还需将ADC_CR2的TSVREFE位 ([23]) 打开 ( 置1);
-
由于ADC转换器的建立需要时间,所以同时设置ADC_CR2->ADON位,或者是启用校准,以缩短建立时间;
-
计算公式:
温 度 ( ° C ) = V 25 标 准 温 度 电 压 − V s e n s e ( 当 前 温 度 电 压 ) A v g _ S l o p e ( S t 公 司 给 出 的 电 压 . 温 度 曲 线 的 斜 率 ) + 25 温度(°C)=\frac{V_{25标准温度电压}-V_{sense(当前温度电压)}}{Avg\_Slope(St公司给出的电压.温度曲线的斜率) }+25 温度(°C)=Avg_Slope(St公司给出的电压.温度曲线的斜率)V25标准温度电压−Vsense(当前温度电压)+25
5.光强检测:
-
-
光敏二极管的检测与ADC检测一致,即通过ADC检测由光敏电阻引起的电压变化,从而检测周围环境的光强。
-
需要注意的是,光敏二极管的特性是:
- 在光弱的时候,光敏二极管于普通二极管一样,反向截止;
- 在光强的时候,光敏二极管会产生一个倒灌的电流,即二极管反向是可以有电流通过的,且光强越强,反向的导通性越好。
-
STM32ZET6原子精英板上的连接如下:
所以只要检测PF8即ADC3的通道6检测模拟电压的输入即可。
同时由于光敏二极管的特性,检测电压越大(最大3.3V),环境光强越弱。