44.1 初学者重要提示
STM32H7虽然支持差分,但不支持负压测量。
STM32H7的ADC采集通道体验快速通道Fast Channels和低速通道Slow Channels的区别,详情看本章2.12小节的电气特性。
STM32H7的ADC支持过采样,通过过采样技术可以做到26位分辨率。
ADC的专业术语诠释文档,推荐大家看看:
http://www.armbbs.cn/forum.php?mod=viewthread&tid=89414 。
44.2 ADC基础知识
ADC的几个关键知识点放在开头说:
STM32H7支持三路ADC,分别是ADC1,ADC2和ADC3。其中ADC1和ADC2可以组成双ADC模式,ADC3是独立的。这个跟STM32F4有所不同,F4的ADC1,ADC2和ADC3可以组成三ADC模式。
可以配置为16bit,14bit,12bit,10bit或者8bit分辨率,分辨率越低可以做到的采样率越高,因为转换时间要短。
每个ADC都支持20路采样通道。其中有6路快速通道和14路慢速通道,慢速和快速的区别主要是支持的最高采样率不同,慢速通道要比快速通道低。
支持单独输入和差分输入,其中差分输入不支持负压测量。
支持偏移校准和线性度校准,STM32F1的时候还带校准功能,到了STM32F4取消掉了,H7又恢复了校准功能。
支持规则通道和注入通道两种采样方式。
支持低功耗特性,系统在低频工作时保持最佳 ADC 性能(提供自动延迟插入)。
具有五条专用的内部通道,内部参考电压 VrefInt,内部温度传感器和VBAT 监测通道 VBAT/4都是连接到 ADC3。另外内部 DAC 通道 1 和通道 2,连接到 ADC2。
支持过采样,最高可以调整到26bit采样率。
ADC采样的数据可接入DFSDM数字滤波器进行后期处理。
每个ADC支持三路模拟看门狗。
44.2.1 ADC硬件框图
认识一个外设,最好的方式就是看他的框图,方便我们快速的了解ADC的基本功能,然后再看手册了解细节。框图如下所示(ADC1和ADC2):
相比前面章节讲解的外设,ADC的框图相对较复杂,因为涉及到控制寄存器较多。通过这个框图,我们可以得到如下信息:
ADC_INP[0:19]和ADC_INN[0:19]
INP是差分正向输入,INN是差分反向输入。
ADC_INP[0:5]和ADC_INN[0:5]是快速通道。
ADC_INP[6:19]和ADC_INN[6:19]是慢速通道。
adc_ext_trg[20:0]
共有21路触发用于规则通道,ADC1和ADC2共用的,而ADC3是独立的。
adc_jext_trg[20:0]
共有21路触发用于注入通道,ADC1和ADC2共用的,而ADC3是独立的。
adc_awd1,adc_awd2和adc_awd3
每个ADC都支持三个模拟看门狗。
adc_it
ADC中断。
adc_hclk
ADC的AHB时钟。
adc_ker_ck
ADC的内核时钟。
adc_dma
用于ADC的DMA请求。
dac_out1,dac_out2,Vsense,Vrefint和Vbat
五条专用的内部通道,内部参考电压 VrefInt,内部温度传感器和VBAT 监测通道 VBAT/4都是连接到 ADC3。另外内部 DAC 通道 1 和通道 2,连接到 ADC2。
44.2.2 ADC时钟源选择
ADC有两种时钟源可供选择,可以使用来自AHB总线的系统时钟(属于同步时钟,对应下面框图的adc_hclk),也可以使用PLL2,PLL3,HSE,HSI或者CSI时钟(属于异步时钟,对应下面框图的adc_ker_ck)。
结合上面的框图,ADC的时钟源要注意以下几个问题:
ADC1,ADC2和ADC3共用选择的时钟。
ADC的时钟源使用AHB时钟,且使用注入模式,那么在16bit,14bit,12bit或者10bit分辨率时,ADC的时钟不能超过AHB时钟的四分之一。8bit模式时,不能超过AHB时钟的三分之一。
选择AHB时钟的话,ADC的配置中提供了不分频,二分频和四分频。如果选择了不分频,那么配置AHB的时钟输出时也不可以设置分频,即RCC的CFGR寄存器配置不可分频。
如果使用PLL时钟,运行期间要一直开启,不可关闭。
最后特别注意一点,如果STM32H7工作在400MHz,ADC使用AHB做时钟源,超频是不可避免的。ADC1和ADC2位于200MHz的AHB1总线时钟,而ADC3位于200MHz的AHB4下。根据上面的框图,ADCx_CCR寄存器的CKMODE最高可以选择4分频,那么就是50MHz,而ADC数据手册限制最高是36MHz,也就是说已经超频了。
使用AHB作为时钟源的好处就是定时器等外部触发方式的效果好。
第44章 STM32H7的ADC基础知识和HAL库API
本章节为大家讲解ADC(Analog-to-digital converters,模数转换器),极具项目使用价值,因为STM32H7的ADC已经高达16位分辨率,支持3.6Msps采样率。
44.1 初学者重要提示
44.2 ADC基础知识
44.3 ADC的HAL库用法
44.4 源文件stm32h7xx_hal_adc.c
44.5 总结
44.1 初学者重要提示
STM32H7虽然支持差分,但不支持负压测量。
STM32H7的ADC采集通道体验快速通道Fast Channels和低速通道Slow Channels的区别,详情看本章2.12小节的电气特性。
STM32H7的ADC支持过采样,通过过采样技术可以做到26位分辨率。
ADC的专业术语诠释文档,推荐大家看看:
http://www.armbbs.cn/forum.php?mod=viewthread&tid=89414 。
44.2 ADC基础知识
ADC的几个关键知识点放在开头说:
STM32H7支持三路ADC,分别是ADC1,ADC2和ADC3。其中ADC1和ADC2可以组成双ADC模式,ADC3是独立的。这个跟STM32F4有所不同,F4的ADC1,ADC2和ADC3可以组成三ADC模式。
可以配置为16bit,14bit,12bit,10bit或者8bit分辨率,分辨率越低可以做到的采样率越高,因为转换时间要短。
每个ADC都支持20路采样通道。其中有6路快速通道和14路慢速通道,慢速和快速的区别主要是支持的最高采样率不同,慢速通道要比快速通道低。
支持单独输入和差分输入,其中差分输入不支持负压测量。
支持偏移校准和线性度校准,STM32F1的时候还带校准功能,到了STM32F4取消掉了,H7又恢复了校准功能。
支持规则通道和注入通道两种采样方式。
支持低功耗特性,系统在低频工作时保持最佳 ADC 性能(提供自动延迟插入)。
具有五条专用的内部通道,内部参考电压 VrefInt,内部温度传感器和VBAT 监测通道 VBAT/4都是连接到 ADC3。另外内部 DAC 通道 1 和通道 2,连接到 ADC2。
支持过采样,最高可以调整到26bit采样率。
ADC采样的数据可接入DFSDM数字滤波器进行后期处理。
每个ADC支持三路模拟看门狗。
44.2.1 ADC硬件框图
认识一个外设,最好的方式就是看他的框图,方便我们快速的了解ADC的基本功能,然后再看手册了解细节。框图如下所示(ADC1和ADC2):
相比前面章节讲解的外设,ADC的框图相对较复杂,因为涉及到控制寄存器较多。通过这个框图,我们可以得到如下信息:
ADC_INP[0:19]和ADC_INN[0:19]
INP是差分正向输入,INN是差分反向输入。
ADC_INP[0:5]和ADC_INN[0:5]是快速通道。
ADC_INP[6:19]和ADC_INN[6:19]是慢速通道。
adc_ext_trg[20:0]
共有21路触发用于规则通道,ADC1和ADC2共用的,而ADC3是独立的。
adc_jext_trg[20:0]
共有21路触发用于注入通道,ADC1和ADC2共用的,而ADC3是独立的。
adc_awd1,adc_awd2和adc_awd3
每个ADC都支持三个模拟看门狗。
adc_it
ADC中断。
adc_hclk
ADC的AHB时钟。
adc_ker_ck
ADC的内核时钟。
adc_dma
用于ADC的DMA请求。
dac_out1,dac_out2,Vsense,Vrefint和Vbat
五条专用的内部通道,内部参考电压 VrefInt,内部温度传感器和VBAT 监测通道 VBAT/4都是连接到 ADC3。另外内部 DAC 通道 1 和通道 2,连接到 ADC2。
44.2.2 ADC时钟源选择
ADC有两种时钟源可供选择,可以使用来自AHB总线的系统时钟(属于同步时钟,对应下面框图的adc_hclk),也可以使用PLL2,PLL3,HSE,HSI或者CSI时钟(属于异步时钟,对应下面框图的adc_ker_ck)。
结合上面的框图,ADC的时钟源要注意以下几个问题:
ADC1,ADC2和ADC3共用选择的时钟。
ADC的时钟源使用AHB时钟,且使用注入模式,那么在16bit,14bit,12bit或者10bit分辨率时,ADC的时钟不能超过AHB时钟的四分之一。8bit模式时,不能超过AHB时钟的三分之一。
选择AHB时钟的话,ADC的配置中提供了不分频,二分频和四分频。如果选择了不分频,那么配置AHB的时钟输出时也不可以设置分频,即RCC的CFGR寄存器配置不可分频。
如果使用PLL时钟,运行期间要一直开启,不可关闭。
最后特别注意一点,如果STM32H7工作在400MHz,ADC使用AHB做时钟源,超频是不可避免的。ADC1和ADC2位于200MHz的AHB1总线时钟,而ADC3位于200MHz的AHB4下。根据上面的框图,ADCx_CCR寄存器的CKMODE最高可以选择4分频,那么就是50MHz,而ADC数据手册限制最高是36MHz,也就是说已经超频了。
使用AHB作为时钟源的好处就是定时器等外部触发方式的效果好。
#define ADC_EXTERNALTRIG_T1_CC1 ((uint32_t)0x00000000)
#define ADC_EXTERNALTRIG_T1_CC2 ((uint32_t)ADC_CFGR_EXTSEL_0)
#define ADC_EXTERNALTRIG_T1_CC3 ((uint32_t)ADC_CFGR_EXTSEL_1)
#define ADC_EXTERNALTRIG_T2_CC2 ((uint32_t)(ADC_CFGR_EXTSEL_1 | ADC_CFGR_EXTSEL_0))
#define ADC_EXTERNALTRIG_T3_TRGO ((uint32_t)ADC_CFGR_EXTSEL_2)
#define ADC_EXTERNALTRIG_T4_CC4 ((uint32_t)(ADC_CFGR_EXTSEL_2 | ADC_CFGR_EXTSEL_0))
#define ADC_EXTERNALTRIG_EXT_IT11 ((uint32_t)(ADC_CFGR_EXTSEL_2 | ADC_CFGR_EXTSEL_1))
#define ADC_EXTERNALTRIG_T8_TRGO ((uint32_t)(ADC_CFGR_EXTSEL_2 | ADC_CFGR_EXTSEL_1 |
ADC_CFGR_EXTSEL_0))
#define ADC_EXTERNALTRIG_T8_TRGO2 ((uint32_t) ADC_CFGR_EXTSEL_3)
#define ADC_EXTERNALTRIG_T1_TRGO ((uint32_t)(ADC_CFGR_EXTSEL_3 | ADC_CFGR_EXTSEL_0))
#define ADC_EXTERNALTRIG_T1_TRGO2 ((uint32_t)(ADC_CFGR_EXTSEL_3 | ADC_CFGR_EXTSEL_1))
#define ADC_EXTERNALTRIG_T2_TRGO ((uint32_t)(ADC_CFGR_EXTSEL_3 | ADC_CFGR_EXTSEL_1 | ADC_CFGR_EXTSEL_0))
#define ADC_EXTERNALTRIG_T4_TRGO ((uint32_t)(ADC_CFGR_EXTSEL_3 | ADC_CFGR_EXTSEL_2))
#define ADC_EXTERNALTRIG_T6_TRGO ((uint32_t)(ADC_CFGR_EXTSEL_3 | ADC_CFGR_EXTSEL_2 | ADC_CFGR_EXTSEL_0))
#define ADC_EXTERNALTRIG_T15_TRGO ((uint32_t)(ADC_CFGR_EXTSEL_3 | ADC_CFGR_EXTSEL_2 | ADC_CFGR_EXTSEL_1))
#define ADC_EXTERNALTRIG_T3_CC4 ((uint32_t)(ADC_CFGR_EXTSEL_3 | ADC_CFGR_EXTSEL_2 | ADC_CFGR_EXTSEL_1 | ADC_CFGR_EXTSEL_0))
#define ADC_EXTERNALTRIG_HR1_ADCTRG1 ((uint32_t) ADC_CFGR_EXTSEL_4)
#define ADC_EXTERNALTRIG_HR1_ADCTRG3 ((uint32_t) (ADC_CFGR_EXTSEL_4 | ADC_CFGR_EXTSEL_0))
#define ADC_EXTERNALTRIG_LPTIM1_OUT ((uint32_t) (ADC_CFGR_EXTSEL_4 | ADC_CFGR_EXTSEL_1))
#define ADC_EXTERNALTRIG_LPTIM2_OUT ((uint32_t) (ADC_CFGR_EXTSEL_4 | ADC_CFGR_EXTSEL_1| ADC_CFGR_EXTSEL_0))
#define ADC_EXTERNALTRIG_LPTIM3_OUT ((uint32_t) (ADC_CFGR_EXTSEL_4 | ADC_CFGR_EXTSEL_2))
注入通道支持的外部触发源如下:
#define ADC_EXTERNALTRIGINJEC_T1_TRGO ((uint32_t)0x00000000)
#define ADC_EXTERNALTRIGINJEC_T1_CC4 ((uint32_t)ADC_JSQR_JEXTSEL_0)
#define ADC_EXTERNALTRIGINJEC_T2_TRGO ((uint32_t)ADC_JSQR_JEXTSEL_1)
#define ADC_EXTERNALTRIGINJEC_T2_CC1 ((uint32_t)(ADC_JSQR_JEXTSEL_1 | ADC_JSQR_JEXTSEL_0))
#define ADC_EXTERNALTRIGINJEC_T3_CC4 ((uint32_t)ADC_JSQR_JEXTSEL_2)
#define ADC_EXTERNALTRIGINJEC_T4_TRGO ((uint32_t)(ADC_JSQR_JEXTSEL_2 | ADC_JSQR_JEXTSEL_0))
#define ADC_EXTERNALTRIGINJEC_EXT_IT15 ((uint32_t)(ADC_JSQR_JEXTSEL_2 | ADC_JSQR_JEXTSEL_1))
#define ADC_EXTERNALTRIGINJEC_T8_CC4 ((uint32_t)(ADC_JSQR_JEXTSEL_2 | ADC_JSQR_JEXTSEL_1 |
ADC_JSQR_JEXTSEL_0))
#define ADC_EXTERNALTRIGINJEC_T1_TRGO2 ((uint32_t)ADC_JSQR_JEXTSEL_3)
#define ADC_EXTERNALTRIGINJEC_T8_TRGO ((uint32_t)(ADC_JSQR_JEXTSEL_3 | ADC_JSQR_JEXTSEL_0))
#define ADC_EXTERNALTRIGINJEC_T8_TRGO2 ((uint32_t)(ADC_JSQR_JEXTSEL_3 | ADC_JSQR_JEXTSEL_1))
#define ADC_EXTERNALTRIGINJEC_T3_CC3 ((uint32_t)(ADC_JSQR_JEXTSEL_3 | ADC_JSQR_JEXTSEL_1 | ADC_JSQR_JEXTSEL_0))